diff --git a/BUILD.gn b/BUILD.gn index e1f9e9f3..e2df773a 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -198,10 +198,10 @@ "//mojo/edk/test:mojo_public_system_unittests", "//net:net_perftests", "//storage:storage_unittests", + "//third_party/WebKit/Source/controller:webkit_unit_tests", "//third_party/WebKit/Source/platform:blink_platform_unittests", "//third_party/WebKit/Source/platform/heap:blink_heap_unittests", "//third_party/WebKit/Source/platform/wtf:wtf_unittests", - "//third_party/WebKit/Source/web:webkit_unit_tests", "//third_party/angle/src/tests:angle_end2end_tests", "//third_party/angle/src/tests:angle_unittests", "//third_party/angle/src/tests:angle_white_box_tests",
diff --git a/DEPS b/DEPS index a0847ba..95500fb9 100644 --- a/DEPS +++ b/DEPS
@@ -40,7 +40,7 @@ # 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': '0ac06e47269a40c177747310a613d213c95d1d6d', + 'skia_revision': 'c94ff43cf846cf470b7d46e1d2aaa1724c5cc948', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -60,11 +60,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '4d3efedb10ce60bdb7847336eba0360fdc9af9d3', + 'swiftshader_revision': '64ed0d75e58d5b6b12bdb30ae6b83a878a4142a6', # 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': '78fc9aa402409f3fcd8dc1f458e67798cb3b483e', + 'pdfium_revision': '31d706bd8122830a15c574ba461e8f1a41427b9c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '6065b9274f907f556afab696d631dd816e325ff8', + 'catapult_revision': '9d0d9fc4552beb4f7d5eefb4b2ecde33f58bd421', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other.
diff --git a/WATCHLISTS b/WATCHLISTS index 8798744..34233661 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -2280,7 +2280,6 @@ 'views': ['tfarina@chromium.org'], 'virtual_keyboard': ['blakeo+virtualkb@chromium.org', 'dfaden+virtualkb@google.com', - 'groby+virtualkb@chromium.org', 'oka+watchvk@chromium.org', 'yhanada+watchvk@chromium.org'], 'virtual_reality': ['feature-vr-reviews@chromium.org'],
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn index 6a6e637..3e074f1 100644 --- a/android_webview/BUILD.gn +++ b/android_webview/BUILD.gn
@@ -101,7 +101,7 @@ java_cpp_enum("aw_safe_browsing_action") { sources = [ - "browser/aw_safe_browsing_resource_throttle.h", + "browser/aw_url_checker_delegate_impl.h", ] } @@ -521,6 +521,8 @@ "browser/aw_settings.h", "browser/aw_ssl_host_state_delegate.cc", "browser/aw_ssl_host_state_delegate.h", + "browser/aw_url_checker_delegate_impl.cc", + "browser/aw_url_checker_delegate_impl.h", "browser/aw_web_contents_delegate.cc", "browser/aw_web_contents_delegate.h", "browser/aw_web_contents_view_delegate.cc",
diff --git a/android_webview/browser/aw_browser_manifest_overlay.json b/android_webview/browser/aw_browser_manifest_overlay.json index 8356644..c161781f 100644 --- a/android_webview/browser/aw_browser_manifest_overlay.json +++ b/android_webview/browser/aw_browser_manifest_overlay.json
@@ -1,6 +1,13 @@ { "name": "content_browser", "interface_provider_specs": { + "service_manager:connector": { + "provides": { + "renderer": [ + "safe_browsing::mojom::SafeBrowsing" + ] + } + }, "navigation:frame": { "provides": { "renderer": [
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc index 6cf4a0f0..15820f4 100644 --- a/android_webview/browser/aw_content_browser_client.cc +++ b/android_webview/browser/aw_content_browser_client.cc
@@ -16,6 +16,7 @@ #include "android_webview/browser/aw_printing_message_filter.h" #include "android_webview/browser/aw_quota_permission_context.h" #include "android_webview/browser/aw_settings.h" +#include "android_webview/browser/aw_url_checker_delegate_impl.h" #include "android_webview/browser/aw_web_contents_view_delegate.h" #include "android_webview/browser/net/aw_url_request_context_getter.h" #include "android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h" @@ -30,6 +31,7 @@ #include "base/base_paths_android.h" #include "base/base_switches.h" #include "base/command_line.h" +#include "base/feature_list.h" #include "base/files/scoped_file.h" #include "base/json/json_reader.h" #include "base/memory/ptr_util.h" @@ -38,6 +40,8 @@ #include "components/cdm/browser/cdm_message_filter_android.h" #include "components/crash/content/browser/crash_dump_observer_android.h" #include "components/navigation_interception/intercept_navigation_delegate.h" +#include "components/safe_browsing/browser/browser_url_loader_throttle.h" +#include "components/safe_browsing/browser/mojo_safe_browsing_impl.h" #include "components/spellcheck/spellcheck_build_features.h" #include "content/public/browser/browser_message_filter.h" #include "content/public/browser/browser_thread.h" @@ -50,9 +54,11 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" #include "content/public/common/service_names.mojom.h" #include "content/public/common/url_constants.h" +#include "content/public/common/url_loader_throttle.h" #include "content/public/common/web_preferences.h" #include "device/geolocation/access_token_store.h" #include "device/geolocation/geolocation_delegate.h" @@ -551,4 +557,51 @@ render_frame_host); } +void AwContentBrowserClient::ExposeInterfacesToRenderer( + service_manager::BinderRegistry* registry, + content::AssociatedInterfaceRegistry* associated_registry, + content::RenderProcessHost* render_process_host) { + if (base::FeatureList::IsEnabled(features::kNetworkService)) { + registry->AddInterface( + base::Bind( + &safe_browsing::MojoSafeBrowsingImpl::MaybeCreate, + render_process_host->GetID(), + base::Bind( + &AwContentBrowserClient::GetSafeBrowsingUrlCheckerDelegate, + base::Unretained(this))), + BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)); + } +} + +std::vector<std::unique_ptr<content::URLLoaderThrottle>> +AwContentBrowserClient::CreateURLLoaderThrottles( + const base::Callback<content::WebContents*()>& wc_getter) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(base::FeatureList::IsEnabled(features::kNetworkService)); + + std::vector<std::unique_ptr<content::URLLoaderThrottle>> result; + + auto safe_browsing_throttle = + safe_browsing::BrowserURLLoaderThrottle::MaybeCreate( + GetSafeBrowsingUrlCheckerDelegate(), wc_getter); + if (safe_browsing_throttle) + result.push_back(std::move(safe_browsing_throttle)); + + return result; +} + +safe_browsing::UrlCheckerDelegate* +AwContentBrowserClient::GetSafeBrowsingUrlCheckerDelegate() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + if (!safe_browsing_url_checker_delegate_) { + safe_browsing_url_checker_delegate_ = new AwUrlCheckerDelegateImpl( + browser_context_->GetSafeBrowsingDBManager(), + browser_context_->GetSafeBrowsingUIManager(), + browser_context_->GetSafeBrowsingWhitelistManager()); + } + + return safe_browsing_url_checker_delegate_.get(); +} + } // namespace android_webview
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h index 1a82d426..2f273ef9c 100644 --- a/android_webview/browser/aw_content_browser_client.h +++ b/android_webview/browser/aw_content_browser_client.h
@@ -11,6 +11,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" +#include "base/memory/ref_counted.h" #include "content/public/browser/content_browser_client.h" #include "services/service_manager/public/cpp/binder_registry.h" @@ -18,6 +19,10 @@ class RenderFrameHost; } +namespace safe_browsing { +class UrlCheckerDelegate; +} + namespace android_webview { class AwBrowserContext; @@ -137,8 +142,17 @@ content::RenderFrameHost* render_frame_host, const std::string& interface_name, mojo::ScopedMessagePipeHandle interface_pipe) override; + void ExposeInterfacesToRenderer( + service_manager::BinderRegistry* registry, + content::AssociatedInterfaceRegistry* associated_registry, + content::RenderProcessHost* render_process_host) override; + std::vector<std::unique_ptr<content::URLLoaderThrottle>> + CreateURLLoaderThrottles( + const base::Callback<content::WebContents*()>& wc_getter) override; private: + safe_browsing::UrlCheckerDelegate* GetSafeBrowsingUrlCheckerDelegate(); + // Android WebView currently has a single global (non-off-the-record) browser // context. std::unique_ptr<AwBrowserContext> browser_context_; @@ -146,6 +160,9 @@ service_manager::BinderRegistryWithArgs<content::RenderFrameHost*> frame_interfaces_; + scoped_refptr<safe_browsing::UrlCheckerDelegate> + safe_browsing_url_checker_delegate_; + DISALLOW_COPY_AND_ASSIGN(AwContentBrowserClient); };
diff --git a/android_webview/browser/aw_contents_client_bridge.cc b/android_webview/browser/aw_contents_client_bridge.cc index b49e1f4..a1f1a27 100644 --- a/android_webview/browser/aw_contents_client_bridge.cc +++ b/android_webview/browser/aw_contents_client_bridge.cc
@@ -453,6 +453,7 @@ void AwContentsClientBridge::OnSafeBrowsingHit( const AwWebResourceRequest& request, const safe_browsing::SBThreatType& threat_type, + const std::string& privacy_policy_url, const SafeBrowsingActionCallback& callback) { int request_id = safe_browsing_callbacks_.Add( base::MakeUnique<SafeBrowsingActionCallback>(callback)); @@ -470,7 +471,7 @@ request.has_user_gesture, java_web_resource_request.jmethod, java_web_resource_request.jheader_names, java_web_resource_request.jheader_values, static_cast<int>(threat_type), - request_id); + ConvertUTF8ToJavaString(env, privacy_policy_url), request_id); } void AwContentsClientBridge::OnReceivedHttpError( @@ -552,7 +553,7 @@ return; } callback->Run( - static_cast<AwSafeBrowsingResourceThrottle::SafeBrowsingAction>(action), + static_cast<AwUrlCheckerDelegateImpl::SafeBrowsingAction>(action), reporting); safe_browsing_callbacks_.Remove(request_id); }
diff --git a/android_webview/browser/aw_contents_client_bridge.h b/android_webview/browser/aw_contents_client_bridge.h index 77ffc60..7f9f2766 100644 --- a/android_webview/browser/aw_contents_client_bridge.h +++ b/android_webview/browser/aw_contents_client_bridge.h
@@ -7,7 +7,7 @@ #include <memory> -#include "android_webview/browser/aw_safe_browsing_resource_throttle.h" +#include "android_webview/browser/aw_url_checker_delegate_impl.h" #include "android_webview/browser/net/aw_web_resource_request.h" #include "base/android/jni_weak_ref.h" #include "base/android/scoped_java_ref.h" @@ -100,11 +100,12 @@ int error_code, bool safebrowsing_hit); - void OnSafeBrowsingHit(const AwWebResourceRequest& request, - const safe_browsing::SBThreatType& threat_type, - const base::Callback<void( - AwSafeBrowsingResourceThrottle::SafeBrowsingAction, - bool)>& callback); + void OnSafeBrowsingHit( + const AwWebResourceRequest& request, + const safe_browsing::SBThreatType& threat_type, + const std::string& privacy_policy_url, + const base::Callback<void(AwUrlCheckerDelegateImpl::SafeBrowsingAction, + bool)>& callback); // Called when a response from the server is received with status code >= 400. void OnReceivedHttpError( @@ -140,7 +141,7 @@ typedef const base::Callback<void(content::CertificateRequestResultType)> CertErrorCallback; typedef const base::Callback< - void(AwSafeBrowsingResourceThrottle::SafeBrowsingAction, bool)> + void(AwUrlCheckerDelegateImpl::SafeBrowsingAction, bool)> SafeBrowsingActionCallback; IDMap<std::unique_ptr<CertErrorCallback>> pending_cert_error_callbacks_; IDMap<std::unique_ptr<SafeBrowsingActionCallback>> safe_browsing_callbacks_;
diff --git a/android_webview/browser/aw_safe_browsing_resource_throttle.cc b/android_webview/browser/aw_safe_browsing_resource_throttle.cc index 809cf61..4a61902f 100644 --- a/android_webview/browser/aw_safe_browsing_resource_throttle.cc +++ b/android_webview/browser/aw_safe_browsing_resource_throttle.cc
@@ -54,12 +54,15 @@ database_manager, ui_manager), request_(request), - whitelist_manager_(whitelist_manager) {} + url_checker_delegate_( + new AwUrlCheckerDelegateImpl(std::move(database_manager), + std::move(ui_manager), + whitelist_manager)) {} AwSafeBrowsingResourceThrottle::~AwSafeBrowsingResourceThrottle() {} bool AwSafeBrowsingResourceThrottle::CheckUrl(const GURL& gurl) { - if (whitelist_manager_->IsURLWhitelisted(gurl)) { + if (url_checker_delegate_->IsUrlWhitelisted(gurl)) { return true; } return BaseResourceThrottle::CheckUrl(gurl); @@ -67,87 +70,37 @@ void AwSafeBrowsingResourceThrottle::StartDisplayingBlockingPageHelper( security_interstitials::UnsafeResource resource) { - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&AwSafeBrowsingResourceThrottle::StartApplicationResponse, - AsWeakPtr(), ui_manager(), resource, - AwWebResourceRequest(*request_))); + resource.callback = + base::Bind(&AwSafeBrowsingResourceThrottle::OnBlockingPageComplete, + AsWeakPtr(), resource.callback); + + const content::ResourceRequestInfo* info = + content::ResourceRequestInfo::ForRequest(request_); + bool is_main_frame = + info && info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME; + bool has_user_gesture = info && info->HasUserGesture(); + + net::HttpRequestHeaders headers; + if (!request_->GetFullRequestHeaders(&headers)) + headers = request_->extra_request_headers(); + + url_checker_delegate_->StartDisplayingBlockingPageHelper( + resource, request_->method(), headers, is_main_frame, has_user_gesture); } // static -void AwSafeBrowsingResourceThrottle::StartApplicationResponse( +void AwSafeBrowsingResourceThrottle::OnBlockingPageComplete( const base::WeakPtr<BaseResourceThrottle>& throttle, - scoped_refptr<safe_browsing::BaseUIManager> ui_manager, - const security_interstitials::UnsafeResource& resource, - const AwWebResourceRequest& request) { - content::WebContents* web_contents = resource.web_contents_getter.Run(); - AwContentsClientBridge* client = - AwContentsClientBridge::FromWebContents(web_contents); - - if (client) { - base::Callback<void(SafeBrowsingAction, bool)> callback = - base::Bind(&AwSafeBrowsingResourceThrottle::DoApplicationResponse, - throttle, ui_manager, resource); - - client->OnSafeBrowsingHit(request, resource.threat_type, callback); - } -} - -// static -void AwSafeBrowsingResourceThrottle::DoApplicationResponse( - const base::WeakPtr<BaseResourceThrottle>& throttle, - scoped_refptr<safe_browsing::BaseUIManager> ui_manager, - const security_interstitials::UnsafeResource& resource, - SafeBrowsingAction action, - bool reporting) { - if (!reporting) { - AwSafeBrowsingUIManager* aw_ui_manager = - static_cast<AwSafeBrowsingUIManager*>(ui_manager.get()); - aw_ui_manager->SetExtendedReportingAllowed(false); - } - // TODO(ntfschr): fully handle reporting once we add support (crbug/688629) - bool proceed; - switch (action) { - case SafeBrowsingAction::SHOW_INTERSTITIAL: - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&BaseResourceThrottle::StartDisplayingBlockingPage, - throttle, ui_manager, resource)); - return; - case SafeBrowsingAction::PROCEED: - proceed = true; - break; - case SafeBrowsingAction::BACK_TO_SAFETY: - proceed = false; - break; - default: - NOTREACHED(); + const base::Callback<void(bool)>& forward_callback, + bool proceed) { + if (throttle && !proceed) { + AwSafeBrowsingResourceThrottle* aw_throttle = + static_cast<AwSafeBrowsingResourceThrottle*>(throttle.get()); + aw_throttle->request_->SetUserData( + kUserDataKey, base::MakeUnique<base::SupportsUserData::Data>()); } - content::WebContents* web_contents = resource.web_contents_getter.Run(); - content::NavigationEntry* entry = resource.GetNavigationEntryForResource(); - GURL main_frame_url = entry ? entry->GetURL() : GURL(); - - // Navigate back for back-to-safety on subresources - if (!proceed && resource.is_subframe) { - if (web_contents->GetController().CanGoBack()) { - web_contents->GetController().GoBack(); - } else { - web_contents->GetController().LoadURL( - ui_manager->default_safe_page(), content::Referrer(), - ui::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string()); - } - } - - ui_manager->OnBlockingPageDone( - std::vector<security_interstitials::UnsafeResource>{resource}, proceed, - web_contents, main_frame_url); -} - -void AwSafeBrowsingResourceThrottle::CancelResourceLoad() { - request_->SetUserData(kUserDataKey, - base::MakeUnique<base::SupportsUserData::Data>()); - Cancel(); + forward_callback.Run(proceed); } } // namespace android_webview
diff --git a/android_webview/browser/aw_safe_browsing_resource_throttle.h b/android_webview/browser/aw_safe_browsing_resource_throttle.h index 93509c7..75b991a7 100644 --- a/android_webview/browser/aw_safe_browsing_resource_throttle.h +++ b/android_webview/browser/aw_safe_browsing_resource_throttle.h
@@ -6,6 +6,7 @@ #define ANDROID_WEBVIEW_BROWSER_AW_SAFE_BROWSING_RESOURCE_THROTTLE_H_ #include "android_webview/browser/aw_safe_browsing_ui_manager.h" +#include "android_webview/browser/aw_url_checker_delegate_impl.h" #include "android_webview/browser/net/aw_web_resource_request.h" #include "base/macros.h" #include "components/safe_browsing/base_resource_throttle.h" @@ -27,13 +28,6 @@ class AwSafeBrowsingResourceThrottle : public safe_browsing::BaseResourceThrottle { public: - // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.android_webview - enum class SafeBrowsingAction { - SHOW_INTERSTITIAL, - PROCEED, - BACK_TO_SAFETY, - }; - static const void* const kUserDataKey; // Will construct an AwSafeBrowsingResourceThrottle if GMS exists on device @@ -63,28 +57,14 @@ void StartDisplayingBlockingPageHelper( security_interstitials::UnsafeResource resource) override; - static void StartApplicationResponse( + static void OnBlockingPageComplete( const base::WeakPtr<BaseResourceThrottle>& throttle, - scoped_refptr<safe_browsing::BaseUIManager> ui_manager, - const security_interstitials::UnsafeResource& resource, - const AwWebResourceRequest& request); - - // Follow the application's response to WebViewClient#onSafeBrowsingHit(). If - // the action is PROCEED or BACK_TO_SAFETY, then |reporting| will determine if - // we should send an extended report. Otherwise, |reporting| determines if we - // should allow showing the reporting checkbox or not. - static void DoApplicationResponse( - const base::WeakPtr<BaseResourceThrottle>& throttle, - scoped_refptr<safe_browsing::BaseUIManager> ui_manager, - const security_interstitials::UnsafeResource& resource, - SafeBrowsingAction action, - bool reporting); - - void CancelResourceLoad() override; + const base::Callback<void(bool)>& forward_callback, + bool proceed); net::URLRequest* request_; - AwSafeBrowsingWhitelistManager* whitelist_manager_; + scoped_refptr<safe_browsing::UrlCheckerDelegate> url_checker_delegate_; DISALLOW_COPY_AND_ASSIGN(AwSafeBrowsingResourceThrottle); };
diff --git a/android_webview/browser/aw_url_checker_delegate_impl.cc b/android_webview/browser/aw_url_checker_delegate_impl.cc new file mode 100644 index 0000000..e74a794d --- /dev/null +++ b/android_webview/browser/aw_url_checker_delegate_impl.cc
@@ -0,0 +1,154 @@ +// 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 "android_webview/browser/aw_url_checker_delegate_impl.h" + +#include "android_webview/browser/aw_contents_client_bridge.h" +#include "android_webview/browser/aw_safe_browsing_ui_manager.h" +#include "android_webview/browser/aw_safe_browsing_whitelist_manager.h" +#include "android_webview/browser/net/aw_web_resource_request.h" +#include "base/bind.h" +#include "components/safe_browsing_db/database_manager.h" +#include "components/safe_browsing_db/v4_protocol_manager_util.h" +#include "components/security_interstitials/content/unsafe_resource.h" +#include "components/security_interstitials/core/urls.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/web_contents.h" + +namespace android_webview { + +AwUrlCheckerDelegateImpl::AwUrlCheckerDelegateImpl( + scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager, + scoped_refptr<AwSafeBrowsingUIManager> ui_manager, + AwSafeBrowsingWhitelistManager* whitelist_manager) + : database_manager_(std::move(database_manager)), + ui_manager_(std::move(ui_manager)), + threat_types_(safe_browsing::CreateSBThreatTypeSet( + {safe_browsing::SB_THREAT_TYPE_URL_MALWARE, + safe_browsing::SB_THREAT_TYPE_URL_PHISHING})), + whitelist_manager_(whitelist_manager) {} + +AwUrlCheckerDelegateImpl::~AwUrlCheckerDelegateImpl() = default; + +void AwUrlCheckerDelegateImpl::MaybeDestroyPrerenderContents( + const base::Callback<content::WebContents*()>& web_contents_getter) {} + +void AwUrlCheckerDelegateImpl::StartDisplayingBlockingPageHelper( + const security_interstitials::UnsafeResource& resource, + const std::string& method, + const net::HttpRequestHeaders& headers, + bool is_main_frame, + bool has_user_gesture) { + AwWebResourceRequest request(resource.url.spec(), method, is_main_frame, + has_user_gesture, headers); + + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&AwUrlCheckerDelegateImpl::StartApplicationResponse, + ui_manager_, resource, std::move(request))); +} + +bool AwUrlCheckerDelegateImpl::IsUrlWhitelisted(const GURL& url) { + return whitelist_manager_->IsURLWhitelisted(url); +} + +const safe_browsing::SBThreatTypeSet& +AwUrlCheckerDelegateImpl::GetThreatTypes() { + return threat_types_; +} + +safe_browsing::SafeBrowsingDatabaseManager* +AwUrlCheckerDelegateImpl::GetDatabaseManager() { + return database_manager_.get(); +} + +safe_browsing::BaseUIManager* AwUrlCheckerDelegateImpl::GetUIManager() { + return ui_manager_.get(); +} + +// static +void AwUrlCheckerDelegateImpl::StartApplicationResponse( + scoped_refptr<AwSafeBrowsingUIManager> ui_manager, + const security_interstitials::UnsafeResource& resource, + const AwWebResourceRequest& request) { + content::WebContents* web_contents = resource.web_contents_getter.Run(); + AwContentsClientBridge* client = + AwContentsClientBridge::FromWebContents(web_contents); + + if (client) { + base::Callback<void(SafeBrowsingAction, bool)> callback = base::Bind( + &AwUrlCheckerDelegateImpl::DoApplicationResponse, ui_manager, resource); + + client->OnSafeBrowsingHit( + request, resource.threat_type, + security_interstitials::kSafeBrowsingPrivacyPolicyUrl, callback); + } +} + +// static +void AwUrlCheckerDelegateImpl::DoApplicationResponse( + scoped_refptr<AwSafeBrowsingUIManager> ui_manager, + const security_interstitials::UnsafeResource& resource, + SafeBrowsingAction action, + bool reporting) { + if (!reporting) + ui_manager->SetExtendedReportingAllowed(false); + + // TODO(ntfschr): fully handle reporting once we add support (crbug/688629) + bool proceed; + switch (action) { + case SafeBrowsingAction::SHOW_INTERSTITIAL: + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind( + &AwUrlCheckerDelegateImpl::StartDisplayingDefaultBlockingPage, + ui_manager, resource)); + return; + case SafeBrowsingAction::PROCEED: + proceed = true; + break; + case SafeBrowsingAction::BACK_TO_SAFETY: + proceed = false; + break; + default: + NOTREACHED(); + } + + content::WebContents* web_contents = resource.web_contents_getter.Run(); + content::NavigationEntry* entry = resource.GetNavigationEntryForResource(); + GURL main_frame_url = entry ? entry->GetURL() : GURL(); + + // Navigate back for back-to-safety on subresources + if (!proceed && resource.is_subframe) { + if (web_contents->GetController().CanGoBack()) { + web_contents->GetController().GoBack(); + } else { + web_contents->GetController().LoadURL( + ui_manager->default_safe_page(), content::Referrer(), + ui::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string()); + } + } + + ui_manager->OnBlockingPageDone( + std::vector<security_interstitials::UnsafeResource>{resource}, proceed, + web_contents, main_frame_url); +} + +// static +void AwUrlCheckerDelegateImpl::StartDisplayingDefaultBlockingPage( + scoped_refptr<AwSafeBrowsingUIManager> ui_manager, + const security_interstitials::UnsafeResource& resource) { + content::WebContents* web_contents = resource.web_contents_getter.Run(); + if (web_contents) { + ui_manager->DisplayBlockingPage(resource); + return; + } + + // Reporting back that it is not okay to proceed with loading the URL. + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(resource.callback, false)); +} + +} // namespace android_webview
diff --git a/android_webview/browser/aw_url_checker_delegate_impl.h b/android_webview/browser/aw_url_checker_delegate_impl.h new file mode 100644 index 0000000..e048e32 --- /dev/null +++ b/android_webview/browser/aw_url_checker_delegate_impl.h
@@ -0,0 +1,80 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ANDROID_WEBVIEW_BROWSER_AW_URL_CHECKER_DELEGATE_IMPL_H_ +#define ANDROID_WEBVIEW_BROWSER_AW_URL_CHECKER_DELEGATE_IMPL_H_ + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "components/safe_browsing/browser/url_checker_delegate.h" + +namespace android_webview { + +class AwSafeBrowsingUIManager; +class AwSafeBrowsingWhitelistManager; +struct AwWebResourceRequest; + +class AwUrlCheckerDelegateImpl : public safe_browsing::UrlCheckerDelegate { + public: + // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.android_webview + enum class SafeBrowsingAction { + SHOW_INTERSTITIAL, + PROCEED, + BACK_TO_SAFETY, + }; + + AwUrlCheckerDelegateImpl( + scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> + database_manager, + scoped_refptr<AwSafeBrowsingUIManager> ui_manager, + AwSafeBrowsingWhitelistManager* whitelist_manager); + + private: + ~AwUrlCheckerDelegateImpl() override; + + // Implementation of UrlCheckerDelegate: + void MaybeDestroyPrerenderContents( + const base::Callback<content::WebContents*()>& web_contents_getter) + override; + void StartDisplayingBlockingPageHelper( + const security_interstitials::UnsafeResource& resource, + const std::string& method, + const net::HttpRequestHeaders& headers, + bool is_main_frame, + bool has_user_gesture) override; + bool IsUrlWhitelisted(const GURL& url) override; + const safe_browsing::SBThreatTypeSet& GetThreatTypes() override; + safe_browsing::SafeBrowsingDatabaseManager* GetDatabaseManager() override; + safe_browsing::BaseUIManager* GetUIManager() override; + + static void StartApplicationResponse( + scoped_refptr<AwSafeBrowsingUIManager> ui_manager, + const security_interstitials::UnsafeResource& resource, + const AwWebResourceRequest& request); + + // Follow the application's response to WebViewClient#onSafeBrowsingHit(). If + // the action is PROCEED or BACK_TO_SAFETY, then |reporting| will determine if + // we should send an extended report. Otherwise, |reporting| determines if we + // should allow showing the reporting checkbox or not. + static void DoApplicationResponse( + scoped_refptr<AwSafeBrowsingUIManager> ui_manager, + const security_interstitials::UnsafeResource& resource, + SafeBrowsingAction action, + bool reporting); + + static void StartDisplayingDefaultBlockingPage( + scoped_refptr<AwSafeBrowsingUIManager> ui_manager, + const security_interstitials::UnsafeResource& resource); + + scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager_; + scoped_refptr<AwSafeBrowsingUIManager> ui_manager_; + safe_browsing::SBThreatTypeSet threat_types_; + AwSafeBrowsingWhitelistManager* whitelist_manager_; + + DISALLOW_COPY_AND_ASSIGN(AwUrlCheckerDelegateImpl); +}; + +} // namespace android_webview + +#endif // ANDROID_WEBVIEW_BROWSER_AW_URL_CHECKER_DELEGATE_IMPL_H_
diff --git a/android_webview/browser/net/aw_web_resource_request.cc b/android_webview/browser/net/aw_web_resource_request.cc index 20f8e7c..56ef792 100644 --- a/android_webview/browser/net/aw_web_resource_request.cc +++ b/android_webview/browser/net/aw_web_resource_request.cc
@@ -15,6 +15,21 @@ using base::android::ToJavaArrayOfStrings; namespace android_webview { +namespace { + +void ConvertRequestHeadersToVectors(const net::HttpRequestHeaders& headers, + std::vector<std::string>* header_names, + std::vector<std::string>* header_values) { + DCHECK(header_names->empty()); + DCHECK(header_values->empty()); + net::HttpRequestHeaders::Iterator headers_iterator(headers); + while (headers_iterator.GetNext()) { + header_names->push_back(headers_iterator.name()); + header_values->push_back(headers_iterator.value()); + } +} + +} // namespace AwWebResourceRequest::AwWebResourceRequest(const net::URLRequest& request) : url(request.url().spec()), method(request.method()) { @@ -27,11 +42,21 @@ net::HttpRequestHeaders headers; if (!request.GetFullRequestHeaders(&headers)) headers = request.extra_request_headers(); - net::HttpRequestHeaders::Iterator headers_iterator(headers); - while (headers_iterator.GetNext()) { - header_names.push_back(headers_iterator.name()); - header_values.push_back(headers_iterator.value()); - } + + ConvertRequestHeadersToVectors(headers, &header_names, &header_values); +} + +AwWebResourceRequest::AwWebResourceRequest( + const std::string& in_url, + const std::string& in_method, + bool in_is_main_frame, + bool in_has_user_gesture, + const net::HttpRequestHeaders& in_headers) + : url(in_url), + method(in_method), + is_main_frame(in_is_main_frame), + has_user_gesture(in_has_user_gesture) { + ConvertRequestHeadersToVectors(in_headers, &header_names, &header_values); } AwWebResourceRequest::AwWebResourceRequest(AwWebResourceRequest&& other) =
diff --git a/android_webview/browser/net/aw_web_resource_request.h b/android_webview/browser/net/aw_web_resource_request.h index 53dca70..071a415 100644 --- a/android_webview/browser/net/aw_web_resource_request.h +++ b/android_webview/browser/net/aw_web_resource_request.h
@@ -12,6 +12,7 @@ #include "base/android/jni_string.h" namespace net { +class HttpRequestHeaders; class URLRequest; } @@ -19,8 +20,15 @@ // A passive data structure only used to carry request information. This // class should be copyable. +// The fields are ultimately guided by android.webkit.WebResourceRequest: +// https://developer.android.com/reference/android/webkit/WebResourceRequest.html struct AwWebResourceRequest final { explicit AwWebResourceRequest(const net::URLRequest& request); + AwWebResourceRequest(const std::string& in_url, + const std::string& in_method, + bool in_is_main_frame, + bool in_has_user_gesture, + const net::HttpRequestHeaders& in_headers); // Add default copy/move/assign operators. Adding explicit destructor // prevents generating move operator.
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java index 858c29a..b501163 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java
@@ -634,7 +634,7 @@ @Override public void onSafeBrowsingHit(AwWebResourceRequest request, int threatType, - ValueCallback<AwSafeBrowsingResponse> callback) { + String privacyPolicyUrl, ValueCallback<AwSafeBrowsingResponse> callback) { // TODO(ntfschr): invoke the WebViewClient method once the next SDK rolls callback.onReceiveValue(new AwSafeBrowsingResponse(SafeBrowsingAction.SHOW_INTERSTITIAL, /* reporting */ true));
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java index fc508d0f5a..39ffb33 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
@@ -370,7 +370,7 @@ AwWebResourceRequest request, AwWebResourceError error); protected abstract void onSafeBrowsingHit(AwWebResourceRequest request, int threatType, - ValueCallback<AwSafeBrowsingResponse> callback); + String privacyPolicyUrl, ValueCallback<AwSafeBrowsingResponse> callback); public abstract void onReceivedHttpError(AwWebResourceRequest request, AwWebResourceResponse response);
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsClientBridge.java b/android_webview/java/src/org/chromium/android_webview/AwContentsClientBridge.java index ea82a15..86271e72 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContentsClientBridge.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContentsClientBridge.java
@@ -365,7 +365,7 @@ // WebResourceRequest String url, boolean isMainFrame, boolean hasUserGesture, String method, String[] requestHeaderNames, String[] requestHeaderValues, int threatType, - final int requestId) { + final String privacyPolicyUrl, final int requestId) { AwContentsClient.AwWebResourceRequest request = new AwContentsClient.AwWebResourceRequest(); request.url = url; request.isMainFrame = isMainFrame; @@ -390,8 +390,9 @@ } }; - mClient.getCallbackHelper().postOnSafeBrowsingHit( - request, AwSafeBrowsingConversionHelper.convertThreatType(threatType), callback); + mClient.getCallbackHelper().postOnSafeBrowsingHit(request, + AwSafeBrowsingConversionHelper.convertThreatType(threatType), privacyPolicyUrl, + callback); } @CalledByNative
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsClientCallbackHelper.java b/android_webview/java/src/org/chromium/android_webview/AwContentsClientCallbackHelper.java index a10a936..97e1173 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContentsClientCallbackHelper.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContentsClientCallbackHelper.java
@@ -79,12 +79,14 @@ private static class OnSafeBrowsingHitInfo { final AwContentsClient.AwWebResourceRequest mRequest; final int mThreatType; + final String mPrivacyPolicyUrl; final ValueCallback<AwSafeBrowsingResponse> mCallback; OnSafeBrowsingHitInfo(AwContentsClient.AwWebResourceRequest request, int threatType, - ValueCallback<AwSafeBrowsingResponse> callback) { + String privacyPolicyUrl, ValueCallback<AwSafeBrowsingResponse> callback) { mRequest = request; mThreatType = threatType; + mPrivacyPolicyUrl = privacyPolicyUrl; mCallback = callback; } } @@ -190,8 +192,8 @@ } case MSG_ON_SAFE_BROWSING_HIT: { OnSafeBrowsingHitInfo info = (OnSafeBrowsingHitInfo) msg.obj; - mContentsClient.onSafeBrowsingHit( - info.mRequest, info.mThreatType, info.mCallback); + mContentsClient.onSafeBrowsingHit(info.mRequest, info.mThreatType, + info.mPrivacyPolicyUrl, info.mCallback); break; } case MSG_ON_NEW_PICTURE: { @@ -293,8 +295,9 @@ } public void postOnSafeBrowsingHit(AwContentsClient.AwWebResourceRequest request, int threatType, - ValueCallback<AwSafeBrowsingResponse> callback) { - OnSafeBrowsingHitInfo info = new OnSafeBrowsingHitInfo(request, threatType, callback); + final String privacyPolicyUrl, ValueCallback<AwSafeBrowsingResponse> callback) { + OnSafeBrowsingHitInfo info = + new OnSafeBrowsingHitInfo(request, threatType, privacyPolicyUrl, callback); mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_SAFE_BROWSING_HIT, info)); }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java index 0efef1d..ddf9ca0c 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java
@@ -93,6 +93,9 @@ private static final String WEB_UI_MALWARE_URL = "chrome://safe-browsing/match?type=malware"; private static final String WEB_UI_PHISHING_URL = "chrome://safe-browsing/match?type=phishing"; + private static final String PRIVACY_POLICY_URL = + "https://www.google.com/chrome/browser/privacy/#safe-browsing-policies"; + /** * A fake SafeBrowsingApiHandler which treats URLs ending in MALWARE_HTML_PATH as malicious URLs * that should be blocked. @@ -215,14 +218,16 @@ private static class SafeBrowsingContentsClient extends TestAwContentsClient { private AwWebResourceRequest mLastRequest; private int mLastThreatType; + private String mPrivacyPolicyUrl; private int mAction = SafeBrowsingAction.SHOW_INTERSTITIAL; private boolean mReporting = true; @Override public void onSafeBrowsingHit(AwWebResourceRequest request, int threatType, - ValueCallback<AwSafeBrowsingResponse> callback) { + String privacyPolicyUrl, ValueCallback<AwSafeBrowsingResponse> callback) { mLastRequest = request; mLastThreatType = threatType; + mPrivacyPolicyUrl = privacyPolicyUrl; callback.onReceiveValue(new AwSafeBrowsingResponse(mAction, mReporting)); } @@ -234,6 +239,10 @@ return mLastThreatType; } + public String getLastPrivacyPolicyUrl() { + return mPrivacyPolicyUrl; + } + public void setSafeBrowsingAction(int action) { mAction = action; } @@ -715,11 +724,8 @@ // Assume that we are rendering the interstitial, since we see neither the previous page nor // the target page - // Check onSafeBrowsingHit arguments - final String responseUrl = mTestServer.getURL(PHISHING_HTML_PATH); - assertEquals(responseUrl, mContentsClient.getLastRequest().url); - assertEquals(AwSafeBrowsingConversionHelper.SAFE_BROWSING_THREAT_PHISHING, - mContentsClient.getLastThreatType()); + checkOnSafeBrowsingHitArguments(mTestServer.getURL(PHISHING_HTML_PATH), + AwSafeBrowsingConversionHelper.SAFE_BROWSING_THREAT_PHISHING); } @SmallTest @@ -734,10 +740,8 @@ waitForVisualStateCallback(mAwContents); assertTargetPageHasLoaded(PHISHING_PAGE_BACKGROUND_COLOR); - // Check onSafeBrowsingHit arguments - assertEquals(responseUrl, mContentsClient.getLastRequest().url); - assertEquals(AwSafeBrowsingConversionHelper.SAFE_BROWSING_THREAT_PHISHING, - mContentsClient.getLastThreatType()); + checkOnSafeBrowsingHitArguments( + responseUrl, AwSafeBrowsingConversionHelper.SAFE_BROWSING_THREAT_PHISHING); } @SmallTest @@ -760,10 +764,8 @@ assertEquals("Original page should be showing", GREEN_PAGE_BACKGROUND_COLOR, GraphicsTestUtils.getPixelColorAtCenterOfView(mAwContents, mContainerView)); - // Check onSafeBrowsingHit arguments - assertEquals(responseUrl, mContentsClient.getLastRequest().url); - assertEquals(AwSafeBrowsingConversionHelper.SAFE_BROWSING_THREAT_MALWARE, - mContentsClient.getLastThreatType()); + checkOnSafeBrowsingHitArguments( + responseUrl, AwSafeBrowsingConversionHelper.SAFE_BROWSING_THREAT_MALWARE); } @SmallTest @@ -787,11 +789,9 @@ } }); - // Check onSafeBrowsingHit arguments assertFalse(mContentsClient.getLastRequest().isMainFrame); - assertEquals(subresourceUrl, mContentsClient.getLastRequest().url); - assertEquals(AwSafeBrowsingConversionHelper.SAFE_BROWSING_THREAT_MALWARE, - mContentsClient.getLastThreatType()); + checkOnSafeBrowsingHitArguments( + subresourceUrl, AwSafeBrowsingConversionHelper.SAFE_BROWSING_THREAT_MALWARE); } @SmallTest @@ -818,11 +818,9 @@ } }); - // Check onSafeBrowsingHit arguments assertFalse(mContentsClient.getLastRequest().isMainFrame); - assertEquals(subresourceUrl, mContentsClient.getLastRequest().url); - assertEquals(AwSafeBrowsingConversionHelper.SAFE_BROWSING_THREAT_MALWARE, - mContentsClient.getLastThreatType()); + checkOnSafeBrowsingHitArguments( + subresourceUrl, AwSafeBrowsingConversionHelper.SAFE_BROWSING_THREAT_MALWARE); mContentsClient.setSafeBrowsingAction(SafeBrowsingAction.PROCEED); @@ -831,9 +829,14 @@ assertTargetPageHasLoaded(IFRAME_EMBEDDER_BACKGROUND_COLOR); assertFalse(mContentsClient.getLastRequest().isMainFrame); - assertEquals(subresourceUrl, mContentsClient.getLastRequest().url); - assertEquals(AwSafeBrowsingConversionHelper.SAFE_BROWSING_THREAT_MALWARE, - mContentsClient.getLastThreatType()); + checkOnSafeBrowsingHitArguments( + subresourceUrl, AwSafeBrowsingConversionHelper.SAFE_BROWSING_THREAT_MALWARE); + } + + private void checkOnSafeBrowsingHitArguments(String requestUrl, int threatType) { + assertEquals(requestUrl, mContentsClient.getLastRequest().url); + assertEquals(threatType, mContentsClient.getLastThreatType()); + assertEquals(PRIVACY_POLICY_URL, mContentsClient.getLastPrivacyPolicyUrl()); } @SmallTest
diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc index 033d35f5..d6ced327 100644 --- a/android_webview/lib/aw_main_delegate.cc +++ b/android_webview/lib/aw_main_delegate.cc
@@ -144,6 +144,9 @@ CommandLineHelper::AddDisabledFeature(*cl, features::kWebPayments.name); + // WebView does not support AndroidOverlay yet for video overlays. + CommandLineHelper::AddDisabledFeature(*cl, media::kUseAndroidOverlay.name); + android_webview::RegisterPathProvider(); safe_browsing_api_handler_.reset(
diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc index 81d5d6e..027a22c 100644 --- a/android_webview/renderer/aw_content_renderer_client.cc +++ b/android_webview/renderer/aw_content_renderer_client.cc
@@ -27,6 +27,7 @@ #include "components/autofill/content/renderer/autofill_agent.h" #include "components/autofill/content/renderer/password_autofill_agent.h" #include "components/printing/renderer/print_render_frame_helper.h" +#include "components/safe_browsing/renderer/renderer_url_loader_throttle.h" #include "components/safe_browsing/renderer/websocket_sb_handshake_throttle.h" #include "components/spellcheck/spellcheck_build_features.h" #include "components/supervised_user_error_page/gin_wrapper.h" @@ -311,6 +312,23 @@ safe_browsing_.get()); } +bool AwContentRendererClient::WillSendRequest( + blink::WebLocalFrame* frame, + ui::PageTransition transition_type, + const blink::WebURL& url, + std::vector<std::unique_ptr<content::URLLoaderThrottle>>* throttles, + GURL* new_url) { + if (UsingSafeBrowsingMojoService()) { + content::RenderFrame* render_frame = + content::RenderFrame::FromWebFrame(frame); + throttles->push_back( + base::MakeUnique<safe_browsing::RendererURLLoaderThrottle>( + safe_browsing_.get(), render_frame->GetRoutingID())); + } + + return false; +} + bool AwContentRendererClient::ShouldUseMediaPlayerForURL(const GURL& url) { // Android WebView needs to support codecs that Chrome does not, for these // cases we must force the usage of Android MediaPlayer instead of Chrome's
diff --git a/android_webview/renderer/aw_content_renderer_client.h b/android_webview/renderer/aw_content_renderer_client.h index 6f4e390..fa815b28 100644 --- a/android_webview/renderer/aw_content_renderer_client.h +++ b/android_webview/renderer/aw_content_renderer_client.h
@@ -50,6 +50,12 @@ override; std::unique_ptr<blink::WebSocketHandshakeThrottle> CreateWebSocketHandshakeThrottle() override; + bool WillSendRequest( + blink::WebLocalFrame* frame, + ui::PageTransition transition_type, + const blink::WebURL& url, + std::vector<std::unique_ptr<content::URLLoaderThrottle>>* throttles, + GURL* new_url) override; bool HandleNavigation(content::RenderFrame* render_frame, bool is_content_initiated,
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/test/NullContentsClient.java b/android_webview/test/shell/src/org/chromium/android_webview/test/NullContentsClient.java index c9b5b9c..93ad1f5 100644 --- a/android_webview/test/shell/src/org/chromium/android_webview/test/NullContentsClient.java +++ b/android_webview/test/shell/src/org/chromium/android_webview/test/NullContentsClient.java
@@ -185,7 +185,7 @@ @Override public void onSafeBrowsingHit(AwWebResourceRequest request, int threatType, - ValueCallback<AwSafeBrowsingResponse> callback) { + String privacyPolicyUrl, ValueCallback<AwSafeBrowsingResponse> callback) { callback.onReceiveValue(new AwSafeBrowsingResponse(SafeBrowsingAction.SHOW_INTERSTITIAL, /* reporting */ true)); }
diff --git a/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt b/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt index 2355e6d..61af0d1 100644 --- a/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt +++ b/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt
@@ -2483,6 +2483,11 @@ setter selectionStart setter value setter wrap +interface HTMLTimeElement : HTMLElement + attribute @@toStringTag + getter dateTime + method constructor + setter dateTime interface HTMLTitleElement : HTMLElement getter text method constructor @@ -4073,7 +4078,6 @@ method replaceItem interface SVGPathElement : SVGGeometryElement method constructor - method getPathSegAtLength interface SVGPatternElement : SVGElement getter height getter href
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 0c8a5482e..e8d2ecb4 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -853,6 +853,8 @@ "//chromeos:power_manager_proto", "//components/device_event_log", "//components/onc", + "//components/pref_registry", + "//components/prefs", "//components/quirks", "//components/session_manager:base", "//components/signin/core/account_id",
diff --git a/ash/DEPS b/ash/DEPS index 1c030d7d..6336781 100644 --- a/ash/DEPS +++ b/ash/DEPS
@@ -2,6 +2,7 @@ "+device/bluetooth", "+cc/debug", "+cc/output", + "+components/pref_registry", "+components/prefs", "+components/quirks", "+components/session_manager",
diff --git a/ash/app_list/app_list_presenter_delegate.cc b/ash/app_list/app_list_presenter_delegate.cc index 5ceaa6d..caab59f9 100644 --- a/ash/app_list/app_list_presenter_delegate.cc +++ b/ash/app_list/app_list_presenter_delegate.cc
@@ -246,7 +246,9 @@ } void AppListPresenterDelegate::OnGestureEvent(ui::GestureEvent* event) { - if (event->type() == ui::ET_GESTURE_SHOW_PRESS) + if (event->type() == ui::ET_GESTURE_TAP || + event->type() == ui::ET_GESTURE_TWO_FINGER_TAP || + event->type() == ui::ET_GESTURE_LONG_PRESS) ProcessLocatedEvent(event); }
diff --git a/ash/app_list/app_list_presenter_delegate_unittest.cc b/ash/app_list/app_list_presenter_delegate_unittest.cc index e5c4eba..71eb479 100644 --- a/ash/app_list/app_list_presenter_delegate_unittest.cc +++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -543,6 +543,41 @@ EXPECT_FALSE(app_list_presenter_impl()->IsVisible()); } +TEST_P(FullscreenAppListPresenterDelegateTest, LongPressOutsideCloseAppList) { + app_list_presenter_impl()->Show(GetPrimaryDisplayId()); + EXPECT_TRUE(app_list_presenter_impl()->IsVisible()); + + // |outside_point| is outside the bounds of app list. + gfx::Point outside_point = + app_list_presenter_impl()->GetView()->bounds().origin(); + outside_point.Offset(0, -10); + + // Dispatch LONG_PRESS to ash::AppListPresenterDelegate. + ui::TouchEvent long_press( + ui::ET_GESTURE_LONG_PRESS, outside_point, base::TimeTicks::Now(), + ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH)); + GetEventGenerator().Dispatch(&long_press); + EXPECT_FALSE(app_list_presenter_impl()->IsVisible()); +} + +TEST_P(FullscreenAppListPresenterDelegateTest, + TwoFingerTapOutsideCloseAppList) { + app_list_presenter_impl()->Show(GetPrimaryDisplayId()); + EXPECT_TRUE(app_list_presenter_impl()->IsVisible()); + + // |outside_point| is outside the bounds of app list. + gfx::Point outside_point = + app_list_presenter_impl()->GetView()->bounds().origin(); + outside_point.Offset(0, -10); + + // Dispatch TWO_FINGER_TAP to ash::AppListPresenterDelegate. + ui::TouchEvent two_finger_tap( + ui::ET_GESTURE_TWO_FINGER_TAP, outside_point, base::TimeTicks::Now(), + ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH)); + GetEventGenerator().Dispatch(&two_finger_tap); + EXPECT_FALSE(app_list_presenter_impl()->IsVisible()); +} + // Tests that a keypress activates the searchbox and that clearing the // searchbox, the searchbox remains active. TEST_F(FullscreenAppListPresenterDelegateTest, KeyPressEnablesSearchBox) {
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index bfc7e0b..c7da7a2 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -950,6 +950,12 @@ <message name="IDS_ASH_LOW_PERIPHERAL_BATTERY_NOTIFICATION_TEXT" desc="The text of the notification when a peripheral device is in low battery condition."> Battery low (<ph name="percentage">$1<ex>56</ex></ph>%) </message> + <message name="IDS_ASH_LOW_STYLUS_BATTERY_NOTIFICATION_TITLE" desc="The title of the notification which notifies user of the battery level of a stylus."> + Stylus battery is low + </message> + <message name="IDS_ASH_LOW_STYLUS_BATTERY_NOTIFICATION_BODY" desc="The message of the notification which notifies user of the battery level of a stylus."> + Please charge or replace the batteries. + </message> <message name="IDS_ASH_SCREENSHOT_NOTIFICATION_TITLE_SUCCESS" desc="The title of the notification when a screenshot was taken."> Screenshot taken </message>
diff --git a/ash/display/mirror_window_controller.cc b/ash/display/mirror_window_controller.cc index d1bb13ee..53a4e52 100644 --- a/ash/display/mirror_window_controller.cc +++ b/ash/display/mirror_window_controller.cc
@@ -292,7 +292,7 @@ } } -void MirrorWindowController::OnHostResized(const aura::WindowTreeHost* host) { +void MirrorWindowController::OnHostResized(aura::WindowTreeHost* host) { for (auto& pair : mirroring_host_info_map_) { MirroringHostInfo* info = pair.second; if (info->ash_host->AsWindowTreeHost() == host) {
diff --git a/ash/display/mirror_window_controller.h b/ash/display/mirror_window_controller.h index 0f2fda7..a5648a3 100644 --- a/ash/display/mirror_window_controller.h +++ b/ash/display/mirror_window_controller.h
@@ -62,7 +62,7 @@ void CloseIfNotNecessary(); // aura::WindowTreeHostObserver overrides: - void OnHostResized(const aura::WindowTreeHost* host) override; + void OnHostResized(aura::WindowTreeHost* host) override; // Return the root window used to mirror the content. NULL if the // display is not mirrored by the compositor path.
diff --git a/ash/display/window_tree_host_manager.cc b/ash/display/window_tree_host_manager.cc index b88df714..a31a49fd 100644 --- a/ash/display/window_tree_host_manager.cc +++ b/ash/display/window_tree_host_manager.cc
@@ -641,10 +641,9 @@ SetDisplayPropertiesOnHost(ash_host, display); } -void WindowTreeHostManager::OnHostResized(const aura::WindowTreeHost* host) { +void WindowTreeHostManager::OnHostResized(aura::WindowTreeHost* host) { display::Display display = - display::Screen::GetScreen()->GetDisplayNearestWindow( - const_cast<aura::Window*>(host->window())); + display::Screen::GetScreen()->GetDisplayNearestWindow(host->window()); display::DisplayManager* display_manager = GetDisplayManager(); if (display_manager->UpdateDisplayBounds(display.id(),
diff --git a/ash/display/window_tree_host_manager.h b/ash/display/window_tree_host_manager.h index 4e8c7ba..1f6c603 100644 --- a/ash/display/window_tree_host_manager.h +++ b/ash/display/window_tree_host_manager.h
@@ -164,7 +164,7 @@ uint32_t metrics) override; // aura::WindowTreeHostObserver overrides: - void OnHostResized(const aura::WindowTreeHost* host) override; + void OnHostResized(aura::WindowTreeHost* host) override; // display::DisplayManager::Delegate overrides: void CreateOrUpdateMirroringDisplay(
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn index dd0f06d..ff8fe16 100644 --- a/ash/public/cpp/BUILD.gn +++ b/ash/public/cpp/BUILD.gn
@@ -35,6 +35,8 @@ "shelf_model.cc", "shelf_model.h", "shelf_model_observer.h", + "shelf_prefs.cc", + "shelf_prefs.h", "shelf_types.cc", "shelf_types.h", "shell_window_ids.cc", @@ -50,9 +52,11 @@ defines = [ "ASH_PUBLIC_IMPLEMENTATION" ] deps = [ + "//components/prefs", "//mojo/common:common_custom_types", "//skia/public/interfaces", "//ui/aura", + "//ui/display", "//ui/views", "//ui/views/mus", ]
diff --git a/ash/public/cpp/DEPS b/ash/public/cpp/DEPS index 899f056..aa4234d5 100644 --- a/ash/public/cpp/DEPS +++ b/ash/public/cpp/DEPS
@@ -1,4 +1,6 @@ include_rules = [ + "+components/prefs", "+mojo/common", "+skia/public/interfaces", + "+ui/display", ]
diff --git a/ash/public/cpp/ash_pref_names.cc b/ash/public/cpp/ash_pref_names.cc index 6abdd1a4..e233d2e0 100644 --- a/ash/public/cpp/ash_pref_names.cc +++ b/ash/public/cpp/ash_pref_names.cc
@@ -37,6 +37,25 @@ const char kNightLightCustomStartTime[] = "ash.night_light.custom_start_time"; const char kNightLightCustomEndTime[] = "ash.night_light.custom_end_time"; +// |kShelfAlignment| and |kShelfAutoHideBehavior| have a local variant. The +// local variant is not synced and is used if set. If the local variant is not +// set its value is set from the synced value (once prefs have been +// synced). This gives a per-machine setting that is initialized from the last +// set value. +// These values are default on the machine but can be overridden by per-display +// values in kShelfPreferences (unless overridden by managed policy). +// String value corresponding to ash::ShelfAlignment (e.g. "Bottom"). +const char kShelfAlignment[] = "shelf_alignment"; +const char kShelfAlignmentLocal[] = "shelf_alignment_local"; +// String value corresponding to ash::ShelfAutoHideBehavior (e.g. "Never"). +const char kShelfAutoHideBehavior[] = "auto_hide_behavior"; +const char kShelfAutoHideBehaviorLocal[] = "auto_hide_behavior_local"; +// Dictionary value that holds per-display preference of shelf alignment and +// auto-hide behavior. Key of the dictionary is the id of the display, and +// its value is a dictionary whose keys are kShelfAlignment and +// kShelfAutoHideBehavior. +const char kShelfPreferences[] = "shelf_preferences"; + // Boolean pref indicating whether to show a logout button in the system tray. const char kShowLogoutButtonInTray[] = "show_logout_button_in_tray";
diff --git a/ash/public/cpp/ash_pref_names.h b/ash/public/cpp/ash_pref_names.h index c947385..d27051c 100644 --- a/ash/public/cpp/ash_pref_names.h +++ b/ash/public/cpp/ash_pref_names.h
@@ -18,6 +18,12 @@ ASH_PUBLIC_EXPORT extern const char kNightLightCustomStartTime[]; ASH_PUBLIC_EXPORT extern const char kNightLightCustomEndTime[]; +ASH_PUBLIC_EXPORT extern const char kShelfAlignment[]; +ASH_PUBLIC_EXPORT extern const char kShelfAlignmentLocal[]; +ASH_PUBLIC_EXPORT extern const char kShelfAutoHideBehavior[]; +ASH_PUBLIC_EXPORT extern const char kShelfAutoHideBehaviorLocal[]; +ASH_PUBLIC_EXPORT extern const char kShelfPreferences[]; + ASH_PUBLIC_EXPORT extern const char kShowLogoutButtonInTray[]; ASH_PUBLIC_EXPORT extern const char kLogoutDialogDurationMs[];
diff --git a/ash/public/cpp/shelf_prefs.cc b/ash/public/cpp/shelf_prefs.cc new file mode 100644 index 0000000..9679923 --- /dev/null +++ b/ash/public/cpp/shelf_prefs.cc
@@ -0,0 +1,229 @@ +// 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 "ash/public/cpp/shelf_prefs.h" + +#include "ash/public/cpp/ash_pref_names.h" +#include "base/memory/ptr_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/values.h" +#include "components/prefs/pref_service.h" +#include "components/prefs/scoped_user_pref_update.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" +#include "ui/display/types/display_constants.h" + +namespace ash { + +const char kShelfAutoHideBehaviorAlways[] = "Always"; +const char kShelfAutoHideBehaviorNever[] = "Never"; + +const char kShelfAlignmentBottom[] = "Bottom"; +const char kShelfAlignmentLeft[] = "Left"; +const char kShelfAlignmentRight[] = "Right"; + +namespace { + +// Returns the preference value for the display with the given |display_id|. +// The pref value is stored in |local_path| and |path|, but the pref service may +// have per-display preferences and the value can be specified by policy. +// Here is the priority: +// * A value managed by policy. This is a single value that applies to all +// displays. +// * A user-set value for the specified display. +// * A user-set value in |local_path| or |path|, if no per-display settings are +// ever specified (see http://crbug.com/173719 for why). |local_path| is +// preferred. See comment in |kShelfAlignment| as to why we consider two +// prefs and why |local_path| is preferred. +// * A value recommended by policy. This is a single value that applies to all +// root windows. +// * The default value for |local_path| if the value is not recommended by +// policy. +std::string GetPerDisplayPref(PrefService* prefs, + int64_t display_id, + const char* local_path, + const char* path) { + const PrefService::Preference* local_pref = prefs->FindPreference(local_path); + const std::string value(prefs->GetString(local_path)); + if (local_pref->IsManaged()) + return value; + + std::string pref_key = base::Int64ToString(display_id); + bool has_per_display_prefs = false; + if (!pref_key.empty()) { + const base::DictionaryValue* shelf_prefs = + prefs->GetDictionary(prefs::kShelfPreferences); + const base::DictionaryValue* display_pref = nullptr; + std::string per_display_value; + if (shelf_prefs->GetDictionary(pref_key, &display_pref) && + display_pref->GetString(path, &per_display_value)) + return per_display_value; + + // If the pref for the specified display is not found, scan the whole prefs + // and check if the prefs for other display is already specified. + std::string unused_value; + for (base::DictionaryValue::Iterator iter(*shelf_prefs); !iter.IsAtEnd(); + iter.Advance()) { + const base::DictionaryValue* display_pref = nullptr; + if (iter.value().GetAsDictionary(&display_pref) && + display_pref->GetString(path, &unused_value)) { + has_per_display_prefs = true; + break; + } + } + } + + if (local_pref->IsRecommended() || !has_per_display_prefs) + return value; + + const base::Value* default_value = prefs->GetDefaultPrefValue(local_path); + std::string default_string; + default_value->GetAsString(&default_string); + return default_string; +} + +// Sets the preference value for the display with the given |display_id|. +void SetPerDisplayPref(PrefService* prefs, + int64_t display_id, + const char* pref_key, + const std::string& value) { + if (display_id < 0) + return; + + // Avoid DictionaryPrefUpdate's notifications for read but unmodified prefs. + const base::DictionaryValue* current_shelf_prefs = + prefs->GetDictionary(prefs::kShelfPreferences); + DCHECK(current_shelf_prefs); + std::string display_key = base::Int64ToString(display_id); + const base::DictionaryValue* current_display_prefs = nullptr; + std::string current_value; + if (current_shelf_prefs->GetDictionary(display_key, ¤t_display_prefs) && + current_display_prefs->GetString(pref_key, ¤t_value) && + current_value == value) { + return; + } + + DictionaryPrefUpdate update(prefs, prefs::kShelfPreferences); + base::DictionaryValue* shelf_prefs = update.Get(); + base::DictionaryValue* display_prefs_weak = nullptr; + if (!shelf_prefs->GetDictionary(display_key, &display_prefs_weak)) { + auto display_prefs = base::MakeUnique<base::DictionaryValue>(); + display_prefs_weak = display_prefs.get(); + shelf_prefs->Set(display_key, std::move(display_prefs)); + } + display_prefs_weak->SetStringWithoutPathExpansion(pref_key, value); +} + +ShelfAlignment AlignmentFromPref(const std::string& value) { + if (value == kShelfAlignmentLeft) + return SHELF_ALIGNMENT_LEFT; + if (value == kShelfAlignmentRight) + return SHELF_ALIGNMENT_RIGHT; + // Default to bottom. + return SHELF_ALIGNMENT_BOTTOM; +} + +const char* AlignmentToPref(ShelfAlignment alignment) { + switch (alignment) { + case SHELF_ALIGNMENT_BOTTOM: + return kShelfAlignmentBottom; + case SHELF_ALIGNMENT_LEFT: + return kShelfAlignmentLeft; + case SHELF_ALIGNMENT_RIGHT: + return kShelfAlignmentRight; + case SHELF_ALIGNMENT_BOTTOM_LOCKED: + // This should not be a valid preference option for now. We only want to + // lock the shelf during login or when adding a user. + return nullptr; + } + NOTREACHED(); + return nullptr; +} + +ShelfAutoHideBehavior AutoHideBehaviorFromPref(const std::string& value) { + // Note: To maintain sync compatibility with old images of chrome/chromeos + // the set of values that may be encountered includes the now-extinct + // "Default" as well as "Never" and "Always", "Default" should now + // be treated as "Never" (http://crbug.com/146773). + if (value == kShelfAutoHideBehaviorAlways) + return SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS; + return SHELF_AUTO_HIDE_BEHAVIOR_NEVER; +} + +const char* AutoHideBehaviorToPref(ShelfAutoHideBehavior behavior) { + switch (behavior) { + case SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS: + return kShelfAutoHideBehaviorAlways; + case SHELF_AUTO_HIDE_BEHAVIOR_NEVER: + return kShelfAutoHideBehaviorNever; + case SHELF_AUTO_HIDE_ALWAYS_HIDDEN: + // This should not be a valid preference option for now. We only want to + // completely hide it when we run in app mode - or while we temporarily + // hide the shelf as part of an animation (e.g. the multi user change). + return nullptr; + } + NOTREACHED(); + return nullptr; +} + +} // namespace + +bool CanUserModifyShelfAutoHideBehavior(PrefService* prefs) { + const std::string& pref = prefs::kShelfAutoHideBehaviorLocal; + return prefs->FindPreference(pref)->IsUserModifiable(); +} + +ShelfAutoHideBehavior GetShelfAutoHideBehaviorPref(PrefService* prefs, + int64_t display_id) { + DCHECK_NE(display_id, display::kInvalidDisplayId); + + // See comment in |kShelfAlignment| as to why we consider two prefs. + return AutoHideBehaviorFromPref( + GetPerDisplayPref(prefs, display_id, prefs::kShelfAutoHideBehaviorLocal, + prefs::kShelfAutoHideBehavior)); +} + +void SetShelfAutoHideBehaviorPref(PrefService* prefs, + int64_t display_id, + ShelfAutoHideBehavior behavior) { + DCHECK_NE(display_id, display::kInvalidDisplayId); + + const char* value = AutoHideBehaviorToPref(behavior); + if (!value) + return; + + SetPerDisplayPref(prefs, display_id, prefs::kShelfAutoHideBehavior, value); + if (display_id == display::Screen::GetScreen()->GetPrimaryDisplay().id()) { + // See comment in |kShelfAlignment| about why we have two prefs here. + prefs->SetString(prefs::kShelfAutoHideBehaviorLocal, value); + prefs->SetString(prefs::kShelfAutoHideBehavior, value); + } +} + +ShelfAlignment GetShelfAlignmentPref(PrefService* prefs, int64_t display_id) { + DCHECK_NE(display_id, display::kInvalidDisplayId); + + // See comment in |kShelfAlignment| as to why we consider two prefs. + return AlignmentFromPref(GetPerDisplayPref( + prefs, display_id, prefs::kShelfAlignmentLocal, prefs::kShelfAlignment)); +} + +void SetShelfAlignmentPref(PrefService* prefs, + int64_t display_id, + ShelfAlignment alignment) { + DCHECK_NE(display_id, display::kInvalidDisplayId); + + const char* value = AlignmentToPref(alignment); + if (!value) + return; + + SetPerDisplayPref(prefs, display_id, prefs::kShelfAlignment, value); + if (display_id == display::Screen::GetScreen()->GetPrimaryDisplay().id()) { + // See comment in |kShelfAlignment| as to why we consider two prefs. + prefs->SetString(prefs::kShelfAlignmentLocal, value); + prefs->SetString(prefs::kShelfAlignment, value); + } +} + +} // namespace ash
diff --git a/ash/public/cpp/shelf_prefs.h b/ash/public/cpp/shelf_prefs.h new file mode 100644 index 0000000..a5f7d56 --- /dev/null +++ b/ash/public/cpp/shelf_prefs.h
@@ -0,0 +1,48 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_PUBLIC_CPP_SHELF_PREFS_H_ +#define ASH_PUBLIC_CPP_SHELF_PREFS_H_ + +#include "ash/public/cpp/ash_public_export.h" +#include "ash/public/cpp/shelf_types.h" + +class PrefService; + +namespace ash { + +// Values used for prefs::kShelfAutoHideBehavior. +ASH_PUBLIC_EXPORT extern const char kShelfAutoHideBehaviorAlways[]; +ASH_PUBLIC_EXPORT extern const char kShelfAutoHideBehaviorNever[]; + +// Values used for prefs::kShelfAlignment. +ASH_PUBLIC_EXPORT extern const char kShelfAlignmentBottom[]; +ASH_PUBLIC_EXPORT extern const char kShelfAlignmentLeft[]; +ASH_PUBLIC_EXPORT extern const char kShelfAlignmentRight[]; + +// Returns true if the user can modify the |shelf|'s auto-hide behavior. +ASH_PUBLIC_EXPORT bool CanUserModifyShelfAutoHideBehavior(PrefService* prefs); + +// Get the shelf auto hide behavior preference for a particular display. +ASH_PUBLIC_EXPORT ShelfAutoHideBehavior +GetShelfAutoHideBehaviorPref(PrefService* prefs, int64_t display_id); + +// Set the shelf auto hide behavior preference for a particular display. +ASH_PUBLIC_EXPORT void SetShelfAutoHideBehaviorPref( + PrefService* prefs, + int64_t display_id, + ShelfAutoHideBehavior behavior); + +// Get the shelf alignment preference for a particular display. +ASH_PUBLIC_EXPORT ShelfAlignment GetShelfAlignmentPref(PrefService* prefs, + int64_t display_id); + +// Set the shelf alignment preference for a particular display. +ASH_PUBLIC_EXPORT void SetShelfAlignmentPref(PrefService* prefs, + int64_t display_id, + ShelfAlignment alignment); + +} // namespace ash + +#endif // ASH_PUBLIC_CPP_SHELF_PREFS_H_
diff --git a/ash/public/cpp/shelf_struct_traits.h b/ash/public/cpp/shelf_struct_traits.h index 532be621..a5a112d 100644 --- a/ash/public/cpp/shelf_struct_traits.h +++ b/ash/public/cpp/shelf_struct_traits.h
@@ -57,79 +57,6 @@ }; template <> -struct EnumTraits<ash::mojom::ShelfAlignment, ash::ShelfAlignment> { - static ash::mojom::ShelfAlignment ToMojom(ash::ShelfAlignment input) { - switch (input) { - case ash::SHELF_ALIGNMENT_BOTTOM: - return ash::mojom::ShelfAlignment::BOTTOM; - case ash::SHELF_ALIGNMENT_LEFT: - return ash::mojom::ShelfAlignment::LEFT; - case ash::SHELF_ALIGNMENT_RIGHT: - return ash::mojom::ShelfAlignment::RIGHT; - case ash::SHELF_ALIGNMENT_BOTTOM_LOCKED: - return ash::mojom::ShelfAlignment::BOTTOM_LOCKED; - } - NOTREACHED(); - return ash::mojom::ShelfAlignment::BOTTOM; - } - - static bool FromMojom(ash::mojom::ShelfAlignment input, - ash::ShelfAlignment* out) { - switch (input) { - case ash::mojom::ShelfAlignment::BOTTOM: - *out = ash::SHELF_ALIGNMENT_BOTTOM; - return true; - case ash::mojom::ShelfAlignment::LEFT: - *out = ash::SHELF_ALIGNMENT_LEFT; - return true; - case ash::mojom::ShelfAlignment::RIGHT: - *out = ash::SHELF_ALIGNMENT_RIGHT; - return true; - case ash::mojom::ShelfAlignment::BOTTOM_LOCKED: - *out = ash::SHELF_ALIGNMENT_BOTTOM_LOCKED; - return true; - } - NOTREACHED(); - return false; - } -}; - -template <> -struct EnumTraits<ash::mojom::ShelfAutoHideBehavior, - ash::ShelfAutoHideBehavior> { - static ash::mojom::ShelfAutoHideBehavior ToMojom( - ash::ShelfAutoHideBehavior input) { - switch (input) { - case ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS: - return ash::mojom::ShelfAutoHideBehavior::ALWAYS; - case ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER: - return ash::mojom::ShelfAutoHideBehavior::NEVER; - case ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN: - return ash::mojom::ShelfAutoHideBehavior::HIDDEN; - } - NOTREACHED(); - return ash::mojom::ShelfAutoHideBehavior::NEVER; - } - - static bool FromMojom(ash::mojom::ShelfAutoHideBehavior input, - ash::ShelfAutoHideBehavior* out) { - switch (input) { - case ash::mojom::ShelfAutoHideBehavior::ALWAYS: - *out = ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS; - return true; - case ash::mojom::ShelfAutoHideBehavior::NEVER: - *out = ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER; - return true; - case ash::mojom::ShelfAutoHideBehavior::HIDDEN: - *out = ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN; - return true; - } - NOTREACHED(); - return false; - } -}; - -template <> struct EnumTraits<ash::mojom::ShelfItemStatus, ash::ShelfItemStatus> { static ash::mojom::ShelfItemStatus ToMojom(ash::ShelfItemStatus input) { switch (input) {
diff --git a/ash/public/interfaces/session_controller.mojom b/ash/public/interfaces/session_controller.mojom index e64153de..df95f6f5 100644 --- a/ash/public/interfaces/session_controller.mojom +++ b/ash/public/interfaces/session_controller.mojom
@@ -97,6 +97,10 @@ // Whether the screen should be locked automatically before suspending. bool should_lock_screen_automatically; + // Whether the session is in app mode, which includes a kiosk-like mode for + // fullscreen web content or running a single [forced] Chrome or ARC app. + bool is_running_in_app_mode; + // Sets whether adding a user session to ash is allowed. AddUserSessionPolicy add_user_session_policy;
diff --git a/ash/public/interfaces/shelf.mojom b/ash/public/interfaces/shelf.mojom index 7382716..be1b5e0 100644 --- a/ash/public/interfaces/shelf.mojom +++ b/ash/public/interfaces/shelf.mojom
@@ -18,12 +18,6 @@ APP_LIST_SHOWN, // The app list launcher menu was shown. }; -// These values match ash::ShelfAlignment. -enum ShelfAlignment { BOTTOM, LEFT, RIGHT, BOTTOM_LOCKED, }; - -// These values match ash::ShelfAutoHideBehavior. -enum ShelfAutoHideBehavior { ALWAYS, NEVER, HIDDEN, }; - // Represents the status of items in the shelf. // These values match ash::ShelfItemStatus. enum ShelfItemStatus { @@ -78,22 +72,10 @@ UpdateShelfItem(ShelfItem item); // Sets the |delegate| for the item with |id|. SetShelfItemDelegate(ShelfID id, ShelfItemDelegate delegate); - - // Set the shelf alignment and auto-hide behavior. See Shelf for details. - // TODO(jamescook): Eliminate all these methods and use the ash pref service - // to observe and to set prefs. http://crbug.com/723085 - SetAlignment(ShelfAlignment alignment, int64 display_id); - SetAutoHideBehavior(ShelfAutoHideBehavior auto_hide, int64 display_id); }; // A Shelf observer, used to persist profile settings and cache a ShelfModel. interface ShelfObserver { - // TODO(jamescook): Eliminate all these methods and use the ash pref service - // to observe and to set prefs. http://crbug.com/723085 - OnShelfInitialized(int64 display_id); - OnAlignmentChanged(ShelfAlignment alignment, int64 display_id); - OnAutoHideBehaviorChanged(ShelfAutoHideBehavior auto_hide, int64 display_id); - // Called when the |item| has been added at |index|. OnShelfItemAdded(int32 index, ShelfItem item); // Called when the item with |id| has been removed.
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc index 3ce92503..3be01f98 100644 --- a/ash/root_window_controller.cc +++ b/ash/root_window_controller.cc
@@ -345,7 +345,6 @@ if (shelf_initialized_) return; shelf_initialized_ = true; - shelf_->NotifyShelfInitialized(); // TODO(jamescook): Pass |shelf_| into the constructors for these layout // managers.
diff --git a/ash/session/session_controller.cc b/ash/session/session_controller.cc index e16abf70..9683d32b 100644 --- a/ash/session/session_controller.cc +++ b/ash/session/session_controller.cc
@@ -85,6 +85,10 @@ return should_lock_screen_automatically_; } +bool SessionController::IsRunningInAppMode() const { + return is_running_in_app_mode_; +} + bool SessionController::IsUserSessionBlocked() const { // User sessions are blocked when session state is not ACTIVE, with two // exceptions: @@ -200,6 +204,7 @@ void SessionController::SetSessionInfo(mojom::SessionInfoPtr info) { can_lock_ = info->can_lock_screen; should_lock_screen_automatically_ = info->should_lock_screen_automatically; + is_running_in_app_mode_ = info->is_running_in_app_mode; add_user_session_policy_ = info->add_user_session_policy; SetSessionState(info->state); }
diff --git a/ash/session/session_controller.h b/ash/session/session_controller.h index 9dd039b..2b10d43 100644 --- a/ash/session/session_controller.h +++ b/ash/session/session_controller.h
@@ -64,6 +64,9 @@ // is turned off or the system is suspended. bool ShouldLockScreenAutomatically() const; + // Returns true if the session is in a kiosk-like mode running a single app. + bool IsRunningInAppMode() const; + // Returns true if user session blocked by some overlying UI. It can be // login screen, lock screen or screen for adding users into multi-profile // session. @@ -167,6 +170,7 @@ // Cached session info. bool can_lock_ = false; bool should_lock_screen_automatically_ = false; + bool is_running_in_app_mode_ = false; AddUserSessionPolicy add_user_session_policy_ = AddUserSessionPolicy::ALLOWED; session_manager::SessionState state_;
diff --git a/ash/session/session_controller_unittest.cc b/ash/session/session_controller_unittest.cc index ecc58b27..52c5d280 100644 --- a/ash/session/session_controller_unittest.cc +++ b/ash/session/session_controller_unittest.cc
@@ -65,6 +65,7 @@ void FillDefaultSessionInfo(mojom::SessionInfo* info) { info->can_lock_screen = true; info->should_lock_screen_automatically = true; + info->is_running_in_app_mode = false; info->add_user_session_policy = AddUserSessionPolicy::ALLOWED; info->state = SessionState::LOGIN_PRIMARY; } @@ -127,16 +128,25 @@ EXPECT_TRUE(controller()->CanLockScreen()); EXPECT_TRUE(controller()->ShouldLockScreenAutomatically()); + EXPECT_FALSE(controller()->IsRunningInAppMode()); info.can_lock_screen = false; SetSessionInfo(info); EXPECT_FALSE(controller()->CanLockScreen()); EXPECT_TRUE(controller()->ShouldLockScreenAutomatically()); + EXPECT_FALSE(controller()->IsRunningInAppMode()); info.should_lock_screen_automatically = false; SetSessionInfo(info); EXPECT_FALSE(controller()->CanLockScreen()); EXPECT_FALSE(controller()->ShouldLockScreenAutomatically()); + EXPECT_FALSE(controller()->IsRunningInAppMode()); + + info.is_running_in_app_mode = true; + SetSessionInfo(info); + EXPECT_FALSE(controller()->CanLockScreen()); + EXPECT_FALSE(controller()->ShouldLockScreenAutomatically()); + EXPECT_TRUE(controller()->IsRunningInAppMode()); } // Tests that the CanLockScreen is only true with an active user session.
diff --git a/ash/shelf/shelf.cc b/ash/shelf/shelf.cc index 15bfcb3..df6ade6f 100644 --- a/ash/shelf/shelf.cc +++ b/ash/shelf/shelf.cc
@@ -120,8 +120,6 @@ aura::Window* status_container = root->GetChildById(kShellWindowId_StatusContainer); shelf_widget_->CreateStatusAreaWidget(status_container); - - Shell::Get()->window_tree_host_manager()->AddObserver(this); } void Shelf::ShutdownShelfWidget() { @@ -131,16 +129,7 @@ void Shelf::DestroyShelfWidget() { // May be called multiple times during shutdown. - if (shelf_widget_) { - shelf_widget_.reset(); - Shell::Get()->window_tree_host_manager()->RemoveObserver(this); - } -} - -void Shelf::NotifyShelfInitialized() { - DCHECK(shelf_layout_manager_); - DCHECK(shelf_widget_); - Shell::Get()->shelf_controller()->NotifyShelfInitialized(this); + shelf_widget_.reset(); } aura::Window* Shelf::GetWindow() { @@ -165,7 +154,6 @@ // The ShelfWidget notifies the ShelfView of the alignment change. shelf_widget_->OnShelfAlignmentChanged(); shelf_layout_manager_->LayoutShelf(); - Shell::Get()->shelf_controller()->NotifyShelfAlignmentChanged(this); Shell::Get()->NotifyShelfAlignmentChanged(GetWindow()->GetRootWindow()); } @@ -207,7 +195,6 @@ return; auto_hide_behavior_ = auto_hide_behavior; - Shell::Get()->shelf_controller()->NotifyShelfAutoHideBehaviorChanged(this); Shell::Get()->NotifyShelfAutoHideBehaviorChanged( GetWindow()->GetRootWindow()); } @@ -371,19 +358,4 @@ observer.OnBackgroundTypeChanged(background_type, change_type); } -void Shelf::OnWindowTreeHostReusedForDisplay( - AshWindowTreeHost* window_tree_host, - const display::Display& display) { - // See comment in OnWindowTreeHostsSwappedDisplays(). - NotifyShelfInitialized(); -} - -void Shelf::OnWindowTreeHostsSwappedDisplays(AshWindowTreeHost* host1, - AshWindowTreeHost* host2) { - // The display id for this shelf instance may have changed, so request - // re-initialization to fetch the alignment and auto-hide state from prefs. - // See http://crbug.com/748291 - NotifyShelfInitialized(); -} - } // namespace ash
diff --git a/ash/shelf/shelf.h b/ash/shelf/shelf.h index 0308cc1..9c673a5 100644 --- a/ash/shelf/shelf.h +++ b/ash/shelf/shelf.h
@@ -8,7 +8,6 @@ #include <memory> #include "ash/ash_export.h" -#include "ash/display/window_tree_host_manager.h" #include "ash/public/cpp/shelf_types.h" #include "ash/shelf/shelf_layout_manager_observer.h" #include "ash/shelf/shelf_locking_manager.h" @@ -41,8 +40,7 @@ // Controller for the shelf state. One per display, because each display might // have different shelf alignment, autohide, etc. Exists for the lifetime of the // root window controller. -class ASH_EXPORT Shelf : public ShelfLayoutManagerObserver, - public WindowTreeHostManager::Observer { +class ASH_EXPORT Shelf : public ShelfLayoutManagerObserver { public: Shelf(); ~Shelf() override; @@ -65,9 +63,6 @@ ShelfWidget* shelf_widget() { return shelf_widget_.get(); } - // TODO(jamescook): Eliminate this method. - void NotifyShelfInitialized(); - // Returns the window showing the shelf. aura::Window* GetWindow(); @@ -148,13 +143,6 @@ void OnBackgroundUpdated(ShelfBackgroundType background_type, AnimationChangeType change_type) override; - // WindowTreeHostManager::Observer: - void OnWindowTreeHostReusedForDisplay( - AshWindowTreeHost* window_tree_host, - const display::Display& display) override; - void OnWindowTreeHostsSwappedDisplays(AshWindowTreeHost* host1, - AshWindowTreeHost* host2) override; - private: class AutoHideEventHandler; friend class ShelfLayoutManagerTest;
diff --git a/ash/shelf/shelf_alignment_menu.cc b/ash/shelf/shelf_alignment_menu.cc index a5c6d07..270e114 100644 --- a/ash/shelf/shelf_alignment_menu.cc +++ b/ash/shelf/shelf_alignment_menu.cc
@@ -6,8 +6,10 @@ #include "ash/metrics/user_metrics_action.h" #include "ash/metrics/user_metrics_recorder.h" +#include "ash/public/cpp/shelf_prefs.h" #include "ash/public/cpp/shelf_types.h" #include "ash/shelf/shelf.h" +#include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" @@ -47,21 +49,29 @@ } void ShelfAlignmentMenu::ExecuteCommand(int command_id, int event_flags) { + PrefService* prefs = Shell::Get()->GetActiveUserPrefService(); + if (!prefs) // Null during startup, user switch and tests. + return; + + int64_t display_id = + display::Screen::GetScreen() + ->GetDisplayNearestWindow(shelf_->shelf_widget()->GetNativeWindow()) + .id(); switch (static_cast<MenuItem>(command_id)) { case MENU_ALIGN_LEFT: Shell::Get()->metrics()->RecordUserMetricsAction( UMA_SHELF_ALIGNMENT_SET_LEFT); - shelf_->SetAlignment(SHELF_ALIGNMENT_LEFT); + SetShelfAlignmentPref(prefs, display_id, SHELF_ALIGNMENT_LEFT); break; case MENU_ALIGN_BOTTOM: Shell::Get()->metrics()->RecordUserMetricsAction( UMA_SHELF_ALIGNMENT_SET_BOTTOM); - shelf_->SetAlignment(SHELF_ALIGNMENT_BOTTOM); + SetShelfAlignmentPref(prefs, display_id, SHELF_ALIGNMENT_BOTTOM); break; case MENU_ALIGN_RIGHT: Shell::Get()->metrics()->RecordUserMetricsAction( UMA_SHELF_ALIGNMENT_SET_RIGHT); - shelf_->SetAlignment(SHELF_ALIGNMENT_RIGHT); + SetShelfAlignmentPref(prefs, display_id, SHELF_ALIGNMENT_RIGHT); break; } }
diff --git a/ash/shelf/shelf_controller.cc b/ash/shelf/shelf_controller.cc index 290fe0f..93bcbf32 100644 --- a/ash/shelf/shelf_controller.cc +++ b/ash/shelf/shelf_controller.cc
@@ -4,8 +4,10 @@ #include "ash/shelf/shelf_controller.h" +#include "ash/public/cpp/ash_pref_names.h" #include "ash/public/cpp/config.h" #include "ash/public/cpp/remote_shelf_item_delegate.h" +#include "ash/public/cpp/shelf_prefs.h" #include "ash/root_window_controller.h" #include "ash/session/session_controller.h" #include "ash/shelf/app_list_shelf_item_delegate.h" @@ -14,6 +16,10 @@ #include "ash/strings/grit/ash_strings.h" #include "base/auto_reset.h" #include "base/strings/utf_string_conversions.h" +#include "components/pref_registry/pref_registry_syncable.h" +#include "components/prefs/pref_change_registrar.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/prefs/pref_service.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/simple_menu_model.h" #include "ui/display/display.h" @@ -31,6 +37,51 @@ return root_window_controller ? root_window_controller->shelf() : nullptr; } +// Set each Shelf's auto-hide behavior from the per-display pref. +void SetShelfAutoHideFromPrefs() { + // TODO(jamescook): The session state check should not be necessary, but + // otherwise this wrongly tries to set the alignment on a secondary display + // during login before the ShelfLockingManager is created. + SessionController* session_controller = Shell::Get()->session_controller(); + PrefService* prefs = Shell::Get()->GetActiveUserPrefService(); + if (!prefs || !session_controller->IsActiveUserSessionStarted()) + return; + + for (const auto& display : display::Screen::GetScreen()->GetAllDisplays()) { + auto value = GetShelfAutoHideBehaviorPref(prefs, display.id()); + // Don't show the shelf in app mode. + if (session_controller->IsRunningInAppMode()) + value = SHELF_AUTO_HIDE_ALWAYS_HIDDEN; + Shelf* shelf = GetShelfForDisplay(display.id()); + if (shelf) + shelf->SetAutoHideBehavior(value); + } +} + +// Set each Shelf's alignment from the per-display pref. +void SetShelfAlignmentFromPrefs() { + // TODO(jamescook): The session state check should not be necessary, but + // otherwise this wrongly tries to set the alignment on a secondary display + // during login before the ShelfLockingManager is created. + SessionController* session_controller = Shell::Get()->session_controller(); + PrefService* prefs = Shell::Get()->GetActiveUserPrefService(); + if (!prefs || !session_controller->IsActiveUserSessionStarted()) + return; + + for (const auto& display : display::Screen::GetScreen()->GetAllDisplays()) { + auto value = GetShelfAlignmentPref(prefs, display.id()); + Shelf* shelf = GetShelfForDisplay(display.id()); + if (shelf) + shelf->SetAlignment(value); + } +} + +// Set each Shelf's auto-hide behavior and alignment from the per-display prefs. +void SetShelfBehaviorsFromPrefs() { + SetShelfAutoHideFromPrefs(); + SetShelfAlignmentFromPrefs(); +} + } // namespace ShelfController::ShelfController() { @@ -43,47 +94,40 @@ model_.Set(0, item); model_.AddObserver(this); + Shell::Get()->AddShellObserver(this); + Shell::Get()->window_tree_host_manager()->AddObserver(this); } ShelfController::~ShelfController() { + Shell::Get()->window_tree_host_manager()->RemoveObserver(this); + Shell::Get()->RemoveShellObserver(this); model_.RemoveObserver(this); } +// static +void ShelfController::RegisterProfilePrefs(PrefRegistrySimple* registry) { + // These prefs are marked PUBLIC for use by Chrome, they're currently only + // needed for ChromeLauncherController::ShelfBoundsChangesProbablyWithUser + // and ChromeLauncherPrefsObserver. See the pref names definitions for an + // explanation of the synced, local, and per-display behavior of these prefs. + registry->RegisterStringPref( + prefs::kShelfAutoHideBehavior, kShelfAutoHideBehaviorNever, + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF | PrefRegistry::PUBLIC); + registry->RegisterStringPref(prefs::kShelfAutoHideBehaviorLocal, + std::string(), PrefRegistry::PUBLIC); + registry->RegisterStringPref( + prefs::kShelfAlignment, kShelfAlignmentBottom, + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF | PrefRegistry::PUBLIC); + registry->RegisterStringPref(prefs::kShelfAlignmentLocal, std::string(), + PrefRegistry::PUBLIC); + registry->RegisterDictionaryPref(prefs::kShelfPreferences, + PrefRegistry::PUBLIC); +} + void ShelfController::BindRequest(mojom::ShelfControllerRequest request) { bindings_.AddBinding(this, std::move(request)); } -void ShelfController::NotifyShelfInitialized(Shelf* shelf) { - // Notify observers, Chrome will set alignment and auto-hide from prefs. - display::Display display = - display::Screen::GetScreen()->GetDisplayNearestWindow(shelf->GetWindow()); - int64_t display_id = display.id(); - observers_.ForAllPtrs([display_id](mojom::ShelfObserver* observer) { - observer->OnShelfInitialized(display_id); - }); -} - -void ShelfController::NotifyShelfAlignmentChanged(Shelf* shelf) { - ShelfAlignment alignment = shelf->alignment(); - display::Display display = - display::Screen::GetScreen()->GetDisplayNearestWindow(shelf->GetWindow()); - int64_t display_id = display.id(); - observers_.ForAllPtrs( - [alignment, display_id](mojom::ShelfObserver* observer) { - observer->OnAlignmentChanged(alignment, display_id); - }); -} - -void ShelfController::NotifyShelfAutoHideBehaviorChanged(Shelf* shelf) { - ShelfAutoHideBehavior behavior = shelf->auto_hide_behavior(); - display::Display display = - display::Screen::GetScreen()->GetDisplayNearestWindow(shelf->GetWindow()); - int64_t display_id = display.id(); - observers_.ForAllPtrs([behavior, display_id](mojom::ShelfObserver* observer) { - observer->OnAutoHideBehaviorChanged(behavior, display_id); - }); -} - void ShelfController::AddObserver( mojom::ShelfObserverAssociatedPtrInfo observer) { mojom::ShelfObserverAssociatedPtr observer_ptr; @@ -106,26 +150,6 @@ observers_.AddPtr(std::move(observer_ptr)); } -void ShelfController::SetAlignment(ShelfAlignment alignment, - int64_t display_id) { - Shelf* shelf = GetShelfForDisplay(display_id); - // TODO(jamescook): The session state check should not be necessary, but - // otherwise this wrongly tries to set the alignment on a secondary display - // during login before the ShelfLockingManager is created. - if (shelf && Shell::Get()->session_controller()->IsActiveUserSessionStarted()) - shelf->SetAlignment(alignment); -} - -void ShelfController::SetAutoHideBehavior(ShelfAutoHideBehavior auto_hide, - int64_t display_id) { - Shelf* shelf = GetShelfForDisplay(display_id); - // TODO(jamescook): The session state check should not be necessary, but - // otherwise this wrongly tries to set auto-hide state on a secondary display - // during login. - if (shelf && Shell::Get()->session_controller()->IsActiveUserSessionStarted()) - shelf->SetAutoHideBehavior(auto_hide); -} - void ShelfController::AddShelfItem(int32_t index, const ShelfItem& item) { DCHECK_EQ(Shell::GetAshConfig(), Config::MASH) << " Unexpected model sync"; DCHECK(!applying_remote_shelf_model_changes_) << " Unexpected model change"; @@ -252,4 +276,40 @@ }); } +void ShelfController::OnActiveUserPrefServiceChanged( + PrefService* pref_service) { + pref_change_registrar_.reset(); + if (!pref_service) // Null during startup, user switch and tests. + return; + SetShelfBehaviorsFromPrefs(); + pref_change_registrar_ = base::MakeUnique<PrefChangeRegistrar>(); + pref_change_registrar_->Init(pref_service); + pref_change_registrar_->Add(prefs::kShelfAlignmentLocal, + base::Bind(&SetShelfAlignmentFromPrefs)); + pref_change_registrar_->Add(prefs::kShelfAutoHideBehaviorLocal, + base::Bind(&SetShelfAutoHideFromPrefs)); + pref_change_registrar_->Add(prefs::kShelfPreferences, + base::Bind(&SetShelfBehaviorsFromPrefs)); +} + +void ShelfController::OnDisplayConfigurationChanged() { + // Set/init the shelf behaviors from preferences, in case a display was added. + SetShelfBehaviorsFromPrefs(); +} + +void ShelfController::OnWindowTreeHostReusedForDisplay( + AshWindowTreeHost* window_tree_host, + const display::Display& display) { + // See comment in OnWindowTreeHostsSwappedDisplays(). + SetShelfBehaviorsFromPrefs(); +} + +void ShelfController::OnWindowTreeHostsSwappedDisplays( + AshWindowTreeHost* host1, + AshWindowTreeHost* host2) { + // The display ids for existing shelf instances may have changed, so update + // the alignment and auto-hide state from prefs. See http://crbug.com/748291 + SetShelfBehaviorsFromPrefs(); +} + } // namespace ash
diff --git a/ash/shelf/shelf_controller.h b/ash/shelf/shelf_controller.h index a55a9f0..a596cf3 100644 --- a/ash/shelf/shelf_controller.h +++ b/ash/shelf/shelf_controller.h
@@ -5,41 +5,40 @@ #ifndef ASH_SHELF_SHELF_CONTROLLER_H_ #define ASH_SHELF_SHELF_CONTROLLER_H_ +#include "ash/display/window_tree_host_manager.h" #include "ash/public/cpp/shelf_item.h" #include "ash/public/cpp/shelf_model.h" #include "ash/public/cpp/shelf_model_observer.h" #include "ash/public/cpp/shelf_types.h" #include "ash/public/interfaces/shelf.mojom.h" +#include "ash/shell_observer.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/bindings/interface_ptr_set.h" -namespace ash { +class PrefChangeRegistrar; +class PrefRegistrySimple; -class Shelf; +namespace ash { // Ash's ShelfController owns the ShelfModel and implements interface functions // that allow Chrome to modify and observe the Shelf and ShelfModel state. class ShelfController : public mojom::ShelfController, - public ShelfModelObserver { + public ShelfModelObserver, + public ShellObserver, + public WindowTreeHostManager::Observer { public: ShelfController(); ~ShelfController() override; + static void RegisterProfilePrefs(PrefRegistrySimple* registry); + // Binds the mojom::ShelfController interface request to this object. void BindRequest(mojom::ShelfControllerRequest request); ShelfModel* model() { return &model_; } - // Functions used to notify mojom::ShelfObserver instances of changes. - void NotifyShelfInitialized(Shelf* shelf); - void NotifyShelfAlignmentChanged(Shelf* shelf); - void NotifyShelfAutoHideBehaviorChanged(Shelf* shelf); - // mojom::ShelfController: void AddObserver(mojom::ShelfObserverAssociatedPtrInfo observer) override; - void SetAlignment(ShelfAlignment alignment, int64_t display_id) override; - void SetAutoHideBehavior(ShelfAutoHideBehavior auto_hide, - int64_t display_id) override; void AddShelfItem(int32_t index, const ShelfItem& item) override; void RemoveShelfItem(const ShelfID& id) override; void MoveShelfItem(const ShelfID& id, int32_t index) override; @@ -56,6 +55,17 @@ ShelfItemDelegate* delegate) override; private: + // ShellObserver: + void OnActiveUserPrefServiceChanged(PrefService* pref_service) override; + + // WindowTreeHostManager::Observer: + void OnDisplayConfigurationChanged() override; + void OnWindowTreeHostReusedForDisplay( + AshWindowTreeHost* window_tree_host, + const display::Display& display) override; + void OnWindowTreeHostsSwappedDisplays(AshWindowTreeHost* host1, + AshWindowTreeHost* host2) override; + // The shelf model shared by all shelf instances. ShelfModel model_; @@ -69,6 +79,9 @@ // The set of shelf observers notified about state and model changes. mojo::AssociatedInterfacePtrSet<mojom::ShelfObserver> observers_; + // Observes user profile prefs for the shelf. + std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_; + DISALLOW_COPY_AND_ASSIGN(ShelfController); };
diff --git a/ash/shelf/shelf_controller_unittest.cc b/ash/shelf/shelf_controller_unittest.cc index 65ecae8..852c688 100644 --- a/ash/shelf/shelf_controller_unittest.cc +++ b/ash/shelf/shelf_controller_unittest.cc
@@ -4,22 +4,31 @@ #include "ash/shelf/shelf_controller.h" -#include <set> #include <string> +#include "ash/public/cpp/ash_pref_names.h" #include "ash/public/cpp/config.h" #include "ash/public/cpp/shelf_model.h" #include "ash/public/cpp/shelf_model_observer.h" +#include "ash/public/cpp/shelf_prefs.h" #include "ash/public/interfaces/shelf.mojom.h" +#include "ash/root_window_controller.h" +#include "ash/session/test_session_controller_client.h" #include "ash/shelf/shelf.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" +#include "ash/test/ash_test_helper.h" +#include "ash/test_shell_delegate.h" +#include "components/prefs/testing_pref_service.h" #include "mojo/public/cpp/bindings/associated_binding.h" -#include "ui/display/types/display_constants.h" namespace ash { namespace { +Shelf* GetShelfForDisplay(int64_t display_id) { + return Shell::GetRootWindowControllerWithDisplayId(display_id)->shelf(); +} + // A test implementation of the ShelfObserver mojo interface. class TestShelfObserver : public mojom::ShelfObserver { public: @@ -27,19 +36,6 @@ ~TestShelfObserver() override = default; // mojom::ShelfObserver: - void OnShelfInitialized(int64_t display_id) override { - display_id_ = display_id; - } - void OnAlignmentChanged(ShelfAlignment alignment, - int64_t display_id) override { - alignment_ = alignment; - display_id_ = display_id; - } - void OnAutoHideBehaviorChanged(ShelfAutoHideBehavior auto_hide, - int64_t display_id) override { - auto_hide_ = auto_hide; - display_id_ = display_id; - } void OnShelfItemAdded(int32_t, const ShelfItem&) override { added_count_++; } void OnShelfItemRemoved(const ShelfID&) override { removed_count_++; } void OnShelfItemMoved(const ShelfID&, int32_t) override {} @@ -47,16 +43,10 @@ void OnShelfItemDelegateChanged(const ShelfID&, mojom::ShelfItemDelegatePtr) override {} - int64_t display_id() const { return display_id_; } - ShelfAlignment alignment() const { return alignment_; } - ShelfAutoHideBehavior auto_hide() const { return auto_hide_; } size_t added_count() const { return added_count_; } size_t removed_count() const { return removed_count_; } private: - int64_t display_id_ = display::kInvalidDisplayId; - ShelfAlignment alignment_ = SHELF_ALIGNMENT_BOTTOM_LOCKED; - ShelfAutoHideBehavior auto_hide_ = SHELF_AUTO_HIDE_ALWAYS_HIDDEN; size_t added_count_ = 0; size_t removed_count_ = 0; @@ -64,7 +54,6 @@ }; using ShelfControllerTest = AshTestBase; -using NoSessionShelfControllerTest = NoSessionAshTestBase; TEST_F(ShelfControllerTest, IntializesAppListItemDelegate) { ShelfModel* model = Shell::Get()->shelf_controller()->model(); @@ -77,34 +66,6 @@ EXPECT_FALSE(model->GetShelfItemDelegate(ShelfID(kChromeAppId))); } -TEST_F(NoSessionShelfControllerTest, AlignmentAndAutoHide) { - ShelfController* controller = Shell::Get()->shelf_controller(); - TestShelfObserver observer; - mojom::ShelfObserverAssociatedPtr observer_ptr; - mojo::AssociatedBinding<mojom::ShelfObserver> binding( - &observer, mojo::MakeIsolatedRequest(&observer_ptr)); - controller->AddObserver(observer_ptr.PassInterface()); - - // Simulated login should initialize the primary shelf and notify |observer|. - EXPECT_EQ(display::kInvalidDisplayId, observer.display_id()); - EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM_LOCKED, observer.alignment()); - EXPECT_EQ(SHELF_AUTO_HIDE_ALWAYS_HIDDEN, observer.auto_hide()); - SetUserLoggedIn(true); - SetSessionStarted(true); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(GetPrimaryDisplay().id(), observer.display_id()); - EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM, observer.alignment()); - EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, observer.auto_hide()); - - // Changing shelf properties should notify |observer|. - GetPrimaryShelf()->SetAlignment(SHELF_ALIGNMENT_LEFT); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(SHELF_ALIGNMENT_LEFT, observer.alignment()); - GetPrimaryShelf()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, observer.auto_hide()); -} - TEST_F(ShelfControllerTest, ShelfModelChangesInClassicAsh) { if (Shell::GetAshConfig() == Config::MASH) return; @@ -194,5 +155,159 @@ EXPECT_EQ(1u, observer.removed_count()); } +class ShelfControllerPrefsTest : public AshTestBase { + public: + ShelfControllerPrefsTest() = default; + ~ShelfControllerPrefsTest() override = default; + + void SetUp() override { + // TODO(crbug.com/753149): Refine apis to use TestPrefService in mash. + Shell::RegisterProfilePrefs(prefs_.registry()); + TestShellDelegate* delegate = new TestShellDelegate(); + delegate->set_active_user_pref_service(&prefs_); + ash_test_helper()->set_test_shell_delegate(delegate); + AshTestBase::SetUp(); + TestSessionControllerClient* session = GetSessionControllerClient(); + session->AddUserSession("user1@test.com"); + session->SetSessionState(session_manager::SessionState::ACTIVE); + session->SwitchActiveUser(AccountId::FromUserEmail("user1@test.com")); + } + + private: + TestingPrefServiceSimple prefs_; + + DISALLOW_COPY_AND_ASSIGN(ShelfControllerPrefsTest); +}; + +// Ensure shelf settings are updated on preference changes. +TEST_F(ShelfControllerPrefsTest, ShelfRespectsPrefs) { + Shelf* shelf = GetPrimaryShelf(); + EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM, shelf->alignment()); + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior()); + + PrefService* prefs = Shell::Get()->GetActiveUserPrefService(); + // TODO(crbug.com/753149): Enable with Mash GetActiveUserPrefService support. + EXPECT_EQ(Shell::GetAshConfig() == Config::MASH, prefs == nullptr); + if (Shell::GetAshConfig() == Config::MASH) + return; + + prefs->SetString(prefs::kShelfAlignmentLocal, "Left"); + prefs->SetString(prefs::kShelfAutoHideBehaviorLocal, "Always"); + + EXPECT_EQ(SHELF_ALIGNMENT_LEFT, shelf->alignment()); + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior()); +} + +// Ensure shelf settings are updated on per-display preference changes. +TEST_F(ShelfControllerPrefsTest, ShelfRespectsPerDisplayPrefs) { + UpdateDisplay("1024x768,800x600"); + base::RunLoop().RunUntilIdle(); + const int64_t id1 = GetPrimaryDisplay().id(); + const int64_t id2 = GetSecondaryDisplay().id(); + Shelf* shelf1 = GetShelfForDisplay(id1); + Shelf* shelf2 = GetShelfForDisplay(id2); + + EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM, shelf1->alignment()); + EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM, shelf2->alignment()); + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf1->auto_hide_behavior()); + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf2->auto_hide_behavior()); + + PrefService* prefs = Shell::Get()->GetActiveUserPrefService(); + // TODO(crbug.com/753149): Enable with Mash GetActiveUserPrefService support. + EXPECT_EQ(Shell::GetAshConfig() == Config::MASH, prefs == nullptr); + if (Shell::GetAshConfig() == Config::MASH) + return; + + SetShelfAlignmentPref(prefs, id1, SHELF_ALIGNMENT_LEFT); + SetShelfAlignmentPref(prefs, id2, SHELF_ALIGNMENT_RIGHT); + SetShelfAutoHideBehaviorPref(prefs, id1, SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); + SetShelfAutoHideBehaviorPref(prefs, id2, SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); + + EXPECT_EQ(SHELF_ALIGNMENT_LEFT, shelf1->alignment()); + EXPECT_EQ(SHELF_ALIGNMENT_RIGHT, shelf2->alignment()); + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf1->auto_hide_behavior()); + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf2->auto_hide_behavior()); +} + +// Ensure shelf settings are correct after display swap, see crbug.com/748291 +TEST_F(ShelfControllerPrefsTest, ShelfSettingsValidAfterDisplaySwap) { + // Simulate adding an external display at the lock screen. + GetSessionControllerClient()->RequestLockScreen(); + UpdateDisplay("1024x768,800x600"); + base::RunLoop().RunUntilIdle(); + const int64_t internal_display_id = GetPrimaryDisplay().id(); + const int64_t external_display_id = GetSecondaryDisplay().id(); + + // The primary shelf should be on the internal display. + EXPECT_EQ(GetPrimaryShelf(), GetShelfForDisplay(internal_display_id)); + EXPECT_NE(GetPrimaryShelf(), GetShelfForDisplay(external_display_id)); + + PrefService* prefs = Shell::Get()->GetActiveUserPrefService(); + // TODO(crbug.com/753149): Enable with Mash GetActiveUserPrefService support. + EXPECT_EQ(Shell::GetAshConfig() == Config::MASH, prefs == nullptr); + if (Shell::GetAshConfig() == Config::MASH) + return; + + // Check for the default shelf preferences. + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, + GetShelfAutoHideBehaviorPref(prefs, internal_display_id)); + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, + GetShelfAutoHideBehaviorPref(prefs, external_display_id)); + EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM, + GetShelfAlignmentPref(prefs, internal_display_id)); + EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM, + GetShelfAlignmentPref(prefs, external_display_id)); + + // Check the current state; shelves have locked alignments in the lock screen. + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, + GetShelfForDisplay(internal_display_id)->auto_hide_behavior()); + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, + GetShelfForDisplay(external_display_id)->auto_hide_behavior()); + EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM_LOCKED, + GetShelfForDisplay(internal_display_id)->alignment()); + EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM_LOCKED, + GetShelfForDisplay(external_display_id)->alignment()); + + // Set some shelf prefs to differentiate the two shelves, check state. + SetShelfAlignmentPref(prefs, internal_display_id, SHELF_ALIGNMENT_LEFT); + SetShelfAlignmentPref(prefs, external_display_id, SHELF_ALIGNMENT_RIGHT); + EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM_LOCKED, + GetShelfForDisplay(internal_display_id)->alignment()); + EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM_LOCKED, + GetShelfForDisplay(external_display_id)->alignment()); + + SetShelfAutoHideBehaviorPref(prefs, external_display_id, + SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, + GetShelfForDisplay(internal_display_id)->auto_hide_behavior()); + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, + GetShelfForDisplay(external_display_id)->auto_hide_behavior()); + + // Simulate the external display becoming the primary display. The shelves are + // swapped (each instance now has a different display id), check state. + SwapPrimaryDisplay(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM_LOCKED, + GetShelfForDisplay(internal_display_id)->alignment()); + EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM_LOCKED, + GetShelfForDisplay(external_display_id)->alignment()); + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, + GetShelfForDisplay(internal_display_id)->auto_hide_behavior()); + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, + GetShelfForDisplay(external_display_id)->auto_hide_behavior()); + + // After screen unlock the shelves should have the expected alignment values. + GetSessionControllerClient()->UnlockScreen(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(SHELF_ALIGNMENT_LEFT, + GetShelfForDisplay(internal_display_id)->alignment()); + EXPECT_EQ(SHELF_ALIGNMENT_RIGHT, + GetShelfForDisplay(external_display_id)->alignment()); + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, + GetShelfForDisplay(internal_display_id)->auto_hide_behavior()); + EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, + GetShelfForDisplay(external_display_id)->auto_hide_behavior()); +} + } // namespace } // namespace ash
diff --git a/ash/shelf/shelf_unittest.cc b/ash/shelf/shelf_unittest.cc index 8963ead..b87bbd34 100644 --- a/ash/shelf/shelf_unittest.cc +++ b/ash/shelf/shelf_unittest.cc
@@ -5,8 +5,6 @@ #include <utility> #include "ash/public/cpp/shelf_model.h" -#include "ash/root_window_controller.h" -#include "ash/session/test_session_controller_client.h" #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_button.h" #include "ash/shelf/shelf_controller.h" @@ -15,51 +13,16 @@ #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" -#include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "mojo/public/cpp/bindings/associated_binding.h" namespace ash { namespace { -Shelf* GetShelfForDisplay(int64_t display_id) { - return Shell::GetRootWindowControllerWithDisplayId(display_id)->shelf(); -} - -// Tracks shelf initialization display ids. -class ShelfInitializationObserver : public mojom::ShelfObserver { - public: - ShelfInitializationObserver() = default; - ~ShelfInitializationObserver() override = default; - - // mojom::ShelfObserver: - void OnShelfInitialized(int64_t display_id) override { - shelf_initialized_display_ids_.push_back(display_id); - } - void OnAlignmentChanged(ShelfAlignment alignment, - int64_t display_id) override {} - void OnAutoHideBehaviorChanged(ShelfAutoHideBehavior auto_hide, - int64_t display_id) override {} - void OnShelfItemAdded(int32_t, const ShelfItem&) override {} - void OnShelfItemRemoved(const ShelfID&) override {} - void OnShelfItemMoved(const ShelfID&, int32_t) override {} - void OnShelfItemUpdated(const ShelfItem&) override {} - void OnShelfItemDelegateChanged(const ShelfID&, - mojom::ShelfItemDelegatePtr) override {} - - std::vector<int64_t> shelf_initialized_display_ids_; - - private: - DISALLOW_COPY_AND_ASSIGN(ShelfInitializationObserver); -}; - -} // namespace - class ShelfTest : public AshTestBase { public: - ShelfTest() : shelf_model_(nullptr) {} - - ~ShelfTest() override {} + ShelfTest() = default; + ~ShelfTest() override = default; void SetUp() override { AshTestBase::SetUp(); @@ -75,7 +38,7 @@ ShelfViewTestAPI* test_api() { return test_.get(); } private: - ShelfModel* shelf_model_; + ShelfModel* shelf_model_ = nullptr; std::unique_ptr<ShelfViewTestAPI> test_; DISALLOW_COPY_AND_ASSIGN(ShelfTest); @@ -150,65 +113,5 @@ EXPECT_FALSE(shelf_widget->IsShowingOverflowBubble()); } -// Verifies that shelves are re-initialized after display swap, which will -// reload their alignment prefs. http://crbug.com/748291 -TEST_F(ShelfTest, ShelfInitializedOnDisplaySwap) { - ShelfController* controller = Shell::Get()->shelf_controller(); - ShelfInitializationObserver observer; - mojom::ShelfObserverAssociatedPtr observer_ptr; - mojo::AssociatedBinding<mojom::ShelfObserver> binding( - &observer, mojo::MakeIsolatedRequest(&observer_ptr)); - controller->AddObserver(observer_ptr.PassInterface()); - base::RunLoop().RunUntilIdle(); - ASSERT_EQ(0u, observer.shelf_initialized_display_ids_.size()); - - // Simulate adding an external display at the lock screen. The shelf on the - // new display is initialized. - GetSessionControllerClient()->RequestLockScreen(); - UpdateDisplay("1024x768,800x600"); - base::RunLoop().RunUntilIdle(); - const int64_t internal_display_id = GetPrimaryDisplay().id(); - const int64_t external_display_id = GetSecondaryDisplay().id(); - ASSERT_EQ(1u, observer.shelf_initialized_display_ids_.size()); - EXPECT_EQ(external_display_id, observer.shelf_initialized_display_ids_[0]); - observer.shelf_initialized_display_ids_.clear(); - - // Simulate the external display becoming the primary display. Each shelf is - // re-initialized. - SwapPrimaryDisplay(); - base::RunLoop().RunUntilIdle(); - ASSERT_EQ(2u, observer.shelf_initialized_display_ids_.size()); - EXPECT_TRUE(base::ContainsValue(observer.shelf_initialized_display_ids_, - internal_display_id)); - EXPECT_TRUE(base::ContainsValue(observer.shelf_initialized_display_ids_, - external_display_id)); - - // Simulate shelf state being set from prefs, which is how Chrome responds to - // the initialization request. - controller->SetAlignment(SHELF_ALIGNMENT_LEFT, internal_display_id); - controller->SetAlignment(SHELF_ALIGNMENT_RIGHT, external_display_id); - controller->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, - internal_display_id); - controller->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, - external_display_id); - - // Shelf is still locked to bottom because screen is locked. - EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM_LOCKED, - GetShelfForDisplay(internal_display_id)->alignment()); - EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM_LOCKED, - GetShelfForDisplay(external_display_id)->alignment()); - - // After screen unlock all shelves should have an alignment. - GetSessionControllerClient()->UnlockScreen(); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(SHELF_ALIGNMENT_LEFT, - GetShelfForDisplay(internal_display_id)->alignment()); - EXPECT_EQ(SHELF_ALIGNMENT_RIGHT, - GetShelfForDisplay(external_display_id)->alignment()); - EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, - GetShelfForDisplay(internal_display_id)->auto_hide_behavior()); - EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, - GetShelfForDisplay(external_display_id)->auto_hide_behavior()); -} - +} // namespace } // namespace ash
diff --git a/ash/shelf/shelf_window_watcher.cc b/ash/shelf/shelf_window_watcher.cc index 791d9707..e7f479e 100644 --- a/ash/shelf/shelf_window_watcher.cc +++ b/ash/shelf/shelf_window_watcher.cc
@@ -20,8 +20,6 @@ #include "ui/aura/client/aura_constants.h" #include "ui/aura/window.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/display/display.h" -#include "ui/display/screen.h" #include "ui/resources/grit/ui_resources.h" #include "ui/wm/public/activation_client.h" @@ -168,13 +166,13 @@ observed_container_windows_(&container_window_observer_), observed_user_windows_(&user_window_observer_) { Shell::Get()->activation_client()->AddObserver(this); - for (const auto& display : display::Screen::GetScreen()->GetAllDisplays()) - OnDisplayAdded(display); - display::Screen::GetScreen()->AddObserver(this); + Shell::Get()->AddShellObserver(this); + for (aura::Window* window : Shell::GetAllRootWindows()) + OnRootWindowAdded(window); } ShelfWindowWatcher::~ShelfWindowWatcher() { - display::Screen::GetScreen()->RemoveObserver(this); + Shell::Get()->RemoveShellObserver(this); Shell::Get()->activation_client()->RemoveObserver(this); } @@ -259,31 +257,15 @@ OnUserWindowPropertyChanged(lost_active); } -void ShelfWindowWatcher::OnDisplayAdded(const display::Display& new_display) { - aura::Window* root = Shell::GetRootWindowForDisplayId(new_display.id()); - - // When the primary root window's display is removed, the existing root window - // is taken over by the new display, and the observer is already set. - aura::Window* default_container = - root->GetChildById(kShellWindowId_DefaultContainer); - if (!observed_container_windows_.IsObserving(default_container)) { - for (aura::Window* window : default_container->children()) +void ShelfWindowWatcher::OnRootWindowAdded(aura::Window* root_window) { + constexpr int container_ids[] = {kShellWindowId_DefaultContainer, + kShellWindowId_PanelContainer}; + for (const int container_id : container_ids) { + aura::Window* container = root_window->GetChildById(container_id); + for (aura::Window* window : container->children()) OnUserWindowAdded(window); - observed_container_windows_.Add(default_container); - } - aura::Window* panel_container = - root->GetChildById(kShellWindowId_PanelContainer); - if (!observed_container_windows_.IsObserving(panel_container)) { - for (aura::Window* window : panel_container->children()) - OnUserWindowAdded(window); - observed_container_windows_.Add(panel_container); + observed_container_windows_.Add(container); } } -void ShelfWindowWatcher::OnDisplayRemoved(const display::Display& old_display) { -} - -void ShelfWindowWatcher::OnDisplayMetricsChanged(const display::Display&, - uint32_t) {} - } // namespace ash
diff --git a/ash/shelf/shelf_window_watcher.h b/ash/shelf/shelf_window_watcher.h index bacf303..c125bc0 100644 --- a/ash/shelf/shelf_window_watcher.h +++ b/ash/shelf/shelf_window_watcher.h
@@ -7,10 +7,10 @@ #include <set> +#include "ash/shell_observer.h" #include "base/macros.h" #include "base/scoped_observer.h" #include "ui/aura/window_observer.h" -#include "ui/display/display_observer.h" #include "ui/wm/public/activation_change_observer.h" namespace ash { @@ -24,7 +24,7 @@ // it until the window is closed, even if the window is transiently reparented // (e.g. during a drag). class ShelfWindowWatcher : public ::wm::ActivationChangeObserver, - public display::DisplayObserver { + public ShellObserver { public: explicit ShelfWindowWatcher(ShelfModel* model); ~ShelfWindowWatcher() override; @@ -91,11 +91,8 @@ aura::Window* gained_active, aura::Window* lost_active) override; - // display::DisplayObserver overrides: - void OnDisplayAdded(const display::Display& display) override; - void OnDisplayRemoved(const display::Display& old_display) override; - void OnDisplayMetricsChanged(const display::Display& display, - uint32_t metrics) override; + // ShellObserver: + void OnRootWindowAdded(aura::Window* root_window) override; ShelfModel* model_;
diff --git a/ash/shell.cc b/ash/shell.cc index 9b151c25..0ed1bb9 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -340,6 +340,7 @@ void Shell::RegisterProfilePrefs(PrefRegistrySimple* registry) { LogoutButtonTray::RegisterProfilePrefs(registry); NightLightController::RegisterProfilePrefs(registry); + ShelfController::RegisterProfilePrefs(registry); } views::NonClientFrameView* Shell::CreateDefaultNonClientFrameView( @@ -642,7 +643,6 @@ media_controller_(base::MakeUnique<MediaController>()), new_window_controller_(base::MakeUnique<NewWindowController>()), session_controller_(base::MakeUnique<SessionController>()), - shelf_controller_(base::MakeUnique<ShelfController>()), shell_delegate_(std::move(shell_delegate)), shutdown_controller_(base::MakeUnique<ShutdownController>()), system_tray_controller_(base::MakeUnique<SystemTrayController>()), @@ -873,6 +873,8 @@ void Shell::Init(const ShellInitParams& init_params) { const Config config = shell_port_->GetAshConfig(); + shelf_controller_ = base::MakeUnique<ShelfController>(); + if (NightLightController::IsFeatureEnabled()) night_light_controller_ = base::MakeUnique<NightLightController>();
diff --git a/ash/shell/app_list.cc b/ash/shell/app_list.cc index b6035a9c..3c32daf4 100644 --- a/ash/shell/app_list.cc +++ b/ash/shell/app_list.cc
@@ -296,6 +296,19 @@ bool IsSpeechRecognitionEnabled() override { return false; } + void GetWallpaperProminentColors(std::vector<SkColor>* colors) override { + NOTIMPLEMENTED(); + } + + void AddObserver(app_list::AppListViewDelegateObserver* observer) override { + NOTIMPLEMENTED(); + } + + void RemoveObserver( + app_list::AppListViewDelegateObserver* observer) override { + NOTIMPLEMENTED(); + } + std::unique_ptr<app_list::AppListModel> model_; app_list::SpeechUIModel speech_ui_;
diff --git a/ash/system/system_notifier.cc b/ash/system/system_notifier.cc index b094f7a..0bbf6118 100644 --- a/ash/system/system_notifier.cc +++ b/ash/system/system_notifier.cc
@@ -20,7 +20,7 @@ const char* kAlwaysShownSystemNotifierIds[] = { kNotifierAccessibility, kNotifierDeprecatedAccelerator, kNotifierBattery, kNotifierDisplay, kNotifierDisplayError, kNotifierNetworkError, - kNotifierPower, + kNotifierPower, kNotifierStylusBattery, // Note: Order doesn't matter here, so keep this in alphabetic order, don't // just add your stuff at the end! NULL}; @@ -76,6 +76,7 @@ const char kNotifierScreenShare[] = "ash.screen-share"; const char kNotifierSessionLengthTimeout[] = "ash.session-length-timeout"; const char kNotifierSms[] = "ash.sms"; +const char kNotifierStylusBattery[] = "ash.stylus-battery"; const char kNotifierSupervisedUser[] = "ash.locally-managed-user"; const char kNotifierTether[] = "ash.tether"; const char kNotifierWebUsb[] = "ash.webusb";
diff --git a/ash/system/system_notifier.h b/ash/system/system_notifier.h index ba5a5fa9..e9b0822 100644 --- a/ash/system/system_notifier.h +++ b/ash/system/system_notifier.h
@@ -38,6 +38,7 @@ ASH_EXPORT extern const char kNotifierScreenShare[]; ASH_EXPORT extern const char kNotifierSessionLengthTimeout[]; ASH_EXPORT extern const char kNotifierSms[]; +ASH_EXPORT extern const char kNotifierStylusBattery[]; ASH_EXPORT extern const char kNotifierSupervisedUser[]; ASH_EXPORT extern const char kNotifierTether[]; ASH_EXPORT extern const char kNotifierWebUsb[];
diff --git a/ash/test/ash_test_base.cc b/ash/test/ash_test_base.cc index 96fadf7..e7fe7ecd 100644 --- a/ash/test/ash_test_base.cc +++ b/ash/test/ash_test_base.cc
@@ -117,6 +117,10 @@ AshTestBase::AshTestBase() : setup_called_(false), teardown_called_(false), start_session_(true) { + if (AshTestHelper::config() != Config::CLASSIC) { + CHECK(aura::Env::GetInstance()); + aura::Env::GetInstance()->AddObserver(this); + } ash_test_environment_ = AshTestEnvironment::Create(); // Must initialize |ash_test_helper_| here because some tests rely on @@ -129,21 +133,8 @@ << "You have overridden SetUp but never called AshTestBase::SetUp"; CHECK(teardown_called_) << "You have overridden TearDown but never called AshTestBase::TearDown"; -} - -void AshTestBase::UnblockCompositors() { - // In order for frames to be generated, a viz::LocalSurfaceId must be given to - // the ui::Compositor. Normally that viz::LocalSurfaceId comes from the window - // server but in unit tests, there is no window server so we just make up a - // viz::LocalSurfaceId to allow the layer compositor to make forward progress. - if (Shell::GetAshConfig() == Config::MUS || - Shell::GetAshConfig() == Config::MASH) { - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - for (aura::Window* root : root_windows) { - viz::LocalSurfaceId id(1, base::UnguessableToken::Create()); - root->GetHost()->compositor()->SetLocalSurfaceId(id); - } - } + if (AshTestHelper::config() != Config::CLASSIC) + aura::Env::GetInstance()->RemoveObserver(this); } void AshTestBase::SetUp() { @@ -164,8 +155,6 @@ if (Shell::GetAshConfig() == Config::CLASSIC) Shell::Get()->cursor_manager()->EnableMouseEvents(); - UnblockCompositors(); - // Changing GestureConfiguration shouldn't make tests fail. These values // prevent unexpected events from being generated during tests. Such as // delayed events which create race conditions on slower tests. @@ -180,10 +169,6 @@ teardown_called_ = true; Shell::Get()->session_controller()->NotifyChromeTerminating(); - // Some tasks are blocked on progress by the layer compositor. The layer - // compositor might be blocked if created during a unit test. - UnblockCompositors(); - // Flush the message loop to finish pending release tasks. RunAllPendingInMessageLoop(); @@ -229,7 +214,6 @@ void AshTestBase::UpdateDisplay(const std::string& display_specs) { display::test::DisplayManagerTestApi(Shell::Get()->display_manager()) .UpdateDisplay(display_specs); - UnblockCompositors(); } aura::Window* AshTestBase::CurrentContext() { @@ -482,4 +466,21 @@ return ash_test_helper_->GetSecondaryDisplay(); } +void AshTestBase::OnWindowInitialized(aura::Window* window) {} + +void AshTestBase::OnHostInitialized(aura::WindowTreeHost* host) { + // AshTestBase outlives all the WindowTreeHosts. So RemoveObserver() is not + // necessary. + host->AddObserver(this); + OnHostResized(host); +} + +void AshTestBase::OnHostResized(aura::WindowTreeHost* host) { + // The local surface id comes from the window server. However, there is no + // window server in tests. So a fake id is assigned so that the layer + // compositor can submit compositor frames. + viz::LocalSurfaceId id(1, base::UnguessableToken::Create()); + host->compositor()->SetLocalSurfaceId(id); +} + } // namespace ash
diff --git a/ash/test/ash_test_base.h b/ash/test/ash_test_base.h index 68ef2c23..34125cf 100644 --- a/ash/test/ash_test_base.h +++ b/ash/test/ash_test_base.h
@@ -17,6 +17,8 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/aura/client/window_types.h" +#include "ui/aura/env_observer.h" +#include "ui/aura/window_tree_host_observer.h" #include "ui/display/display.h" namespace aura { @@ -57,15 +59,13 @@ class TestScreenshotDelegate; class TestSessionControllerClient; -class AshTestBase : public testing::Test { +class AshTestBase : public testing::Test, + public aura::EnvObserver, + public aura::WindowTreeHostObserver { public: AshTestBase(); ~AshTestBase() override; - // Give all ui::Compositors a valid viz::LocalSurfaceId so that they can - // unblock cc::LayerTreeHost. - void UnblockCompositors(); - // testing::Test: void SetUp() override; void TearDown() override; @@ -198,6 +198,13 @@ display::Display GetSecondaryDisplay(); private: + // aura::EnvObserver: + void OnWindowInitialized(aura::Window* window) override; + void OnHostInitialized(aura::WindowTreeHost* host) override; + + // aura::WindowTreeHostObserver: + void OnHostResized(aura::WindowTreeHost* host) override; + bool setup_called_; bool teardown_called_; // |SetUp()| doesn't activate session if this is set to false.
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc index b79db51e..39c54bc 100644 --- a/ash/wallpaper/wallpaper_controller.cc +++ b/ash/wallpaper/wallpaper_controller.cc
@@ -302,6 +302,19 @@ session_manager::SessionState state) { CalculateWallpaperColors(); + // The wallpaper may be dimmed/blurred based on session state. The color of + // the dimming overlay depends on the prominent color cached from a previous + // calculation, or a default color if cache is not available. It should never + // depend on any in-flight color calculation. + if (wallpaper_mode_ == WALLPAPER_IMAGE && + (state == session_manager::SessionState::ACTIVE || + state == session_manager::SessionState::LOCKED || + state == session_manager::SessionState::LOGIN_SECONDARY)) { + // TODO(crbug.com/753518): Reuse the existing WallpaperWidgetController for + // dimming/blur purpose. + InstallDesktopControllerForAllWindows(); + } + if (state == session_manager::SessionState::ACTIVE) MoveToUnlockedContainer(); else
diff --git a/ash/wallpaper/wallpaper_view.cc b/ash/wallpaper/wallpaper_view.cc index 17f34a1..ec74bc7 100644 --- a/ash/wallpaper/wallpaper_view.cc +++ b/ash/wallpaper/wallpaper_view.cc
@@ -4,6 +4,7 @@ #include "ash/wallpaper/wallpaper_view.h" +#include "ash/login/ui/login_constants.h" #include "ash/root_window_controller.h" #include "ash/session/session_controller.h" #include "ash/shell.h" @@ -18,6 +19,8 @@ #include "ui/display/manager/managed_display_info.h" #include "ui/display/screen.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/color_analysis.h" +#include "ui/gfx/color_utils.h" #include "ui/gfx/geometry/safe_integer_conversions.h" #include "ui/gfx/geometry/size_conversions.h" #include "ui/gfx/transform.h" @@ -71,6 +74,23 @@ DISALLOW_COPY_AND_ASSIGN(LayerControlView); }; +// Returns the color used to darken the wallpaper, needed by login, lock, OOBE +// and add user screens. +SkColor GetWallpaperDarkenColor() { + SkColor darken_color = + Shell::Get()->wallpaper_controller()->GetProminentColor( + color_utils::ColorProfile(color_utils::LumaRange::DARK, + color_utils::SaturationRange::MUTED)); + if (darken_color == WallpaperController::kInvalidColor) + darken_color = login_constants::kDefaultBaseColor; + + darken_color = color_utils::GetResultingPaintColor( + SkColorSetA(login_constants::kDefaultBaseColor, + login_constants::kTranslucentColorDarkenAlpha), + SkColorSetA(darken_color, 0xFF)); + return SkColorSetA(darken_color, login_constants::kTranslucentAlpha); +} + } // namespace // This event handler receives events in the pre-target phase and takes care of @@ -139,6 +159,12 @@ if (wallpaper.isNull()) return; + cc::PaintFlags flags; + if (Shell::Get()->session_controller()->IsUserSessionBlocked()) { + flags.setColorFilter(SkColorFilter::MakeModeFilter( + GetWallpaperDarkenColor(), SkBlendMode::kDarken)); + } + if (layout == wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED) { // The dimension with the smallest ratio must be cropped, the other one // is preserved. Both are set in gfx::Size cropped_size. @@ -164,13 +190,14 @@ canvas->DrawImageInt( wallpaper, wallpaper_cropped_rect.x(), wallpaper_cropped_rect.y(), wallpaper_cropped_rect.width(), wallpaper_cropped_rect.height(), 0, 0, - width(), height(), true); + width(), height(), true, flags); } else if (layout == wallpaper::WALLPAPER_LAYOUT_TILE) { - canvas->TileImageInt(wallpaper, 0, 0, width(), height()); + canvas->TileImageInt(wallpaper, 0, 0, 0, 0, width(), height(), 1.0f, + &flags); } else if (layout == wallpaper::WALLPAPER_LAYOUT_STRETCH) { // This is generally not recommended as it may show artifacts. canvas->DrawImageInt(wallpaper, 0, 0, wallpaper.width(), wallpaper.height(), - 0, 0, width(), height(), true); + 0, 0, width(), height(), true, flags); } else { float image_scale = canvas->image_scale(); gfx::Rect wallpaper_rect(0, 0, wallpaper.width() / image_scale, @@ -179,7 +206,8 @@ canvas->DrawImageInt(wallpaper, 0, 0, wallpaper.width(), wallpaper.height(), (width() - wallpaper_rect.width()) / 2, (height() - wallpaper_rect.height()) / 2, - wallpaper_rect.width(), wallpaper_rect.height(), true); + wallpaper_rect.width(), wallpaper_rect.height(), true, + flags); } } @@ -235,6 +263,9 @@ aura::Window* container = root_window->GetChildById(container_id); wallpaper_widget->SetBounds(container->bounds()); + if (Shell::Get()->session_controller()->IsUserSessionBlocked()) + wallpaper_widget->GetLayer()->SetLayerBlur(login_constants::kBlurSigma); + return wallpaper_widget; }
diff --git a/ash/wm/lock_state_controller.cc b/ash/wm/lock_state_controller.cc index 3bc2f11..f2382820 100644 --- a/ash/wm/lock_state_controller.cc +++ b/ash/wm/lock_state_controller.cc
@@ -208,8 +208,7 @@ lock_screen_displayed_callback_ = std::move(callback); } -void LockStateController::OnHostCloseRequested( - const aura::WindowTreeHost* host) { +void LockStateController::OnHostCloseRequested(aura::WindowTreeHost* host) { Shell::Get()->shell_delegate()->Exit(); }
diff --git a/ash/wm/lock_state_controller.h b/ash/wm/lock_state_controller.h index bfafc43..564ece3 100644 --- a/ash/wm/lock_state_controller.h +++ b/ash/wm/lock_state_controller.h
@@ -106,7 +106,7 @@ void SetLockScreenDisplayedCallback(base::OnceClosure callback); // aura::WindowTreeHostObserver override: - void OnHostCloseRequested(const aura::WindowTreeHost* host) override; + void OnHostCloseRequested(aura::WindowTreeHost* host) override; // SessionObserver overrides: void OnChromeTerminating() override;
diff --git a/base/compiler_specific.h b/base/compiler_specific.h index 6389330..7d474f4 100644 --- a/base/compiler_specific.h +++ b/base/compiler_specific.h
@@ -137,7 +137,7 @@ // |dots_param| is the one-based index of the "..." parameter. // For v*printf functions (which take a va_list), pass 0 for dots_param. // (This is undocumented but matches what the system C headers do.) -#if defined(COMPILER_GCC) +#if defined(COMPILER_GCC) || defined(__clang__) #define PRINTF_FORMAT(format_param, dots_param) \ __attribute__((format(printf, format_param, dots_param))) #else
diff --git a/base/files/scoped_file.cc b/base/files/scoped_file.cc index 78d4ca52..df702bd 100644 --- a/base/files/scoped_file.cc +++ b/base/files/scoped_file.cc
@@ -11,7 +11,6 @@ #include <errno.h> #include <unistd.h> -#include "base/debug/alias.h" #include "base/posix/eintr_wrapper.h" #endif @@ -31,16 +30,11 @@ // a single open directory would bypass the entire security model. int ret = IGNORE_EINTR(close(fd)); - // TODO(davidben): Remove this once it's been determined whether - // https://crbug.com/603354 is caused by EBADF or a network filesystem - // returning some other error. - int close_errno = errno; - base::debug::Alias(&close_errno); - -#if defined(OS_LINUX) +#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_FUCHSIA) // NB: Some file descriptors can return errors from close() e.g. network - // filesystems such as NFS and Linux input devices. On Linux, errors from - // close other than EBADF do not indicate failure to actually close the fd. + // filesystems such as NFS and Linux input devices. On Linux, macOS, and + // Fuchsia's POSIX layer, errors from close other than EBADF do not indicate + // failure to actually close the fd. if (ret != 0 && errno != EBADF) ret = 0; #endif
diff --git a/base/process/process_fuchsia.cc b/base/process/process_fuchsia.cc index eb64f61..1c421a75 100644 --- a/base/process/process_fuchsia.cc +++ b/base/process/process_fuchsia.cc
@@ -23,12 +23,14 @@ Process::Process(Process&& other) : process_(other.process_), is_current_process_(other.is_current_process_) { other.process_ = kNullProcessHandle; + other.is_current_process_ = false; } Process& Process::operator=(Process&& other) { process_ = other.process_; other.process_ = kNullProcessHandle; is_current_process_ = other.is_current_process_; + other.is_current_process_ = false; return *this; }
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java b/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java index ac5dbfc..7d7d99c 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java +++ b/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java
@@ -18,6 +18,8 @@ import org.chromium.base.Log; import org.chromium.base.multidex.ChromiumMultiDexInstaller; +import java.io.IOException; + /** * A custom AndroidJUnitRunner that supports multidex installer and list out test information. * @@ -28,6 +30,20 @@ public class BaseChromiumAndroidJUnitRunner extends AndroidJUnitRunner { private static final String LIST_ALL_TESTS_FLAG = "org.chromium.base.test.BaseChromiumAndroidJUnitRunner.TestList"; + + /** + * The following arguments are corresponding to AndroidJUnitRunner command line arguments. + * `annotation`: run with only the argument annotation + * `notAnnotation`: run all tests except the ones with argument annotation + * `log`: run in log only mode, do not execute tests + * + * For more detail, please check + * https://developer.android.com/reference/android/support/test/runner/AndroidJUnitRunner.html + */ + private static final String ARGUMENT_ANNOTATION = "annotation"; + private static final String ARGUMENT_NOT_ANNOTATION = "notAnnotation"; + private static final String ARGUMENT_LOG_ONLY = "log"; + private static final String TAG = "BaseJUnitRunner"; private Bundle mArguments; @@ -66,13 +82,29 @@ private void listTests() { Bundle results = new Bundle(); + TestListInstrumentationRunListener listener = new TestListInstrumentationRunListener(); try { TestExecutor.Builder executorBuilder = new TestExecutor.Builder(this); - executorBuilder.addRunListener(new TestListInstrumentationRunListener( - mArguments.getString(LIST_ALL_TESTS_FLAG))); - TestRequest listTestRequest = createListTestRequest(mArguments); - results = executorBuilder.build().execute(listTestRequest); - } catch (RuntimeException e) { + executorBuilder.addRunListener(listener); + Bundle junit3Arguments = new Bundle(mArguments); + junit3Arguments.putString(ARGUMENT_NOT_ANNOTATION, "org.junit.runner.RunWith"); + TestRequest listJUnit3TestRequest = createListTestRequest(junit3Arguments); + results = executorBuilder.build().execute(listJUnit3TestRequest); + + Bundle junit4Arguments = new Bundle(mArguments); + junit4Arguments.putString(ARGUMENT_ANNOTATION, "org.junit.runner.RunWith"); + + // Do not use Log runner from android test support. + // + // Test logging and execution skipping is handled by BaseJUnit4ClassRunner, + // having ARGUMENT_LOG_ONLY in argument bundle here causes AndroidJUnitRunner + // to use its own log-only class runner instead of BaseJUnit4ClassRunner. + junit4Arguments.remove(ARGUMENT_LOG_ONLY); + + TestRequest listJUnit4TestRequest = createListTestRequest(junit4Arguments); + results.putAll(executorBuilder.build().execute(listJUnit4TestRequest)); + listener.saveTestsToJson(mArguments.getString(LIST_ALL_TESTS_FLAG)); + } catch (IOException | RuntimeException e) { String msg = "Fatal exception when running tests"; Log.e(TAG, msg, e); // report the exception to instrumentation out @@ -90,4 +122,8 @@ builder.addFromRunnerArgs(runnerArgs); return builder.build(); } + + static boolean shouldListTests(Bundle arguments) { + return arguments != null && arguments.getString(LIST_ALL_TESTS_FLAG) != null; + } }
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java b/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java index 080654f8..382e675e 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java +++ b/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java
@@ -4,11 +4,14 @@ package org.chromium.base.test; +import static org.chromium.base.test.BaseChromiumAndroidJUnitRunner.shouldListTests; + import android.content.Context; import android.support.test.InstrumentationRegistry; import android.support.test.internal.runner.junit4.AndroidJUnit4ClassRunner; import android.support.test.internal.util.AndroidRunnerParams; +import org.junit.runner.Description; import org.junit.runner.notification.RunNotifier; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.InitializationError; @@ -129,6 +132,21 @@ return super.isIgnored(method) || shouldSkip(method); } + /** + * Run test with or without execution based on bundle arguments. + */ + @Override + public void run(RunNotifier notifier) { + if (shouldListTests(InstrumentationRegistry.getArguments())) { + for (Description child : getDescription().getChildren()) { + notifier.fireTestStarted(child); + notifier.fireTestFinished(child); + } + } else { + super.run(notifier); + } + } + @Override protected void runChild(FrameworkMethod method, RunNotifier notifier) { runPreTestHooks(method);
diff --git a/base/test/android/javatests/src/org/chromium/base/test/TestListInstrumentationRunListener.java b/base/test/android/javatests/src/org/chromium/base/test/TestListInstrumentationRunListener.java index 71fa4e0..8cde5700 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/TestListInstrumentationRunListener.java +++ b/base/test/android/javatests/src/org/chromium/base/test/TestListInstrumentationRunListener.java
@@ -9,7 +9,6 @@ import org.json.JSONArray; import org.json.JSONObject; import org.junit.runner.Description; -import org.junit.runner.Result; import org.chromium.base.Log; @@ -36,12 +35,6 @@ Arrays.asList(new String[] {"toString", "hashCode", "annotationType", "equals"})); private final Map<Class<?>, JSONObject> mTestClassJsonMap = new HashMap<>(); - private final String mOutputPath; - - public TestListInstrumentationRunListener(String outputPath) { - super(); - mOutputPath = outputPath; - } /** * Store the test method description to a Map at the beginning of a test run. @@ -65,10 +58,9 @@ /** * Create a JSONArray with all the test class JSONObjects and save it to listed output path. */ - @Override - public void testRunFinished(Result result) throws IOException { + public void saveTestsToJson(String outputPath) throws IOException { Writer writer = null; - File file = new File(mOutputPath); + File file = new File(outputPath); try { writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8"); JSONArray allTestClassesJSON = new JSONArray(mTestClassJsonMap.values());
diff --git a/build/config/android/config.gni b/build/config/android/config.gni index a00b29cc..1ff5744 100644 --- a/build/config/android/config.gni +++ b/build/config/android/config.gni
@@ -157,10 +157,6 @@ # abi in 64-bit Monochrome and WebView. build_apk_secondary_abi = true - # Enables java8 language features (via Desugar). - # work-in-progress (http://crbug.com/730711) - use_java8 = false - # Build incremental targets whenever possible. # Ex. with this arg set to true, the chrome_public_apk target result in # chrome_public_apk_incremental being built.
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index a30316e..4228f64 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -1196,10 +1196,8 @@ defined(invoker.supports_android) && invoker.supports_android && (is_java_debug || dcheck_always_on) - _desugar = - defined(invoker.supports_android) && invoker.supports_android && - ((defined(invoker.process_java8) && invoker.process_java8) || use_java8) - + _desugar = defined(invoker.supports_android) && invoker.supports_android + _deps = [] _previous_output_jar = _input_jar_path @@ -2070,7 +2068,6 @@ forward_variables_from(invoker, [ "jar_excluded_patterns", - "process_java8", "strip_resource_classes", ]) @@ -2298,6 +2295,7 @@ "--jar-path=$_rebased_jar_path", "--java-srcjars=$_rebased_java_srcjars", "--java-srcjars=@FileArg($_rebased_build_config:javac:srcjars)", + "--java-version=1.8", ] if (_enable_interface_jars_javac) { args += [ "--classpath=@FileArg($_rebased_build_config:javac:interface_classpath)" ] @@ -2324,11 +2322,6 @@ rebase_path(_android_sdk_ijar, root_build_dir) args += [ "--bootclasspath=$_rebased_android_sdk_ijar" ] } - if (use_java8) { - args += [ "--java-version=1.8" ] - } else if (_supports_android) { - args += [ "--java-version=1.7" ] - } foreach(e, _manifest_entries) { args += [ "--manifest-entry=" + e ] }
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 9e24195..648b14fe 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -1272,8 +1272,6 @@ # supports_android: If true, Android targets (android_library, android_apk) # may depend on this target. Note: if true, this target must only use the # subset of Java available on Android. - # process_java8: The specified prebuilt jar contains Java 8 bytecode; - # process it for compatibility with Java 7. # # Example # java_prebuilt("foo_java") { @@ -1492,8 +1490,6 @@ # Defaults to the input .jar file name. # proguard_configs: List of proguard configs to use in final apk step for # any apk that depends on this library. - # process_java8: The specified prebuilt jar contains Java 8 bytecode; - # process it for compatibility with Java 7. # # Example # android_java_prebuilt("foo_java") {
diff --git a/cc/input/layer_selection_bound.cc b/cc/input/layer_selection_bound.cc index c6a6030..1799f77e 100644 --- a/cc/input/layer_selection_bound.cc +++ b/cc/input/layer_selection_bound.cc
@@ -8,14 +8,15 @@ namespace cc { LayerSelectionBound::LayerSelectionBound() - : type(gfx::SelectionBound::EMPTY), layer_id(0) {} + : type(gfx::SelectionBound::EMPTY), layer_id(0), hidden(false) {} LayerSelectionBound::~LayerSelectionBound() { } bool LayerSelectionBound::operator==(const LayerSelectionBound& other) const { return type == other.type && layer_id == other.layer_id && - edge_top == other.edge_top && edge_bottom == other.edge_bottom; + edge_top == other.edge_top && edge_bottom == other.edge_bottom && + hidden == other.hidden; } bool LayerSelectionBound::operator!=(const LayerSelectionBound& other) const {
diff --git a/cc/input/layer_selection_bound.h b/cc/input/layer_selection_bound.h index abadc3c..f69d1548 100644 --- a/cc/input/layer_selection_bound.h +++ b/cc/input/layer_selection_bound.h
@@ -22,6 +22,9 @@ gfx::Point edge_top; gfx::Point edge_bottom; int layer_id; + // Whether this bound is hidden (clipped out/occluded) within the painted + // content of the layer (as opposed to being outside of the layer's bounds). + bool hidden; bool operator==(const LayerSelectionBound& other) const; bool operator!=(const LayerSelectionBound& other) const;
diff --git a/cc/ipc/BUILD.gn b/cc/ipc/BUILD.gn index f3714f9..477bd02 100644 --- a/cc/ipc/BUILD.gn +++ b/cc/ipc/BUILD.gn
@@ -49,7 +49,6 @@ "local_surface_id.mojom", "quads.mojom", "render_pass.mojom", - "returned_resource.mojom", "selection.mojom", "shared_bitmap_allocation_notifier.mojom", "shared_quad_state.mojom",
diff --git a/cc/ipc/returned_resource.typemap b/cc/ipc/returned_resource.typemap deleted file mode 100644 index 414ed5bb..0000000 --- a/cc/ipc/returned_resource.typemap +++ /dev/null
@@ -1,15 +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. - -mojom = "//cc/ipc/returned_resource.mojom" -public_headers = [ "//components/viz/common/resources/returned_resource.h" ] -traits_headers = [ "//cc/ipc/returned_resource_struct_traits.h" ] -deps = [ - "//components/viz/common", - "//gpu/command_buffer/common", -] -type_mappings = [ - "cc.mojom.ReturnedResource=viz::ReturnedResource", - "cc.mojom.ReturnedResourceArray=viz::ReturnedResourceArray", -]
diff --git a/cc/ipc/struct_traits_unittest.cc b/cc/ipc/struct_traits_unittest.cc index 95877e8..0586f98 100644 --- a/cc/ipc/struct_traits_unittest.cc +++ b/cc/ipc/struct_traits_unittest.cc
@@ -82,11 +82,6 @@ std::move(callback).Run(std::move(r)); } - void EchoReturnedResource(const viz::ReturnedResource& r, - EchoReturnedResourceCallback callback) override { - std::move(callback).Run(r); - } - void EchoSelection(const Selection<gfx::SelectionBound>& s, EchoSelectionCallback callback) override { std::move(callback).Run(s); @@ -848,32 +843,6 @@ EXPECT_EQ(color_space, output->color_space); } -TEST_F(StructTraitsTest, ReturnedResource) { - const RenderPassId id = 1337u; - const gpu::CommandBufferNamespace command_buffer_namespace = gpu::IN_PROCESS; - const int32_t extra_data_field = 0xbeefbeef; - const gpu::CommandBufferId command_buffer_id( - gpu::CommandBufferId::FromUnsafeValue(0xdeadbeef)); - const uint64_t release_count = 0xdeadbeefdead; - const gpu::SyncToken sync_token(command_buffer_namespace, extra_data_field, - command_buffer_id, release_count); - const int count = 1234; - const bool lost = true; - - viz::ReturnedResource input; - input.id = id; - input.sync_token = sync_token; - input.count = count; - input.lost = lost; - mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy(); - viz::ReturnedResource output; - proxy->EchoReturnedResource(input, &output); - EXPECT_EQ(id, output.id); - EXPECT_EQ(sync_token, output.sync_token); - EXPECT_EQ(count, output.count); - EXPECT_EQ(lost, output.lost); -} - TEST_F(StructTraitsTest, Selection) { gfx::SelectionBound start; start.SetEdge(gfx::PointF(1234.5f, 67891.f), gfx::PointF(5432.1f, 1987.6f));
diff --git a/cc/ipc/traits_test_service.mojom b/cc/ipc/traits_test_service.mojom index 6ae6939..d38c0d752 100644 --- a/cc/ipc/traits_test_service.mojom +++ b/cc/ipc/traits_test_service.mojom
@@ -12,7 +12,6 @@ import "cc/ipc/filter_operations.mojom"; import "cc/ipc/quads.mojom"; import "cc/ipc/render_pass.mojom"; -import "cc/ipc/returned_resource.mojom"; import "cc/ipc/selection.mojom"; import "cc/ipc/shared_quad_state.mojom"; import "cc/ipc/surface_id.mojom"; @@ -49,9 +48,6 @@ EchoRenderPass(RenderPass r) => (RenderPass pass); [Sync] - EchoReturnedResource(ReturnedResource r) => (ReturnedResource pass); - - [Sync] EchoSelection(Selection s) => (Selection pass); [Sync]
diff --git a/cc/ipc/typemaps.gni b/cc/ipc/typemaps.gni index b5d695ce..017deb2 100644 --- a/cc/ipc/typemaps.gni +++ b/cc/ipc/typemaps.gni
@@ -12,7 +12,6 @@ "//cc/ipc/frame_sink_id.typemap", "//cc/ipc/local_surface_id.typemap", "//cc/ipc/render_pass.typemap", - "//cc/ipc/returned_resource.typemap", "//cc/ipc/selection.typemap", "//cc/ipc/shared_quad_state.typemap", "//cc/ipc/surface_id.typemap",
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index 9cfb45e..26d2084 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc
@@ -932,9 +932,30 @@ const auto& transform = ScreenSpaceTransform(); if (transform.HasPerspective()) { float scale = MathUtil::ComputeApproximateMaxScale(transform); + + const int kMaxTilesToCoverLayerDimension = 5; + // Cap the scale in a way that it should be covered by at most + // |kMaxTilesToCoverLayerDimension|^2 default tile sizes. If this is left + // uncapped, then we can fairly easily use too much memory (or too many + // tiles). See crbug.com/752382 for an example of such a page. Note that + // because this is an approximation anyway, it's fine to use a smaller scale + // that desired. On top of this, the layer has a perspective transform so + // technically it could all be within the viewport, so it's important for us + // to have a reasonable scale here. The scale we use would also be at least + // |default_scale|, as checked below. + float scale_cap = std::min( + (layer_tree_impl()->settings().default_tile_size.width() - 2) * + kMaxTilesToCoverLayerDimension / + static_cast<float>(bounds().width()), + (layer_tree_impl()->settings().default_tile_size.height() - 2) * + kMaxTilesToCoverLayerDimension / + static_cast<float>(bounds().height())); + scale = std::min(scale, scale_cap); + // Since we're approximating the scale anyway, round it to the nearest // integer to prevent jitter when animating the transform. scale = std::round(scale); + // Don't let the scale fall below the default scale. return std::max(scale, default_scale); }
diff --git a/cc/layers/layer_impl_unittest.cc b/cc/layers/layer_impl_unittest.cc index 733f29e..560e84d 100644 --- a/cc/layers/layer_impl_unittest.cc +++ b/cc/layers/layer_impl_unittest.cc
@@ -444,6 +444,7 @@ &task_graph_runner); auto owned_layer = LayerImpl::Create(host_impl.active_tree(), 1); LayerImpl* layer = owned_layer.get(); + layer->SetBounds(gfx::Size(10, 10)); layer->set_contributes_to_drawn_render_surface(true); host_impl.active_tree()->SetRootLayerForTesting(std::move(owned_layer)); host_impl.active_tree()->BuildLayerListAndPropertyTreesForTesting(); @@ -468,6 +469,16 @@ ASSERT_TRUE(layer->ScreenSpaceTransform().HasPerspective()); EXPECT_FLOAT_EQ(1.f, layer->GetIdealContentsScale()); } + // Ensure that large scales don't end up extremely large. + { + gfx::Transform transform; + transform.Scale(10000.1f, 10000.2f); + transform.ApplyPerspectiveDepth(10); + layer->draw_properties().screen_space_transform = transform; + + ASSERT_TRUE(layer->ScreenSpaceTransform().HasPerspective()); + EXPECT_FLOAT_EQ(127.f, layer->GetIdealContentsScale()); + } } class LayerImplScrollTest : public testing::Test {
diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc index 564a8fe..7276dea8 100644 --- a/cc/layers/video_layer_impl.cc +++ b/cc/layers/video_layer_impl.cc
@@ -131,7 +131,8 @@ external_resources.mailboxes[i], SingleReleaseCallbackImpl::Create( external_resources.release_callbacks[i]), - external_resources.read_lock_fences_enabled); + external_resources.read_lock_fences_enabled, + external_resources.buffer_format); frame_resources_.push_back(FrameResource( resource_id, external_resources.mailboxes[i].size_in_pixels(), external_resources.mailboxes[i].is_overlay_candidate()));
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc index 494111ef..272d2fa 100644 --- a/cc/resources/resource_provider.cc +++ b/cc/resources/resource_provider.cc
@@ -660,7 +660,8 @@ viz::ResourceId ResourceProvider::CreateResourceFromTextureMailbox( const viz::TextureMailbox& mailbox, std::unique_ptr<SingleReleaseCallbackImpl> release_callback_impl, - bool read_lock_fences_enabled) { + bool read_lock_fences_enabled, + gfx::BufferFormat buffer_format) { DCHECK(thread_checker_.CalledOnValidThread()); // Just store the information. Mailbox will be consumed in LockForRead(). viz::ResourceId id = next_id_++; @@ -689,6 +690,7 @@ base::Bind(&SingleReleaseCallbackImpl::Run, base::Owned(release_callback_impl.release())); resource->read_lock_fences_enabled = read_lock_fences_enabled; + resource->buffer_format = buffer_format; resource->is_overlay_candidate = mailbox.is_overlay_candidate(); #if defined(OS_ANDROID) resource->is_backed_by_surface_texture = @@ -704,6 +706,15 @@ viz::ResourceId ResourceProvider::CreateResourceFromTextureMailbox( const viz::TextureMailbox& mailbox, + std::unique_ptr<SingleReleaseCallbackImpl> release_callback_impl, + bool read_lock_fences_enabled) { + return CreateResourceFromTextureMailbox( + mailbox, std::move(release_callback_impl), read_lock_fences_enabled, + gfx::BufferFormat::RGBA_8888); +} + +viz::ResourceId ResourceProvider::CreateResourceFromTextureMailbox( + const viz::TextureMailbox& mailbox, std::unique_ptr<SingleReleaseCallbackImpl> release_callback_impl) { return CreateResourceFromTextureMailbox( mailbox, std::move(release_callback_impl), false);
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h index 55efcdc2..72ff12e69 100644 --- a/cc/resources/resource_provider.h +++ b/cc/resources/resource_provider.h
@@ -160,6 +160,12 @@ std::unique_ptr<SingleReleaseCallbackImpl> release_callback_impl, bool read_lock_fences_enabled); + viz::ResourceId CreateResourceFromTextureMailbox( + const viz::TextureMailbox& mailbox, + std::unique_ptr<SingleReleaseCallbackImpl> release_callback_impl, + bool read_lock_fences_enabled, + gfx::BufferFormat buffer_format); + void DeleteResource(viz::ResourceId id); // In the case of GPU resources, we may need to flush the GL context to ensure // that texture deletions are seen in a timely fashion. This function should
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc index d0787c9..e78e1d002 100644 --- a/cc/resources/video_resource_updater.cc +++ b/cc/resources/video_resource_updater.cc
@@ -35,7 +35,9 @@ VideoFrameExternalResources::ResourceType ResourceTypeForVideoFrame( media::VideoFrame* video_frame, + gfx::BufferFormat* buffer_format, bool use_stream_video_draw_quad) { + DCHECK(buffer_format); switch (video_frame->format()) { case media::PIXEL_FORMAT_ARGB: case media::PIXEL_FORMAT_XRGB: @@ -64,7 +66,13 @@ switch (video_frame->mailbox_holder(0).texture_target) { case GL_TEXTURE_EXTERNAL_OES: case GL_TEXTURE_2D: - return VideoFrameExternalResources::YUV_RESOURCE; + // Single plane textures can be sampled as RGB. + if (video_frame->NumTextures() > 1) { + return VideoFrameExternalResources::YUV_RESOURCE; + } else { + *buffer_format = gfx::BufferFormat::YUV_420_BIPLANAR; + return VideoFrameExternalResources::RGB_RESOURCE; + } case GL_TEXTURE_RECTANGLE_ARB: return VideoFrameExternalResources::RGB_RESOURCE; default: @@ -172,6 +180,7 @@ VideoFrameExternalResources::VideoFrameExternalResources() : type(NONE), read_lock_fences_enabled(false), + buffer_format(gfx::BufferFormat::RGBA_8888), offset(0.0f), multiplier(1.0f), bits_per_channel(8) {} @@ -652,8 +661,9 @@ } gfx::ColorSpace resource_color_space = video_frame->ColorSpace(); - external_resources.type = - ResourceTypeForVideoFrame(video_frame.get(), use_stream_video_draw_quad_); + external_resources.type = ResourceTypeForVideoFrame( + video_frame.get(), &external_resources.buffer_format, + use_stream_video_draw_quad_); if (external_resources.type == VideoFrameExternalResources::NONE) { DLOG(ERROR) << "Unsupported Texture format" << media::VideoPixelFormatToString(video_frame->format());
diff --git a/cc/resources/video_resource_updater.h b/cc/resources/video_resource_updater.h index 63b5388a..7a62202 100644 --- a/cc/resources/video_resource_updater.h +++ b/cc/resources/video_resource_updater.h
@@ -20,6 +20,7 @@ #include "cc/resources/release_callback_impl.h" #include "components/viz/common/quads/resource_format.h" #include "components/viz/common/quads/texture_mailbox.h" +#include "ui/gfx/buffer_types.h" #include "ui/gfx/geometry/size.h" namespace media { @@ -55,6 +56,8 @@ std::vector<viz::TextureMailbox> mailboxes; std::vector<ReleaseCallbackImpl> release_callbacks; bool read_lock_fences_enabled; + // Format of the storage of the resource, if known. + gfx::BufferFormat buffer_format; // TODO(danakj): Remove these too. std::vector<unsigned> software_resources;
diff --git a/cc/resources/video_resource_updater_unittest.cc b/cc/resources/video_resource_updater_unittest.cc index e933119f..4788e0ec 100644 --- a/cc/resources/video_resource_updater_unittest.cc +++ b/cc/resources/video_resource_updater_unittest.cc
@@ -179,6 +179,7 @@ } scoped_refptr<media::VideoFrame> CreateTestHardwareVideoFrame( + media::VideoPixelFormat format, unsigned target) { const int kDimension = 10; gfx::Size size(kDimension, kDimension); @@ -190,7 +191,7 @@ gpu::MailboxHolder(mailbox, kMailboxSyncToken, target)}; scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::WrapNativeTextures( - media::PIXEL_FORMAT_ARGB, mailbox_holders, + format, mailbox_holders, base::Bind(&VideoResourceUpdaterTest::SetReleaseSyncToken, base::Unretained(this)), size, // coded_size @@ -202,13 +203,14 @@ } scoped_refptr<media::VideoFrame> CreateTestRGBAHardwareVideoFrame() { - return CreateTestHardwareVideoFrame(GL_TEXTURE_2D); + return CreateTestHardwareVideoFrame(media::PIXEL_FORMAT_ARGB, + GL_TEXTURE_2D); } scoped_refptr<media::VideoFrame> CreateTestStreamTextureHardwareVideoFrame( bool needs_copy) { - scoped_refptr<media::VideoFrame> video_frame = - CreateTestHardwareVideoFrame(GL_TEXTURE_EXTERNAL_OES); + scoped_refptr<media::VideoFrame> video_frame = CreateTestHardwareVideoFrame( + media::PIXEL_FORMAT_ARGB, GL_TEXTURE_EXTERNAL_OES); video_frame->metadata()->SetBoolean( media::VideoFrameMetadata::COPY_REQUIRED, needs_copy); return video_frame; @@ -665,5 +667,26 @@ EXPECT_NE(resources.mailboxes[0].sync_token(), kMailboxSyncToken); } +// NV12 VideoFrames backed by a single native texture can be sampled out +// by GL as RGB. To use them as HW overlays we need to know the format +// of the underlying buffer, that is YUV_420_BIPLANAR. +TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_SingleNV12) { + bool use_stream_video_draw_quad = false; + VideoResourceUpdater updater(context_provider_.get(), + resource_provider3d_.get(), + use_stream_video_draw_quad); + context3d_->ResetTextureCreationCount(); + scoped_refptr<media::VideoFrame> video_frame = CreateTestHardwareVideoFrame( + media::PIXEL_FORMAT_NV12, GL_TEXTURE_EXTERNAL_OES); + + VideoFrameExternalResources resources = + updater.CreateExternalResourcesFromVideoFrame(video_frame); + EXPECT_EQ(VideoFrameExternalResources::RGB_RESOURCE, resources.type); + EXPECT_EQ(1u, resources.mailboxes.size()); + EXPECT_EQ((GLenum)GL_TEXTURE_EXTERNAL_OES, resources.mailboxes[0].target()); + EXPECT_EQ(gfx::BufferFormat::YUV_420_BIPLANAR, resources.buffer_format); + EXPECT_EQ(0, context3d_->TextureCreationCount()); +} + } // namespace } // namespace cc
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 45b849b..77e3137 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -9416,7 +9416,58 @@ EXPECT_EQ(gfx::PointF(selection_bottom), selection_after.start.edge_bottom()); EXPECT_EQ(gfx::PointF(selection_top), selection_after.start.edge_top()); EXPECT_TRUE(selection_after.start.visible()); - EXPECT_TRUE(selection_after.start.visible()); + EXPECT_TRUE(selection_after.end.visible()); +} + +TEST_F(LayerTreeHostImplTest, HiddenSelectionBoundsStayHidden) { + int root_layer_id = 1; + std::unique_ptr<SolidColorLayerImpl> root = + SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id); + root->SetPosition(gfx::PointF()); + root->SetBounds(gfx::Size(10, 10)); + root->SetDrawsContent(true); + root->test_properties()->force_render_surface = true; + + host_impl_->active_tree()->SetRootLayerForTesting(std::move(root)); + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + + // Ensure the default frame selection bounds are empty. + auto* fake_layer_tree_frame_sink = + static_cast<FakeLayerTreeFrameSink*>(host_impl_->layer_tree_frame_sink()); + + // Plumb the layer-local selection bounds. + gfx::Point selection_top(5, 0); + gfx::Point selection_bottom(5, 5); + LayerSelection selection; + + // Mark the start as hidden. + selection.start.hidden = true; + + selection.start.type = gfx::SelectionBound::CENTER; + selection.start.layer_id = root_layer_id; + selection.start.edge_bottom = selection_bottom; + selection.start.edge_top = selection_top; + selection.end = selection.start; + host_impl_->active_tree()->RegisterSelection(selection); + + // Trigger a draw-swap sequence. + host_impl_->SetNeedsRedraw(); + + gfx::Rect full_frame_damage(host_impl_->DeviceViewport().size()); + TestFrameData frame; + EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); + EXPECT_TRUE(host_impl_->DrawLayers(&frame)); + host_impl_->DidDrawAllLayers(frame); + + // Ensure the selection bounds have propagated to the frame metadata. + const Selection<gfx::SelectionBound>& selection_after = + fake_layer_tree_frame_sink->last_sent_frame()->metadata.selection; + EXPECT_EQ(selection.start.type, selection_after.start.type()); + EXPECT_EQ(selection.end.type, selection_after.end.type()); + EXPECT_EQ(gfx::PointF(selection_bottom), selection_after.start.edge_bottom()); + EXPECT_EQ(gfx::PointF(selection_top), selection_after.start.edge_top()); + EXPECT_FALSE(selection_after.start.visible()); + EXPECT_FALSE(selection_after.end.visible()); } class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 644f2ac8..00903c8 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -2012,22 +2012,29 @@ viewport_bound.SetEdgeTop(gfx::ScalePoint(screen_top, inv_scale)); viewport_bound.SetEdgeBottom(gfx::ScalePoint(screen_bottom, inv_scale)); - // The bottom edge point is used for visibility testing as it is the logical - // focal point for bound selection handles (this may change in the future). - // Shifting the visibility point fractionally inward ensures that neighboring - // or logically coincident layers aligned to integral DPI coordinates will not - // spuriously occlude the bound. - gfx::Vector2dF visibility_offset = layer_top - layer_bottom; - visibility_offset.Scale(device_scale_factor / visibility_offset.Length()); - gfx::PointF visibility_point = layer_bottom + visibility_offset; - if (visibility_point.x() <= 0) - visibility_point.set_x(visibility_point.x() + device_scale_factor); - visibility_point = - MathUtil::MapPoint(screen_space_transform, visibility_point, &clipped); + // If |layer_bound| is already hidden due to being occluded by painted content + // within the layer, it must remain hidden. Otherwise, check whether its + // position is outside the bounds of the layer. + if (layer_bound.hidden) { + viewport_bound.set_visible(false); + } else { + // The bottom edge point is used for visibility testing as it is the logical + // focal point for bound selection handles (this may change in the future). + // Shifting the visibility point fractionally inward ensures that + // neighboring or logically coincident layers aligned to integral DPI + // coordinates will not spuriously occlude the bound. + gfx::Vector2dF visibility_offset = layer_top - layer_bottom; + visibility_offset.Scale(device_scale_factor / visibility_offset.Length()); + gfx::PointF visibility_point = layer_bottom + visibility_offset; + if (visibility_point.x() <= 0) + visibility_point.set_x(visibility_point.x() + device_scale_factor); + visibility_point = + MathUtil::MapPoint(screen_space_transform, visibility_point, &clipped); - float intersect_distance = 0.f; - viewport_bound.set_visible( - PointHitsLayer(layer, visibility_point, &intersect_distance)); + float intersect_distance = 0.f; + viewport_bound.set_visible( + PointHitsLayer(layer, visibility_point, &intersect_distance)); + } return viewport_bound; }
diff --git a/chrome/VERSION b/chrome/VERSION index 1073fdb..ba0767f 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=62 MINOR=0 -BUILD=3180 +BUILD=3181 PATCH=0
diff --git a/chrome/android/java/res/layout/incognito_bottom_sheet_content.xml b/chrome/android/java/res/layout/incognito_bottom_sheet_content.xml index 8d4cef6..b187f90 100644 --- a/chrome/android/java/res/layout/incognito_bottom_sheet_content.xml +++ b/chrome/android/java/res/layout/incognito_bottom_sheet_content.xml
@@ -3,56 +3,14 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<FrameLayout +<org.chromium.chrome.browser.ntp.IncognitoNewTabPageView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:chrome="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/incognito_primary_color" > - <ScrollView - android:id="@+id/scroll_view" - android:layout_width="match_parent" - android:layout_height="match_parent" > - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:gravity="center_horizontal" - android:orientation="vertical" - android:paddingStart="16dp" - android:paddingEnd="16dp" - android:paddingTop="16dp" - android:paddingBottom="16dp" > - - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/new_tab_incognito_header" - android:textColor="@color/locationbar_light_hint_text" - android:textSize="24sp" /> - - <TextView - android:id="@+id/new_tab_incognito_message" - style="@style/IncognitoNewTabMessage" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="16dp" - android:layout_marginBottom="10dp" - android:text="@string/new_tab_incognito_message" - android:textColor="@color/locationbar_light_hint_text" /> - - <TextView - android:id="@+id/learn_more" - style="@style/IncognitoNewTabLearnMoreLink" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/learn_more" - android:textColor="@color/google_blue_300" /> - - </LinearLayout> - - </ScrollView> + <include layout="@layout/new_tab_page_incognito_common" /> <org.chromium.chrome.browser.widget.FadingShadowView android:id="@+id/shadow" @@ -60,5 +18,4 @@ android:layout_height="@dimen/action_bar_shadow_height" android:visibility="gone" /> -</FrameLayout> - +</org.chromium.chrome.browser.ntp.IncognitoNewTabPageView>
diff --git a/chrome/android/java/res/layout/incognito_bottom_sheet_content_md.xml b/chrome/android/java/res/layout/incognito_bottom_sheet_content_md.xml new file mode 100644 index 0000000..c0cc230 --- /dev/null +++ b/chrome/android/java/res/layout/incognito_bottom_sheet_content_md.xml
@@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. --> + +<org.chromium.chrome.browser.ntp.IncognitoNewTabPageViewMD + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:chrome="http://schemas.android.com/apk/res-auto" + android:id="@+id/ntp_content" + android:layout_width="match_parent" + android:layout_height="match_parent" > + + <include layout="@layout/new_tab_page_incognito_md_common" /> + + <org.chromium.chrome.browser.widget.FadingShadowView + android:id="@+id/shadow" + android:layout_width="match_parent" + android:layout_height="@dimen/action_bar_shadow_height" + android:visibility="gone" /> + +</org.chromium.chrome.browser.ntp.IncognitoNewTabPageViewMD>
diff --git a/chrome/android/java/res/layout/new_tab_page_incognito.xml b/chrome/android/java/res/layout/new_tab_page_incognito.xml index f6be0ba3..7598ea6 100644 --- a/chrome/android/java/res/layout/new_tab_page_incognito.xml +++ b/chrome/android/java/res/layout/new_tab_page_incognito.xml
@@ -11,64 +11,6 @@ android:layout_height="match_parent" android:paddingTop="@dimen/tab_strip_height" > - <org.chromium.chrome.browser.ntp.NewTabPageScrollView - android:id="@+id/ntp_scrollview" - android:background="@color/ntp_bg_incognito" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:paddingTop="@dimen/toolbar_height_no_shadow" - android:fadingEdgeLength="9dp" - android:fillViewport="false" - android:focusable="true" - android:focusableInTouchMode="true" - android:requiresFadingEdge="vertical" - android:contentDescription="@string/accessibility_new_incognito_tab_page" > - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:gravity="center_horizontal" - android:orientation="vertical" - android:paddingStart="32dp" - android:paddingEnd="32dp" - android:paddingTop="24dp" - android:paddingBottom="16dp" > - - <ImageView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginBottom="19dp" - android:contentDescription="@null" - android:src="@drawable/incognito_splash"/> - - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:fontFamily="sans-serif-light" - android:text="@string/new_tab_incognito_header" - android:textColor="#d2d2d2" - android:textSize="24sp" /> - - <TextView - android:id="@+id/new_tab_incognito_message" - style="@style/IncognitoNewTabMessage" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="32dp" - android:layout_marginBottom="10dp" - android:text="@null" - android:textColor="#bdbdbd" /> - - <TextView - android:id="@+id/learn_more" - style="@style/IncognitoNewTabLearnMoreLink" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/learn_more" - android:textColor="#03a9f4" /> - - </LinearLayout> - - </org.chromium.chrome.browser.ntp.NewTabPageScrollView> + <include layout="@layout/new_tab_page_incognito_common"/> </org.chromium.chrome.browser.ntp.IncognitoNewTabPageView>
diff --git a/chrome/android/java/res/layout/new_tab_page_incognito_common.xml b/chrome/android/java/res/layout/new_tab_page_incognito_common.xml new file mode 100644 index 0000000..b5e56637 --- /dev/null +++ b/chrome/android/java/res/layout/new_tab_page_incognito_common.xml
@@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. --> + +<merge xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:chrome="http://schemas.android.com/apk/res-auto"> + + <org.chromium.chrome.browser.ntp.NewTabPageScrollView + android:id="@+id/ntp_scrollview" + android:background="@color/ntp_bg_incognito" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingTop="@dimen/toolbar_height_no_shadow" + android:fadingEdgeLength="9dp" + android:fillViewport="false" + android:focusable="true" + android:focusableInTouchMode="true" + android:requiresFadingEdge="vertical" + android:contentDescription="@string/accessibility_new_incognito_tab_page" > + + <LinearLayout + android:id="@+id/new_tab_incognito_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center_horizontal" + android:orientation="vertical" + android:paddingStart="32dp" + android:paddingEnd="32dp" + android:paddingTop="24dp" + android:paddingBottom="16dp" > + + <ImageView + android:id="@+id/new_tab_incognito_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="19dp" + android:contentDescription="@null" + android:src="@drawable/incognito_splash"/> + + <TextView + android:id="@+id/ntp_incognito_header" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:fontFamily="sans-serif-light" + android:text="@string/new_tab_incognito_header" + android:textColor="@color/incognito_ntp_header" + android:textSize="24sp" /> + + <TextView + android:id="@+id/new_tab_incognito_message" + style="@style/IncognitoNewTabMessage" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="32dp" + android:layout_marginBottom="10dp" + android:text="@null" + android:textColor="@color/google_grey_400" /> + + <TextView + android:id="@+id/learn_more" + style="@style/IncognitoNewTabLearnMoreLink" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/learn_more" + android:textColor="@color/incognito_ntp_learn_more_link" /> + + </LinearLayout> + + </org.chromium.chrome.browser.ntp.NewTabPageScrollView> + +</merge> \ No newline at end of file
diff --git a/chrome/android/java/res/layout/new_tab_page_incognito_md.xml b/chrome/android/java/res/layout/new_tab_page_incognito_md.xml index 154a115..43cc5c7 100644 --- a/chrome/android/java/res/layout/new_tab_page_incognito_md.xml +++ b/chrome/android/java/res/layout/new_tab_page_incognito_md.xml
@@ -11,83 +11,6 @@ android:layout_height="match_parent" android:paddingTop="@dimen/tab_strip_height" > - <org.chromium.chrome.browser.ntp.NewTabPageScrollView - android:id="@+id/ntp_scrollview" - android:background="@color/ntp_bg_incognito" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:paddingTop="@dimen/toolbar_height_no_shadow" - android:fadingEdgeLength="9dp" - android:fillViewport="false" - android:focusable="true" - android:focusableInTouchMode="true" - android:requiresFadingEdge="vertical" - android:contentDescription="@string/accessibility_new_incognito_tab_page" > - - <LinearLayout - android:id="@+id/new_tab_incognito_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:gravity="start" - android:orientation="vertical"> - - <ImageView - android:id="@+id/new_tab_incognito_icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:contentDescription="@null" - android:src="@drawable/incognito_splash" /> - - <TextView - android:id="@+id/new_tab_incognito_title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/new_tab_otr_title" - android:textColor="@color/incognito_header" /> - - <TextView - android:id="@+id/new_tab_incognito_subtitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/new_tab_otr_subtitle" - android:textColor="@color/incognito_header" - android:lineSpacingExtra="6sp" /> - - <LinearLayout - android:id="@+id/new_tab_incognito_bulletpoints_container" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal" - android:gravity="start"> - - <TextView - android:id="@+id/new_tab_incognito_features" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textColor="@color/incognito_text" - android:lineSpacingExtra="6sp" /> - - <TextView - android:id="@+id/new_tab_incognito_warning" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textColor="@color/incognito_text" - android:lineSpacingExtra="6sp" /> - - </LinearLayout> - - <TextView - android:id="@+id/learn_more" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:clickable="true" - android:focusable="true" - android:text="@string/learn_more" - android:textColor="@color/google_blue_300" - android:lineSpacingExtra="6sp" /> - - </LinearLayout> - - </org.chromium.chrome.browser.ntp.NewTabPageScrollView> + <include layout="@layout/new_tab_page_incognito_md_common"/> </org.chromium.chrome.browser.ntp.IncognitoNewTabPageViewMD>
diff --git a/chrome/android/java/res/layout/new_tab_page_incognito_md_common.xml b/chrome/android/java/res/layout/new_tab_page_incognito_md_common.xml new file mode 100644 index 0000000..533d5b4 --- /dev/null +++ b/chrome/android/java/res/layout/new_tab_page_incognito_md_common.xml
@@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. --> + +<merge xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:chrome="http://schemas.android.com/apk/res-auto"> + + <org.chromium.chrome.browser.ntp.NewTabPageScrollView + android:id="@+id/ntp_scrollview" + android:background="@color/ntp_bg_incognito" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingTop="@dimen/toolbar_height_no_shadow" + android:fadingEdgeLength="9dp" + android:fillViewport="false" + android:focusable="true" + android:focusableInTouchMode="true" + android:requiresFadingEdge="vertical" + android:contentDescription="@string/accessibility_new_incognito_tab_page" > + + <LinearLayout + android:id="@+id/new_tab_incognito_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="start" + android:orientation="vertical" + android:paddingStart="16dp" > + + <ImageView + android:id="@+id/new_tab_incognito_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:contentDescription="@null" + android:src="@drawable/incognito_splash" /> + + <TextView + android:id="@+id/new_tab_incognito_title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/new_tab_otr_title" + android:textColor="@color/incognito_header" /> + + <TextView + android:id="@+id/new_tab_incognito_subtitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/new_tab_otr_subtitle" + android:textColor="@color/incognito_header" + android:lineSpacingExtra="6sp" /> + + <LinearLayout + android:id="@+id/new_tab_incognito_bulletpoints_container" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:gravity="start"> + + <TextView + android:id="@+id/new_tab_incognito_features" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textColor="@color/incognito_text" + android:lineSpacingExtra="6sp" /> + + <TextView + android:id="@+id/new_tab_incognito_warning" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textColor="@color/incognito_text" + android:lineSpacingExtra="6sp" /> + + </LinearLayout> + + <TextView + android:id="@+id/learn_more" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:clickable="true" + android:focusable="true" + android:text="@string/learn_more" + android:textColor="@color/google_blue_300" + android:lineSpacingExtra="6sp" /> + + </LinearLayout> + + </org.chromium.chrome.browser.ntp.NewTabPageScrollView> + +</merge>
diff --git a/chrome/android/java/res/layout/tabular_context_menu_row.xml b/chrome/android/java/res/layout/tabular_context_menu_row.xml index fa3d95d..fa7e275 100644 --- a/chrome/android/java/res/layout/tabular_context_menu_row.xml +++ b/chrome/android/java/res/layout/tabular_context_menu_row.xml
@@ -22,7 +22,7 @@ android:scaleType="centerInside" android:contentDescription="@null" /> <TextView - android:id="@+id/context_text" + android:id="@+id/context_menu_text" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center_vertical"
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml index 3b74282..9d8e041 100644 --- a/chrome/android/java/res/values/colors.xml +++ b/chrome/android/java/res/values/colors.xml
@@ -126,6 +126,8 @@ <color name="incognito_text">#b3ffffff</color> <color name="incognito_emphasis">@android:color/white</color> <color name="incognito_header">#ccffffff</color> + <color name="incognito_ntp_learn_more_link">#03a9f4</color> + <color name="incognito_ntp_header">#d2d2d2</color> <!-- Site suggestion tile colors. --> <color name="tile_view_text">@color/black_alpha_54</color>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java index 56214441..b3e00aed 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
@@ -323,7 +323,12 @@ private void setupMenuButton(View button, final MenuItem item) { button.setEnabled(item.isEnabled()); button.setFocusable(item.isEnabled()); - button.setContentDescription(item.getTitleCondensed()); + if (TextUtils.isEmpty(item.getTitleCondensed())) { + button.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); + } else { + button.setContentDescription(item.getTitleCondensed()); + button.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); + } button.setOnClickListener(new OnClickListener() { @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java index 2adc84ae..fb06d7b17 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java
@@ -184,7 +184,7 @@ && !isChromeScheme && !isFileScheme && !isContentScheme && !isIncognito; prepareAddToHomescreenMenuItem(menu, currentTab, canShowHomeScreenMenuItem); - updateRequestDesktopSiteMenuItem(menu, currentTab); + updateRequestDesktopSiteMenuItem(menu, currentTab, true /* can show */); // Only display reader mode settings menu option if the current page is in reader mode. menu.findItem(R.id.reader_mode_prefs_id) @@ -380,7 +380,8 @@ * @param menu {@link Menu} for request desktop site. * @param currentTab Current tab being displayed. */ - protected void updateRequestDesktopSiteMenuItem(Menu menu, Tab currentTab) { + protected void updateRequestDesktopSiteMenuItem( + Menu menu, Tab currentTab, boolean canShowRequestDekstopSite) { MenuItem requestMenuRow = menu.findItem(R.id.request_desktop_site_row_menu_id); MenuItem requestMenuLabel = menu.findItem(R.id.request_desktop_site_id); MenuItem requestMenuCheck = menu.findItem(R.id.request_desktop_site_check_id); @@ -391,8 +392,11 @@ || url.startsWith(UrlConstants.CHROME_NATIVE_URL_PREFIX); // Also hide request desktop site on Reader Mode. boolean isDistilledPage = DomDistillerUrlUtils.isDistilledPage(url); - requestMenuRow.setVisible( - (!isChromeScheme || currentTab.isNativePage()) && !isDistilledPage); + + boolean itemVisible = canShowRequestDekstopSite + && (!isChromeScheme || currentTab.isNativePage()) && !isDistilledPage; + requestMenuRow.setVisible(itemVisible); + if (!itemVisible) return; // Mark the checkbox if RDS is activated on this page. requestMenuCheck.setChecked(currentTab.getUseDesktopUserAgent());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuListAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuListAdapter.java index 101e7f6..9a31aca 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuListAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuListAdapter.java
@@ -68,7 +68,7 @@ viewHolder = new ViewHolderItem(); viewHolder.mIcon = (ImageView) convertView.findViewById(R.id.context_menu_icon); - viewHolder.mText = (TextView) convertView.findViewById(R.id.context_text); + viewHolder.mText = (TextView) convertView.findViewById(R.id.context_menu_text); if (viewHolder.mText == null) { throw new IllegalStateException("Context text not found in new view inflation"); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java index 5bba453..13229c6e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java
@@ -147,12 +147,6 @@ openInChromeItem.setVisible(false); } - if (requestDesktopSiteVisible) { - updateRequestDesktopSiteMenuItem(menu, currentTab); - } else { - menu.findItem(R.id.request_desktop_site_row_menu_id).setVisible(false); - } - // Add custom menu items. Make sure they are only added once. if (!mIsCustomEntryAdded) { mIsCustomEntryAdded = true; @@ -162,6 +156,7 @@ } } + updateRequestDesktopSiteMenuItem(menu, currentTab, requestDesktopSiteVisible); prepareAddToHomescreenMenuItem(menu, currentTab, addToHomeScreenVisible); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/installedapp/InstalledAppProviderImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/installedapp/InstalledAppProviderImpl.java index d46ed2f..4c3443a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/installedapp/InstalledAppProviderImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/installedapp/InstalledAppProviderImpl.java
@@ -194,8 +194,10 @@ * @param frameUrl Returns false if the Android package does not declare association with the * origin of this URL. Can be null. */ - private boolean isAppInstalledAndAssociatedWithOrigin( + public static boolean isAppInstalledAndAssociatedWithOrigin( String packageName, URI frameUrl, PackageManager pm) { + // TODO(yusufo): Move this to a better/shared location before crbug.com/749876 is closed. + ThreadUtils.assertOnBackgroundThread(); if (frameUrl == null) return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/BaseMediaRouteDialogManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/BaseMediaRouteDialogManager.java index 69f7d3e..f0a1315 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/BaseMediaRouteDialogManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/BaseMediaRouteDialogManager.java
@@ -8,12 +8,12 @@ import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; +import android.support.v7.media.MediaRouteSelector; import android.support.v7.media.MediaRouter; import android.view.View; import android.widget.FrameLayout; import org.chromium.base.ApplicationStatus; -import org.chromium.chrome.browser.media.router.cast.MediaSource; import javax.annotation.Nullable; @@ -56,7 +56,8 @@ } } - private final MediaSource mMediaSource; + private final String mSourceId; + private final MediaRouteSelector mRouteSelector; private final MediaRouter mAndroidMediaRouter; private final MediaRouteDialogDelegate mDelegate; @@ -102,8 +103,10 @@ return mDialogFragment != null && mDialogFragment.isVisible(); } - protected BaseMediaRouteDialogManager(MediaSource source, MediaRouteDialogDelegate delegate) { - mMediaSource = source; + protected BaseMediaRouteDialogManager( + String sourceId, MediaRouteSelector routeSelector, MediaRouteDialogDelegate delegate) { + mSourceId = sourceId; + mRouteSelector = routeSelector; mAndroidMediaRouter = ChromeMediaRouter.getAndroidMediaRouter(); mDelegate = delegate; } @@ -126,7 +129,11 @@ return mAndroidMediaRouter; } - protected MediaSource mediaSource() { - return mMediaSource; + protected String sourceId() { + return mSourceId; + } + + protected MediaRouteSelector routeSelector() { + return mRouteSelector; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java index ec3f60c2..f774874e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java
@@ -6,11 +6,13 @@ import android.support.v7.app.MediaRouteChooserDialogFragment; import android.support.v7.app.MediaRouteControllerDialogFragment; +import android.support.v7.media.MediaRouteSelector; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.chrome.browser.media.router.cast.MediaSink; import org.chromium.chrome.browser.media.router.cast.MediaSource; +import org.chromium.chrome.browser.media.router.cast.remoting.RemotingMediaSource; /** * Implements the JNI interface called from the C++ Media Router dialog controller implementation @@ -43,18 +45,30 @@ public void openRouteChooserDialog(String[] sourceUrns) { if (isShowingDialog()) return; - MediaSource source = null; + String sourceId = null; + MediaRouteSelector routeSelector = null; for (String sourceUrn : sourceUrns) { - source = MediaSource.from(sourceUrn); - if (source != null) break; + MediaSource source = MediaSource.from(sourceUrn); + if (source != null) { + sourceId = source.getUrn(); + routeSelector = source.buildRouteSelector(); + break; + } + + RemotingMediaSource remotingSource = RemotingMediaSource.from(sourceUrn); + if (remotingSource != null) { + sourceId = remotingSource.getSourceId(); + routeSelector = remotingSource.buildRouteSelector(); + break; + } } - if (source == null) { + if (sourceId == null || routeSelector == null) { nativeOnMediaSourceNotSupported(mNativeDialogController); return; } - mDialogManager = new MediaRouteChooserDialogManager(source, this); + mDialogManager = new MediaRouteChooserDialogManager(sourceId, routeSelector, this); mDialogManager.openDialog(); } @@ -67,13 +81,28 @@ public void openRouteControllerDialog(String sourceUrn, String mediaRouteId) { if (isShowingDialog()) return; + String sourceId = null; + MediaRouteSelector routeSelector = null; + MediaSource source = MediaSource.from(sourceUrn); - if (source == null) { + if (source != null) { + sourceId = source.getUrn(); + routeSelector = source.buildRouteSelector(); + } else { + RemotingMediaSource remotingSource = RemotingMediaSource.from(sourceUrn); + if (remotingSource != null) { + sourceId = remotingSource.getSourceId(); + routeSelector = remotingSource.buildRouteSelector(); + } + } + + if (sourceId == null || routeSelector == null) { nativeOnMediaSourceNotSupported(mNativeDialogController); return; } - mDialogManager = new MediaRouteControllerDialogManager(source, mediaRouteId, this); + mDialogManager = + new MediaRouteControllerDialogManager(sourceId, routeSelector, mediaRouteId, this); mDialogManager.openDialog(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteChooserDialogManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteChooserDialogManager.java index 8082d63..607d84f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteChooserDialogManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteChooserDialogManager.java
@@ -12,7 +12,6 @@ import android.support.v7.media.MediaRouteSelector; import org.chromium.chrome.browser.media.router.cast.MediaSink; -import org.chromium.chrome.browser.media.router.cast.MediaSource; /** * Manages the dialog responsible for selecting a {@link MediaSink}. @@ -22,8 +21,9 @@ private static final String DIALOG_FRAGMENT_TAG = "android.support.v7.mediarouter:MediaRouteChooserDialogFragment"; - public MediaRouteChooserDialogManager(MediaSource source, MediaRouteDialogDelegate delegate) { - super(source, delegate); + public MediaRouteChooserDialogManager( + String sourceId, MediaRouteSelector routeSelector, MediaRouteDialogDelegate delegate) { + super(sourceId, routeSelector, delegate); } /** @@ -80,7 +80,7 @@ MediaSink newSink = MediaSink.fromRoute(mManager.androidMediaRouter().getSelectedRoute()); - mManager.delegate().onSinkSelected(mManager.mediaSource().getUrn(), newSink); + mManager.delegate().onSinkSelected(mManager.sourceId(), newSink); } } @@ -89,10 +89,7 @@ if (fm.findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) return null; Fragment fragment = new Fragment(this); - MediaRouteSelector selector = mediaSource().buildRouteSelector(); - if (selector == null) return null; - - fragment.setRouteSelector(selector); + fragment.setRouteSelector(routeSelector()); fragment.show(fm, DIALOG_FRAGMENT_TAG); fm.executePendingTransactions();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteControllerDialogManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteControllerDialogManager.java index 8319b1b..c9d7f4bc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteControllerDialogManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteControllerDialogManager.java
@@ -12,8 +12,6 @@ import android.support.v7.media.MediaRouteSelector; import android.support.v7.media.MediaRouter; -import org.chromium.chrome.browser.media.router.cast.MediaSource; - /** * Manages the dialog responsible for controlling an existing media route. */ @@ -31,9 +29,9 @@ } }; - public MediaRouteControllerDialogManager(MediaSource source, String mediaRouteId, - MediaRouteDialogDelegate delegate) { - super(source, delegate); + public MediaRouteControllerDialogManager(String sourceId, MediaRouteSelector routeSelector, + String mediaRouteId, MediaRouteDialogDelegate delegate) { + super(sourceId, routeSelector, delegate); mMediaRouteId = mediaRouteId; } @@ -88,10 +86,7 @@ if (fm.findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) return null; Fragment fragment = new Fragment(this, mCallback); - MediaRouteSelector selector = mediaSource().buildRouteSelector(); - if (selector == null) return null; - - androidMediaRouter().addCallback(selector, mCallback); + androidMediaRouter().addCallback(routeSelector(), mCallback); fragment.show(fm, DIALOG_FRAGMENT_TAG); fm.executePendingTransactions();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoBottomSheetContent.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoBottomSheetContent.java index 999eb3c..b438f684 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoBottomSheetContent.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoBottomSheetContent.java
@@ -5,16 +5,14 @@ package org.chromium.chrome.browser.ntp; import android.app.Activity; -import android.view.LayoutInflater; import android.view.View; -import android.view.View.OnClickListener; import android.view.ViewTreeObserver.OnScrollChangedListener; +import android.widget.ImageView; import android.widget.ScrollView; +import android.widget.TextView; import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; -import org.chromium.chrome.browser.help.HelpAndFeedback; -import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.widget.FadingShadow; import org.chromium.chrome.browser.widget.FadingShadowView; import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet.BottomSheetContent; @@ -23,8 +21,7 @@ /** * Provides content to be displayed inside the Home tab of the bottom sheet in incognito mode. */ -public class IncognitoBottomSheetContent implements BottomSheetContent { - private final View mView; +public class IncognitoBottomSheetContent extends IncognitoNewTabPage implements BottomSheetContent { private final ScrollView mScrollView; /** @@ -32,25 +29,29 @@ * @param activity The {@link Activity} displaying this bottom sheet content. */ public IncognitoBottomSheetContent(final Activity activity) { - LayoutInflater inflater = LayoutInflater.from(activity); - mView = inflater.inflate(R.layout.incognito_bottom_sheet_content, null); + super(activity); - View learnMore = mView.findViewById(R.id.learn_more); - learnMore.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - HelpAndFeedback.getInstance(activity).show(activity, - activity.getString(R.string.help_context_incognito_learn_more), - Profile.getLastUsedProfile(), null); - } - }); - - final FadingShadowView shadow = (FadingShadowView) mView.findViewById(R.id.shadow); - shadow.init( - ApiCompatibilityUtils.getColor(mView.getResources(), R.color.toolbar_shadow_color), + final FadingShadowView shadow = + (FadingShadowView) mIncognitoNewTabPageView.findViewById(R.id.shadow); + shadow.init(ApiCompatibilityUtils.getColor( + mIncognitoNewTabPageView.getResources(), R.color.toolbar_shadow_color), FadingShadow.POSITION_TOP); - mScrollView = (ScrollView) mView.findViewById(R.id.scroll_view); + initTextViewColors(); + + // Hide the incognito image from the Chrome Home NTP pages. + ImageView incognitoSplash = + (ImageView) mIncognitoNewTabPageView.findViewById(R.id.new_tab_incognito_icon); + incognitoSplash.setVisibility(View.GONE); + + mScrollView = (ScrollView) mIncognitoNewTabPageView.findViewById(R.id.ntp_scrollview); + mScrollView.setBackgroundColor(ApiCompatibilityUtils.getColor( + mIncognitoNewTabPageView.getResources(), R.color.incognito_primary_color)); + // Remove some additional padding that's not necessary when using Chrome Home. + mScrollView.setPaddingRelative(0, + -((int) activity.getResources().getDimension(R.dimen.toolbar_height_no_shadow)), 0, + 0); + mScrollView.getViewTreeObserver().addOnScrollChangedListener(new OnScrollChangedListener() { @Override public void onScrollChanged() { @@ -60,9 +61,55 @@ }); } + private void initTextViewColors() { + final int locationBarLightHintTextColor = ApiCompatibilityUtils.getColor( + mIncognitoNewTabPageView.getResources(), R.color.locationbar_light_hint_text); + final int googleBlueColor = ApiCompatibilityUtils.getColor( + mIncognitoNewTabPageView.getResources(), R.color.google_blue_300); + + final TextView learnMoreView = + (TextView) mIncognitoNewTabPageView.findViewById(R.id.learn_more); + + learnMoreView.setTextColor(googleBlueColor); + + if (useMDIncognitoNTP()) { + final TextView newTabIncognitoTitleView = + (TextView) mIncognitoNewTabPageView.findViewById(R.id.new_tab_incognito_title); + final TextView newTabIncognitoSubtitleView = + (TextView) mIncognitoNewTabPageView.findViewById( + R.id.new_tab_incognito_subtitle); + final TextView newTabIncognitoFeaturesView = + (TextView) mIncognitoNewTabPageView.findViewById( + R.id.new_tab_incognito_features); + final TextView newTabIncognitoWarningView = + (TextView) mIncognitoNewTabPageView.findViewById( + R.id.new_tab_incognito_warning); + + newTabIncognitoTitleView.setTextColor(locationBarLightHintTextColor); + newTabIncognitoSubtitleView.setTextColor(locationBarLightHintTextColor); + newTabIncognitoFeaturesView.setTextColor(locationBarLightHintTextColor); + newTabIncognitoWarningView.setTextColor(locationBarLightHintTextColor); + } else { + final TextView incognitoNtpHeaderView = + (TextView) mIncognitoNewTabPageView.findViewById(R.id.ntp_incognito_header); + final TextView newTabIncognitoMessageView = + (TextView) mIncognitoNewTabPageView.findViewById( + R.id.new_tab_incognito_message); + + incognitoNtpHeaderView.setTextColor(locationBarLightHintTextColor); + newTabIncognitoMessageView.setTextColor(locationBarLightHintTextColor); + } + } + + @Override + protected int getLayoutResource() { + return useMDIncognitoNTP() ? R.layout.incognito_bottom_sheet_content_md + : R.layout.incognito_bottom_sheet_content; + } + @Override public View getContentView() { - return mView; + return getView(); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPage.java index d73f8472..fe2eb4b0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPage.java
@@ -34,7 +34,7 @@ private final String mTitle; private final int mBackgroundColor; private final int mThemeColor; - private final IncognitoNewTabPageView mIncognitoNewTabPageView; + protected final IncognitoNewTabPageView mIncognitoNewTabPageView; private boolean mIsLoaded; @@ -87,10 +87,8 @@ R.color.incognito_primary_color); LayoutInflater inflater = LayoutInflater.from(activity); - mIncognitoNewTabPageView = (IncognitoNewTabPageView) inflater.inflate(useMDIncognitoNTP() - ? R.layout.new_tab_page_incognito_md - : R.layout.new_tab_page_incognito, - null); + mIncognitoNewTabPageView = + (IncognitoNewTabPageView) inflater.inflate(getLayoutResource(), null); mIncognitoNewTabPageView.initialize(mIncognitoNewTabPageManager); if (!useMDIncognitoNTP()) { @@ -101,7 +99,12 @@ } } - private static boolean useMDIncognitoNTP() { + protected int getLayoutResource() { + return useMDIncognitoNTP() ? R.layout.new_tab_page_incognito_md + : R.layout.new_tab_page_incognito; + } + + protected static boolean useMDIncognitoNTP() { return ChromeFeatureList.isEnabled(ChromeFeatureList.MATERIAL_DESIGN_INCOGNITO_NTP); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPageViewMD.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPageViewMD.java index e5782bd..2e99eb32 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPageViewMD.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPageViewMD.java
@@ -26,6 +26,7 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.ui.text.NoUnderlineClickableSpan; import org.chromium.ui.text.SpanApplier; @@ -160,9 +161,9 @@ // - Add the bulletpoint symbols (Unicode BULLET U+2022) // - Remove leading whitespace (caused by formatting in the .grdp file) // - Remove the trailing newline after the last bulletpoint. - text = text.replaceFirst(" +<li>([^<]*)</li>", "<li1>\u2022 $1</li1>"); - text = text.replaceFirst(" +<li>([^<]*)</li>", "<li2>\u2022 $1</li2>"); - text = text.replaceFirst(" +<li>([^<]*)</li>\n", "<li3>\u2022 $1</li3>"); + text = text.replaceFirst(" +<li>([^<]*)</li>", "<li1> \u2022 $1</li1>"); + text = text.replaceFirst(" +<li>([^<]*)</li>", "<li2> \u2022 $1</li2>"); + text = text.replaceFirst(" +<li>([^<]*)</li>\n", "<li3> \u2022 $1</li3>"); // Remove the <ul></ul> tags which serve no purpose here, including the whitespace around // them. @@ -203,15 +204,25 @@ boolean bulletpointsArrangedHorizontally; - if (mWidthDp <= WIDE_LAYOUT_THRESHOLD_DP) { + boolean usingChromeHome = ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_HOME); + if (mWidthDp <= WIDE_LAYOUT_THRESHOLD_DP || usingChromeHome) { // Small padding. - paddingHorizontalDp = mWidthDp <= 240 ? 24 : 32; - paddingVerticalDp = mHeightDp <= 600 ? 32 : 72; + // Set the padding to a default for Chrome Home, since we want less padding in this + // case. + if (usingChromeHome) { + paddingVerticalDp = 0; + paddingHorizontalDp = 16; + } else { + paddingHorizontalDp = mWidthDp <= 240 ? 24 : 32; + paddingVerticalDp = (mHeightDp <= 600) ? 32 : 72; + } // Align left. mContainer.setGravity(Gravity.START); // Decide the bulletpoints orientation. + // TODO (thildebr): This is never set to anything but false, check if we can remove + // related code. bulletpointsArrangedHorizontally = false; // The subtitle is sized automatically, but not wider than CONTENT_WIDTH_DP.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoController.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoController.java index 5690602..fe22060 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoController.java
@@ -44,6 +44,11 @@ private String mAccountName; private final ProfileDataCache mProfileDataCache; private final @AccountSigninActivity.AccessPoint int mAccessPoint; + private final @Nullable String mImpressionCountName; + private final String mImpressionUserActionName; + private final @Nullable String mImpressionWithAccountUserActionName; + private final @Nullable String mImpressionWithNoAccountUserActionName; + private final @StringRes int mDescriptionStringId; /** * Determines whether the promo should be shown to the user or not. @@ -84,41 +89,68 @@ ProfileDataCache profileDataCache, @AccountSigninActivity.AccessPoint int accessPoint) { mProfileDataCache = profileDataCache; mAccessPoint = accessPoint; + + switch (mAccessPoint) { + case SigninAccessPoint.BOOKMARK_MANAGER: + mImpressionCountName = SIGNIN_PROMO_IMPRESSIONS_COUNT_BOOKMARKS; + mImpressionUserActionName = "Signin_Impression_FromBookmarkManager"; + mImpressionWithAccountUserActionName = + "Signin_ImpressionWithAccount_FromBookmarkManager"; + mImpressionWithNoAccountUserActionName = + "Signin_ImpressionWithNoAccount_FromBookmarkManager"; + mDescriptionStringId = R.string.signin_promo_description_bookmarks; + break; + case SigninAccessPoint.NTP_CONTENT_SUGGESTIONS: + // There is no impression limit for NTP content suggestions. + mImpressionCountName = null; + mImpressionUserActionName = "Signin_Impression_FromNTPContentSuggestions"; + // TODO(iuliah): create Signin_ImpressionWithAccount_FromNTPContentSuggestions. + mImpressionWithAccountUserActionName = null; + // TODO(iuliah): create Signin_ImpressionWithNoAccount_FromNTPContentSuggestions. + mImpressionWithNoAccountUserActionName = null; + mDescriptionStringId = R.string.signin_promo_description_ntp_content_suggestions; + break; + case SigninAccessPoint.RECENT_TABS: + // There is no impression limit for Recent Tabs. + mImpressionCountName = null; + mImpressionUserActionName = "Signin_Impression_FromRecentTabs"; + mImpressionWithAccountUserActionName = + "Signin_ImpressionWithAccount_FromRecentTabs"; + mImpressionWithNoAccountUserActionName = + "Signin_ImpressionWithNoAccount_FromRecentTabs"; + mDescriptionStringId = R.string.signin_promo_description_recent_tabs; + break; + case SigninAccessPoint.SETTINGS: + mImpressionCountName = SIGNIN_PROMO_IMPRESSIONS_COUNT_SETTINGS; + mImpressionUserActionName = "Signin_Impression_FromSettings"; + mImpressionWithAccountUserActionName = "Signin_ImpressionWithAccount_FromSettings"; + mImpressionWithNoAccountUserActionName = + "Signin_ImpressionWithNoAccount_FromSettings"; + mDescriptionStringId = R.string.signin_promo_description_settings; + break; + default: + throw new IllegalArgumentException( + "Unexpected value for access point: " + mAccessPoint); + } } /** * Records user actions for promo impressions. */ public void recordSigninPromoImpression() { - recordSigninImpressionUserAction(); + RecordUserAction.record(mImpressionUserActionName); if (mAccountName == null) { recordSigninImpressionWithNoAccountUserAction(); } else { recordSigninImpressionWithAccountUserAction(); } - final String key; - switch (mAccessPoint) { - case SigninAccessPoint.BOOKMARK_MANAGER: - key = SIGNIN_PROMO_IMPRESSIONS_COUNT_BOOKMARKS; - break; - case SigninAccessPoint.NTP_CONTENT_SUGGESTIONS: - // There is no need to record impressions for NTP content suggestions. - return; - case SigninAccessPoint.RECENT_TABS: - // There is no need to record impressions for Recent Tabs. - return; - case SigninAccessPoint.SETTINGS: - key = SIGNIN_PROMO_IMPRESSIONS_COUNT_SETTINGS; - break; - default: - assert false : "Unexpected value for access point: " + mAccessPoint; - return; + // If mImpressionCountName is not null then we should record impressions. + if (mImpressionCountName != null) { + SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); + int numImpressions = preferences.getInt(mImpressionCountName, 0); + preferences.edit().putInt(mImpressionCountName, numImpressions + 1).apply(); } - - SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); - int numImpressions = preferences.getInt(key, 0); - preferences.edit().putInt(key, numImpressions + 1).apply(); } /** @@ -130,7 +162,7 @@ */ public void setupSigninPromoView(Context context, SigninPromoView view, @Nullable final OnDismissListener onDismissListener) { - setDescriptionText(view); + view.getDescription().setText(mDescriptionStringId); if (mAccountName == null) { setupColdState(context, view); @@ -160,85 +192,18 @@ mAccountName = accountName; } - private void recordSigninImpressionUserAction() { - switch (mAccessPoint) { - case SigninAccessPoint.BOOKMARK_MANAGER: - RecordUserAction.record("Signin_Impression_FromBookmarkManager"); - break; - case SigninAccessPoint.NTP_CONTENT_SUGGESTIONS: - RecordUserAction.record("Signin_Impression_FromNTPContentSuggestions"); - break; - case SigninAccessPoint.RECENT_TABS: - RecordUserAction.record("Signin_Impression_FromRecentTabs"); - break; - case SigninAccessPoint.SETTINGS: - RecordUserAction.record("Signin_Impression_FromSettings"); - break; - default: - assert false : "Unexpected value for access point: " + mAccessPoint; - } - } - private void recordSigninImpressionWithAccountUserAction() { - switch (mAccessPoint) { - case SigninAccessPoint.BOOKMARK_MANAGER: - RecordUserAction.record("Signin_ImpressionWithAccount_FromBookmarkManager"); - break; - case SigninAccessPoint.NTP_CONTENT_SUGGESTIONS: - // TODO(iuliah): record Signin_ImpressionWithAccount_FromNTPContentSuggestions. - break; - case SigninAccessPoint.RECENT_TABS: - RecordUserAction.record("Signin_ImpressionWithAccount_FromRecentTabs"); - break; - case SigninAccessPoint.SETTINGS: - RecordUserAction.record("Signin_ImpressionWithAccount_FromSettings"); - break; - default: - assert false : "Unexpected value for access point: " + mAccessPoint; + if (mImpressionWithAccountUserActionName != null) { + RecordUserAction.record(mImpressionWithAccountUserActionName); } } private void recordSigninImpressionWithNoAccountUserAction() { - switch (mAccessPoint) { - case SigninAccessPoint.BOOKMARK_MANAGER: - RecordUserAction.record("Signin_ImpressionWithNoAccount_FromBookmarkManager"); - break; - case SigninAccessPoint.NTP_CONTENT_SUGGESTIONS: - // TODO(iuliah): record Signin_ImpressionWithNoAccount_FromNTPContentSuggestions. - break; - case SigninAccessPoint.RECENT_TABS: - RecordUserAction.record("Signin_ImpressionWithNoAccount_FromRecentTabs"); - break; - case SigninAccessPoint.SETTINGS: - RecordUserAction.record("Signin_ImpressionWithNoAccount_FromSettings"); - break; - default: - assert false : "Unexpected value for access point: " + mAccessPoint; + if (mImpressionWithNoAccountUserActionName != null) { + RecordUserAction.record(mImpressionWithNoAccountUserActionName); } } - private void setDescriptionText(SigninPromoView view) { - final @StringRes int descriptionTextResource; - switch (mAccessPoint) { - case SigninAccessPoint.BOOKMARK_MANAGER: - descriptionTextResource = R.string.signin_promo_description_bookmarks; - break; - case SigninAccessPoint.NTP_CONTENT_SUGGESTIONS: - descriptionTextResource = R.string.signin_promo_description_ntp_content_suggestions; - break; - case SigninAccessPoint.RECENT_TABS: - descriptionTextResource = R.string.signin_promo_description_recent_tabs; - break; - case SigninAccessPoint.SETTINGS: - descriptionTextResource = R.string.signin_promo_description_settings; - break; - default: - assert false : "Unexpected value for access point: " + mAccessPoint; - return; - } - view.getDescription().setText(descriptionTextResource); - } - private void setupColdState(final Context context, SigninPromoView view) { view.getImage().setImageResource(R.drawable.chrome_sync_logo); setImageSize(context, view, R.dimen.signin_promo_cold_state_image_size);
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 689dfbca..107043d 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -5828,6 +5828,9 @@ <message name="IDS_AD_AUTH_NETWORK_ERROR" desc="Error message to show when there is a problem contacting the logon server when authenticating for Active Directory enrollment."> Oops! There was a problem contacting the logon server. Please check your network connection and the domain name, then try again. </message> + <message name="IDS_AD_AUTH_UNKNOWN_ERROR" desc="Error message to show that occurs something a user could not fix."> + Oops! An unknown error occurred. Please try again later or contact your administrator if the issue persists. + </message> <message name="IDS_ENTERPRISE_ENROLLMENT_ATTRIBUTE_EXPLANATION" desc="Device attribute message to be shown on attribute update prompt screen."> Optional — enter new or update existing information to be associated with this device. </message>
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 839d0fe..875fe70 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -229,9 +229,12 @@ <message name="IDS_PERMISSIONS_BUBBLE_PERSIST_TEXT" desc="The label for the checkbox used to allow users to optionally persist a permission request decision"> Remember my decision </message> - <message name="IDS_PERMISSIONS_BUBBLE_PROMPT" desc="The label that is used to introduce permission request details to the user in a papup."> + <message name="IDS_PERMISSIONS_BUBBLE_PROMPT" desc="The label that is used to introduce permission request details to the user in a popup."> <ph name="SITE_NAME">$1<ex>google.com</ex></ph> wants to </message> + <message name="IDS_PERMISSIONS_BUBBLE_ACCESSIBLE_TITLE" desc="The sentence read out by screen readers to describe the permission request popup."> + <ph name="SITE_NAME">$1<ex>google.com</ex></ph> has a permission request. + </message> <message name="IDS_PERMISSION_ALLOW" desc="Label on button to allow a permissions request."> Allow </message>
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index ff686fb..9ab005c 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -2242,12 +2242,16 @@ <message name="IDS_SETTINGS_SITE_SETTINGS_BLOCK_DEFAULT_MENU" desc="Label for the default menu item to block a permission for a particular site."> Block (default) </message> + <!-- TODO(https://crbug.com/753173): Consolidate these strings with those used in the Page Info bubble. --> <message name="IDS_SETTINGS_SITE_SETTINGS_ALLOW_MENU" desc="Label for the menu item to allow permission for a particular site."> Allow </message> <message name="IDS_SETTINGS_SITE_SETTINGS_BLOCK_MENU" desc="Label for the menu item to block permission for a particular site."> Block </message> + <message name="IDS_SETTINGS_SITE_SETTINGS_ASK_MENU" desc="Label for the menu item to ask for permission for a particular site."> + Ask + </message> <message name="IDS_SETTINGS_SITE_SETTINGS_RESET_MENU" desc="Label for the menu item to remove the permission for a particular site (make it ask you again next time)."> Remove </message>
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index 26c4f42..b44d0a9 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd
@@ -267,6 +267,7 @@ <structure type="chrome_scaled_image" name="IDR_NOTIFICATION_DRIVE" file="cros/notification_drive.png" /> <structure type="chrome_scaled_image" name="IDR_NOTIFICATION_FINGERPRINT" file="cros/notification_fingerprint.png" /> <structure type="chrome_scaled_image" name="IDR_NOTIFICATION_PERIPHERAL_BATTERY_LOW" file="cros/notification_peripheral_battery_low.png" /> + <structure type="chrome_scaled_image" name="IDR_NOTIFICATION_STYLUS_BATTERY_LOW" file="cros/notification_peripheral_battery_low.png" /> <structure type="chrome_scaled_image" name="IDR_PORTAL_DETECTION_ALERT" file="cros/captive_portal_icon.png" /> <structure type="chrome_scaled_image" name="IDR_ARC_PLAY_STORE_NOTIFICATION" file="cros/notification_play_store.png" /> <structure type="chrome_scaled_image" name="IDR_ARC_PLAY_STORE_OPTIN_IN_PROGRESS_NOTIFICATION" file="cros/notification_play_store_optin_in_progress.png" />
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn index 87ac0e6..df27f4c6 100644 --- a/chrome/app/vector_icons/BUILD.gn +++ b/chrome/app/vector_icons/BUILD.gn
@@ -69,7 +69,6 @@ "remove_box.icon", "sad_tab.icon", "settings.icon", - "open_in_new.icon", "smartphone.icon", "subresource_filter_active.icon", "supervisor_account.icon",
diff --git a/chrome/app/vector_icons/open_in_new.icon b/chrome/app/vector_icons/open_in_new.icon deleted file mode 100644 index f998ec7f..0000000 --- a/chrome/app/vector_icons/open_in_new.icon +++ /dev/null
@@ -1,31 +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. - -MOVE_TO, 38, 38, -H_LINE_TO, 10, -V_LINE_TO, 10, -R_H_LINE_TO, 14, -V_LINE_TO, 6, -H_LINE_TO, 10, -R_CUBIC_TO, -2.21f, 0, -4, 1.79f, -4, 4, -R_V_LINE_TO, 28, -R_CUBIC_TO, 0, 2.21f, 1.79f, 4, 4, 4, -R_H_LINE_TO, 28, -R_CUBIC_TO, 2.21f, 0, 4, -1.79f, 4, -4, -V_LINE_TO, 24, -R_H_LINE_TO, -4, -R_V_LINE_TO, 14, -CLOSE, -MOVE_TO, 28, 6, -R_V_LINE_TO, 4, -R_H_LINE_TO, 7.17f, -LINE_TO, 15.51f, 29.66f, -R_LINE_TO, 2.83f, 2.83f, -LINE_TO, 38, 12.83f, -V_LINE_TO, 20, -R_H_LINE_TO, 4, -V_LINE_TO, 6, -H_LINE_TO, 28, -CLOSE, -END
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index bbbed59c..9779f24 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2250,11 +2250,13 @@ } deps += [ "//components/offline_pages/content/background_loader", + "//components/offline_pages/content/renovations", "//components/offline_pages/core", "//components/offline_pages/core/background:background_offliner", "//components/offline_pages/core/downloads:offline_pages_ui_adapter", "//components/offline_pages/core/prefetch", "//components/offline_pages/core/recent_tabs", + "//components/offline_pages/core/renovations", "//components/offline_pages/core/request_header:request_header", ] }
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index d70d42ac..fca4630 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2188,6 +2188,9 @@ {"enable-webvr-autopresent", flag_descriptions::kWebVrAutopresentName, flag_descriptions::kWebVrAutopresentDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kWebVrAutopresent)}, + {"enable-webvr-vsync-align", flag_descriptions::kWebVrVsyncAlignName, + flag_descriptions::kWebVrVsyncAlignDescription, kOsAndroid, + FEATURE_VALUE_TYPE(features::kWebVrVsyncAlign)}, #endif // OS_ANDROID #endif // ENABLE_VR #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.cc b/chrome/browser/android/vr_shell/vr_shell_gl.cc index 7e6f506..9825d4f1 100644 --- a/chrome/browser/android/vr_shell/vr_shell_gl.cc +++ b/chrome/browser/android/vr_shell/vr_shell_gl.cc
@@ -26,6 +26,7 @@ #include "chrome/browser/vr/ui_scene.h" #include "chrome/browser/vr/vr_gl_util.h" #include "chrome/browser/vr/vr_shell_renderer.h" +#include "content/public/common/content_features.h" #include "device/vr/android/gvr/gvr_delegate.h" #include "device/vr/android/gvr/gvr_device.h" #include "device/vr/android/gvr/gvr_gamepad_data_provider.h" @@ -258,6 +259,8 @@ // into parts. browser_->OnGlInitialized(content_texture_id_); + webvr_vsync_align_ = base::FeatureList::IsEnabled(features::kWebVrVsyncAlign); + gfx::Size webvr_size = device::GvrDelegate::GetRecommendedWebVrSize(gvr_api_.get()); DVLOG(1) << __FUNCTION__ << ": resize initial to " << webvr_size.width() @@ -1096,7 +1099,7 @@ // In surfaceless (reprojecting) rendering, stay locked // to vsync intervals. Otherwise, for legacy Cardboard mode, // run requested animation frames now if it missed a vsync. - if (surfaceless_rendering_ || !pending_vsync_) { + if ((surfaceless_rendering_ && webvr_vsync_align_) || !pending_vsync_) { if (!callback_.is_null()) { mojo::ReportBadMessage( "Requested VSync before waiting for response to previous request.");
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.h b/chrome/browser/android/vr_shell/vr_shell_gl.h index 2d4c0e3..ca02c9f2 100644 --- a/chrome/browser/android/vr_shell/vr_shell_gl.h +++ b/chrome/browser/android/vr_shell/vr_shell_gl.h
@@ -191,6 +191,9 @@ // samplerExternalOES texture data for WebVR content image. int webvr_texture_id_ = 0; + // Set from feature flag. + bool webvr_vsync_align_; + scoped_refptr<gl::GLSurface> surface_; scoped_refptr<gl::GLContext> context_; scoped_refptr<gl::SurfaceTexture> content_surface_texture_;
diff --git a/chrome/browser/apps/app_url_redirector.cc b/chrome/browser/apps/app_url_redirector.cc index 4b10b98d..45adafa 100644 --- a/chrome/browser/apps/app_url_redirector.cc +++ b/chrome/browser/apps/app_url_redirector.cc
@@ -38,6 +38,15 @@ const Extension* app, content::WebContents* source, const navigation_interception::NavigationParams& params) { + DVLOG(1) << "ShouldOverrideNavigation called for: " << params.url(); + + ui::PageTransition transition_type = params.transition_type(); + if (!(PageTransitionCoreTypeIs(transition_type, ui::PAGE_TRANSITION_LINK))) { + DVLOG(1) << "Don't override: Transition type is " + << PageTransitionGetCoreTransitionString(transition_type); + return false; + } + Browser* browser = chrome::FindBrowserWithWebContents(source); if (browser == nullptr) { DVLOG(1) << "Don't override: No browser, can't know if already in app.";
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 4a1059e..fc35719 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -158,6 +158,8 @@ <include name="IDR_MD_DOWNLOADS_DOWNLOADS_HTML" file="resources\md_downloads\downloads.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_MD_DOWNLOADS_ACTION_SERVICE_HTML" file="resources\md_downloads\action_service.html" type="BINDATA" /> <include name="IDR_MD_DOWNLOADS_ACTION_SERVICE_JS" file="resources\md_downloads\action_service.js" type="BINDATA" /> + <include name="IDR_MD_DOWNLOADS_BROWSER_PROXY_HTML" file="resources\md_downloads\browser_proxy.html" type="BINDATA" /> + <include name="IDR_MD_DOWNLOADS_BROWSER_PROXY_JS" file="resources\md_downloads\browser_proxy.js" type="BINDATA" /> <include name="IDR_MD_DOWNLOADS_CONSTANTS_HTML" file="resources\md_downloads\constants.html" type="BINDATA" /> <include name="IDR_MD_DOWNLOADS_CONSTANTS_JS" file="resources\md_downloads\constants.js" type="BINDATA" /> <include name="IDR_MD_DOWNLOADS_DOWNLOADS_JS" file="resources\md_downloads\downloads.js" type="BINDATA" /> @@ -181,8 +183,6 @@ <include name="IDR_EXTENSIONS_SHORTCUT_UTIL_HTML" file="resources\extensions\shortcut_util.html" type="BINDATA" /> <include name="IDR_EXTENSIONS_SHORTCUT_UTIL_JS" file="resources\extensions\shortcut_util.js" type="BINDATA" /> <include name="IDR_MD_EXTENSIONS_EXTENSIONS_JS" file="resources\md_extensions\extensions.js" type="BINDATA" /> - <include name="IDR_MD_EXTENSIONS_ANIMATION_HELPER_HTML" file="resources\md_extensions\animation_helper.html" type="BINDATA" /> - <include name="IDR_MD_EXTENSIONS_ANIMATION_HELPER_JS" file="resources\md_extensions\animation_helper.js" type="BINDATA" /> <include name="IDR_MD_EXTENSIONS_CODE_SECTION_HTML" file="resources\md_extensions\code_section.html" type="BINDATA" /> <include name="IDR_MD_EXTENSIONS_CODE_SECTION_JS" file="resources\md_extensions\code_section.js" type="BINDATA" /> <include name="IDR_MD_EXTENSIONS_DETAIL_VIEW_HTML" file="resources\md_extensions\detail_view.html" type="BINDATA" /> @@ -221,6 +221,8 @@ <include name="IDR_MD_EXTENSIONS_TOOLBAR_HTML" file="resources\md_extensions\toolbar.html" type="BINDATA" /> <include name="IDR_MD_EXTENSIONS_TOOLBAR_JS" file="resources\md_extensions\toolbar.js" type="BINDATA" /> <include name="IDR_MD_EXTENSIONS_STRINGS_HTML" file="resources\md_extensions\strings.html" type="BINDATA" /> + <include name="IDR_MD_EXTENSIONS_VIEW_MANAGER_HTML" file="resources\md_extensions\view_manager.html" type="BINDATA" /> + <include name="IDR_MD_EXTENSIONS_VIEW_MANAGER_JS" file="resources\md_extensions\view_manager.js" type="BINDATA" /> </if> <include name="IDR_FEEDBACK_MANIFEST" file="resources\feedback\manifest.json" type="BINDATA" /> <if expr="not is_android">
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 3f69c8f6..8144ff5 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -246,7 +246,6 @@ #include "chrome/browser/chromeos/file_system_provider/fileapi/backend_delegate.h" #include "chrome/browser/chromeos/fileapi/file_system_backend.h" #include "chrome/browser/chromeos/fileapi/mtp_file_system_backend_delegate.h" -#include "chrome/browser/chromeos/fileapi/recent_backend_delegate.h" #include "chrome/browser/chromeos/login/signin/merge_session_navigation_throttle.h" #include "chrome/browser/chromeos/login/signin/merge_session_throttling_utils.h" #include "chrome/browser/chromeos/login/startup_utils.h" @@ -2726,7 +2725,6 @@ storage_partition_path), base::MakeUnique<arc::ArcContentFileSystemBackendDelegate>(), base::MakeUnique<arc::ArcDocumentsProviderBackendDelegate>(), - base::MakeUnique<chromeos::RecentBackendDelegate>(), external_mount_points, storage::ExternalMountPoints::GetSystemInstance()); backend->AddSystemMountPoints(); DCHECK(backend->CanHandleType(storage::kFileSystemTypeExternal));
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index f831cc8..c021113e 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -710,10 +710,6 @@ "fileapi/mtp_file_system_backend_delegate.h", "fileapi/mtp_watcher_manager.cc", "fileapi/mtp_watcher_manager.h", - "fileapi/recent_async_file_util.cc", - "fileapi/recent_async_file_util.h", - "fileapi/recent_backend_delegate.cc", - "fileapi/recent_backend_delegate.h", "fileapi/recent_context.cc", "fileapi/recent_context.h", "fileapi/recent_model.cc",
diff --git a/chrome/browser/chromeos/fileapi/file_system_backend.cc b/chrome/browser/chromeos/fileapi/file_system_backend.cc index a1413849..3ed4d84 100644 --- a/chrome/browser/chromeos/fileapi/file_system_backend.cc +++ b/chrome/browser/chromeos/fileapi/file_system_backend.cc
@@ -54,8 +54,7 @@ url.type() == storage::kFileSystemTypeProvided || url.type() == storage::kFileSystemTypeDeviceMediaAsFileStorage || url.type() == storage::kFileSystemTypeArcContent || - url.type() == storage::kFileSystemTypeArcDocumentsProvider || - url.type() == storage::kFileSystemTypeRecent; + url.type() == storage::kFileSystemTypeArcDocumentsProvider; } FileSystemBackend::FileSystemBackend( @@ -64,7 +63,6 @@ std::unique_ptr<FileSystemBackendDelegate> mtp_delegate, std::unique_ptr<FileSystemBackendDelegate> arc_content_delegate, std::unique_ptr<FileSystemBackendDelegate> arc_documents_provider_delegate, - std::unique_ptr<FileSystemBackendDelegate> recent_delegate, scoped_refptr<storage::ExternalMountPoints> mount_points, storage::ExternalMountPoints* system_mount_points) : file_access_permissions_(new FileAccessPermissions()), @@ -75,7 +73,6 @@ arc_content_delegate_(std::move(arc_content_delegate)), arc_documents_provider_delegate_( std::move(arc_documents_provider_delegate)), - recent_delegate_(std::move(recent_delegate)), mount_points_(mount_points), system_mount_points_(system_mount_points) {} @@ -113,7 +110,6 @@ case storage::kFileSystemTypeProvided: case storage::kFileSystemTypeArcContent: case storage::kFileSystemTypeArcDocumentsProvider: - case storage::kFileSystemTypeRecent: return true; default: return false; @@ -289,8 +285,6 @@ return arc_content_delegate_->GetAsyncFileUtil(type); case storage::kFileSystemTypeArcDocumentsProvider: return arc_documents_provider_delegate_->GetAsyncFileUtil(type); - case storage::kFileSystemTypeRecent: - return recent_delegate_->GetAsyncFileUtil(type); default: NOTREACHED(); } @@ -348,8 +342,7 @@ url.type() == storage::kFileSystemTypeDrive || url.type() == storage::kFileSystemTypeProvided || url.type() == storage::kFileSystemTypeArcContent || - url.type() == storage::kFileSystemTypeArcDocumentsProvider || - url.type() == storage::kFileSystemTypeRecent); + url.type() == storage::kFileSystemTypeArcDocumentsProvider); return storage::FileSystemOperation::Create( url, context, base::MakeUnique<storage::FileSystemOperationContext>(context)); @@ -361,8 +354,7 @@ url.type() == storage::kFileSystemTypeProvided || url.type() == storage::kFileSystemTypeDeviceMediaAsFileStorage || url.type() == storage::kFileSystemTypeArcContent || - url.type() == storage::kFileSystemTypeArcDocumentsProvider || - url.type() == storage::kFileSystemTypeRecent; + url.type() == storage::kFileSystemTypeArcDocumentsProvider; } bool FileSystemBackend::HasInplaceCopyImplementation( @@ -376,7 +368,6 @@ case storage::kFileSystemTypeRestrictedNativeLocal: case storage::kFileSystemTypeArcContent: case storage::kFileSystemTypeArcDocumentsProvider: - case storage::kFileSystemTypeRecent: return false; default: NOTREACHED(); @@ -417,9 +408,6 @@ case storage::kFileSystemTypeArcDocumentsProvider: return arc_documents_provider_delegate_->CreateFileStreamReader( url, offset, max_bytes_to_read, expected_modification_time, context); - case storage::kFileSystemTypeRecent: - return recent_delegate_->CreateFileStreamReader( - url, offset, max_bytes_to_read, expected_modification_time, context); default: NOTREACHED(); } @@ -453,7 +441,6 @@ case storage::kFileSystemTypeRestrictedNativeLocal: case storage::kFileSystemTypeArcContent: case storage::kFileSystemTypeArcDocumentsProvider: - case storage::kFileSystemTypeRecent: return std::unique_ptr<storage::FileStreamWriter>(); default: NOTREACHED(); @@ -490,7 +477,6 @@ case storage::kFileSystemTypeRestrictedNativeLocal: case storage::kFileSystemTypeArcContent: case storage::kFileSystemTypeArcDocumentsProvider: - case storage::kFileSystemTypeRecent: callback.Run(GURL()); return; default:
diff --git a/chrome/browser/chromeos/fileapi/file_system_backend.h b/chrome/browser/chromeos/fileapi/file_system_backend.h index e67bd8f..4a796d8 100644 --- a/chrome/browser/chromeos/fileapi/file_system_backend.h +++ b/chrome/browser/chromeos/fileapi/file_system_backend.h
@@ -75,7 +75,6 @@ std::unique_ptr<FileSystemBackendDelegate> arc_content_delegate, std::unique_ptr<FileSystemBackendDelegate> arc_documents_provider_delegate, - std::unique_ptr<FileSystemBackendDelegate> recent_delegate, scoped_refptr<storage::ExternalMountPoints> mount_points, storage::ExternalMountPoints* system_mount_points); ~FileSystemBackend() override; @@ -161,9 +160,6 @@ // The delegate instance for the ARC documents provider related operations. std::unique_ptr<FileSystemBackendDelegate> arc_documents_provider_delegate_; - // The delegate instance for the Recent file system related operations. - std::unique_ptr<FileSystemBackendDelegate> recent_delegate_; - // Mount points specific to the owning context (i.e. per-profile mount // points). //
diff --git a/chrome/browser/chromeos/fileapi/file_system_backend_unittest.cc b/chrome/browser/chromeos/fileapi/file_system_backend_unittest.cc index 50adba8..70eac8eb 100644 --- a/chrome/browser/chromeos/fileapi/file_system_backend_unittest.cc +++ b/chrome/browser/chromeos/fileapi/file_system_backend_unittest.cc
@@ -47,7 +47,6 @@ nullptr, // mtp_delegate nullptr, // arc_content_delegate nullptr, // arc_documents_provider_delegate - nullptr, // recent_delegate mount_points.get(), storage::ExternalMountPoints::GetSystemInstance()); backend.AddSystemMountPoints(); std::vector<base::FilePath> root_dirs = backend.GetRootDirectories(); @@ -76,7 +75,6 @@ nullptr, // mtp_delegate nullptr, // arc_content_delegate nullptr, // arc_documents_provider_delegate - nullptr, // recent_delegate mount_points.get(), system_mount_points.get()); const size_t initial_root_dirs_size = backend.GetRootDirectories().size(); @@ -124,7 +122,6 @@ nullptr, // mtp_delegate nullptr, // arc_content_delegate nullptr, // arc_documents_provider_delegate - nullptr, // recent_delegate mount_points.get(), system_mount_points.get()); std::string extension("ddammdhioacbehjngdmkjcjbnfginlla"); @@ -195,7 +192,6 @@ nullptr, // mtp_delegate nullptr, // arc_content_delegate nullptr, // arc_documents_provider_delegate - nullptr, // recent_delegate mount_points.get(), system_mount_points.get()); const storage::FileSystemType type = storage::kFileSystemTypeNativeLocal;
diff --git a/chrome/browser/chromeos/fileapi/recent_async_file_util.cc b/chrome/browser/chromeos/fileapi/recent_async_file_util.cc deleted file mode 100644 index 2b74fe3..0000000 --- a/chrome/browser/chromeos/fileapi/recent_async_file_util.cc +++ /dev/null
@@ -1,173 +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 "chrome/browser/chromeos/fileapi/recent_async_file_util.h" - -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/time/time.h" -#include "content/public/browser/browser_thread.h" -#include "storage/browser/blob/shareable_file_reference.h" -#include "storage/browser/fileapi/file_system_context.h" -#include "storage/browser/fileapi/file_system_operation_context.h" -#include "storage/browser/fileapi/file_system_url.h" - -using content::BrowserThread; - -class Profile; - -namespace chromeos { - -RecentAsyncFileUtil::RecentAsyncFileUtil() : weak_ptr_factory_(this) {} - -RecentAsyncFileUtil::~RecentAsyncFileUtil() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); -} - -void RecentAsyncFileUtil::CreateOrOpen( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - int file_flags, - const CreateOrOpenCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - // TODO(nya): Implement this function if it is ever called. - NOTIMPLEMENTED(); - callback.Run(base::File(base::File::FILE_ERROR_INVALID_OPERATION), - base::Closure()); -} - -void RecentAsyncFileUtil::EnsureFileExists( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - const EnsureFileExistsCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - NOTREACHED(); // Read-only file system. - callback.Run(base::File::FILE_ERROR_ACCESS_DENIED, false); -} - -void RecentAsyncFileUtil::CreateDirectory( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - bool exclusive, - bool recursive, - const StatusCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - NOTREACHED(); // Read-only file system. - callback.Run(base::File::FILE_ERROR_ACCESS_DENIED); -} - -void RecentAsyncFileUtil::GetFileInfo( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - int fields, - const GetFileInfoCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - NOTIMPLEMENTED(); // TODO(nya): Implement this function. - callback.Run(base::File::FILE_ERROR_FAILED, base::File::Info()); -} - -void RecentAsyncFileUtil::ReadDirectory( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - const ReadDirectoryCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - NOTIMPLEMENTED(); // TODO(nya): Implement this function. - callback.Run(base::File::FILE_ERROR_FAILED, EntryList(), false); -} - -void RecentAsyncFileUtil::Touch( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - const base::Time& last_access_time, - const base::Time& last_modified_time, - const StatusCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - NOTREACHED(); // Read-only file system. - callback.Run(base::File::FILE_ERROR_ACCESS_DENIED); -} - -void RecentAsyncFileUtil::Truncate( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - int64_t length, - const StatusCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - NOTREACHED(); // Read-only file system. - callback.Run(base::File::FILE_ERROR_ACCESS_DENIED); -} - -void RecentAsyncFileUtil::CopyFileLocal( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& src_url, - const storage::FileSystemURL& dest_url, - CopyOrMoveOption option, - const CopyFileProgressCallback& progress_callback, - const StatusCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - NOTREACHED(); // Read-only file system. - callback.Run(base::File::FILE_ERROR_ACCESS_DENIED); -} - -void RecentAsyncFileUtil::MoveFileLocal( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& src_url, - const storage::FileSystemURL& dest_url, - CopyOrMoveOption option, - const StatusCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - NOTREACHED(); // Read-only file system. - callback.Run(base::File::FILE_ERROR_ACCESS_DENIED); -} - -void RecentAsyncFileUtil::CopyInForeignFile( - std::unique_ptr<storage::FileSystemOperationContext> context, - const base::FilePath& src_file_path, - const storage::FileSystemURL& dest_url, - const StatusCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - NOTREACHED(); // Read-only file system. - callback.Run(base::File::FILE_ERROR_ACCESS_DENIED); -} - -void RecentAsyncFileUtil::DeleteFile( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - const StatusCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - NOTREACHED(); // Read-only file system. - callback.Run(base::File::FILE_ERROR_ACCESS_DENIED); -} - -void RecentAsyncFileUtil::DeleteDirectory( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - const StatusCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - NOTREACHED(); // Read-only file system. - callback.Run(base::File::FILE_ERROR_ACCESS_DENIED); -} - -void RecentAsyncFileUtil::DeleteRecursively( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - const StatusCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - NOTREACHED(); // Read-only file system. - callback.Run(base::File::FILE_ERROR_ACCESS_DENIED); -} - -void RecentAsyncFileUtil::CreateSnapshotFile( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - const CreateSnapshotFileCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - NOTIMPLEMENTED(); // TODO(crbug.com/671511): Implement this function. - callback.Run(base::File::FILE_ERROR_FAILED, base::File::Info(), - base::FilePath(), - scoped_refptr<storage::ShareableFileReference>()); -} - -} // namespace chromeos
diff --git a/chrome/browser/chromeos/fileapi/recent_async_file_util.h b/chrome/browser/chromeos/fileapi/recent_async_file_util.h deleted file mode 100644 index 152af3c7..0000000 --- a/chrome/browser/chromeos/fileapi/recent_async_file_util.h +++ /dev/null
@@ -1,100 +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. - -#ifndef CHROME_BROWSER_CHROMEOS_FILEAPI_RECENT_ASYNC_FILE_UTIL_H_ -#define CHROME_BROWSER_CHROMEOS_FILEAPI_RECENT_ASYNC_FILE_UTIL_H_ - -#include <memory> - -#include "base/callback_forward.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "storage/browser/fileapi/async_file_util.h" - -namespace chromeos { - -// The implementation of storage::AsyncFileUtil for recent. -// -// All of the methods must be called on the IO thread. -class RecentAsyncFileUtil : public storage::AsyncFileUtil { - public: - RecentAsyncFileUtil(); - ~RecentAsyncFileUtil() override; - - // storage::AsyncFileUtil overrides. - void CreateOrOpen( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - int file_flags, - const CreateOrOpenCallback& callback) override; - void EnsureFileExists( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - const EnsureFileExistsCallback& callback) override; - void CreateDirectory( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - bool exclusive, - bool recursive, - const StatusCallback& callback) override; - void GetFileInfo(std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - int fields, - const GetFileInfoCallback& callback) override; - void ReadDirectory( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - const ReadDirectoryCallback& callback) override; - void Touch(std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - const base::Time& last_access_time, - const base::Time& last_modified_time, - const StatusCallback& callback) override; - void Truncate(std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - int64_t length, - const StatusCallback& callback) override; - void CopyFileLocal( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& src_url, - const storage::FileSystemURL& dest_url, - CopyOrMoveOption option, - const CopyFileProgressCallback& progress_callback, - const StatusCallback& callback) override; - void MoveFileLocal( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& src_url, - const storage::FileSystemURL& dest_url, - CopyOrMoveOption option, - const StatusCallback& callback) override; - void CopyInForeignFile( - std::unique_ptr<storage::FileSystemOperationContext> context, - const base::FilePath& src_file_path, - const storage::FileSystemURL& dest_url, - const StatusCallback& callback) override; - void DeleteFile(std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - const StatusCallback& callback) override; - void DeleteDirectory( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - const StatusCallback& callback) override; - void DeleteRecursively( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - const StatusCallback& callback) override; - void CreateSnapshotFile( - std::unique_ptr<storage::FileSystemOperationContext> context, - const storage::FileSystemURL& url, - const CreateSnapshotFileCallback& callback) override; - - private: - base::WeakPtrFactory<RecentAsyncFileUtil> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(RecentAsyncFileUtil); -}; - -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_FILEAPI_RECENT_ASYNC_FILE_UTIL_H_
diff --git a/chrome/browser/chromeos/fileapi/recent_backend_delegate.cc b/chrome/browser/chromeos/fileapi/recent_backend_delegate.cc deleted file mode 100644 index ed59b4e..0000000 --- a/chrome/browser/chromeos/fileapi/recent_backend_delegate.cc +++ /dev/null
@@ -1,69 +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 "chrome/browser/chromeos/fileapi/recent_backend_delegate.h" - -#include <utility> - -#include "base/logging.h" -#include "base/memory/ptr_util.h" -#include "content/public/browser/browser_thread.h" -#include "storage/browser/fileapi/file_stream_reader.h" -#include "storage/browser/fileapi/file_stream_writer.h" -#include "url/gurl.h" - -using content::BrowserThread; - -namespace chromeos { - -RecentBackendDelegate::RecentBackendDelegate() = default; - -RecentBackendDelegate::~RecentBackendDelegate() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); -} - -storage::AsyncFileUtil* RecentBackendDelegate::GetAsyncFileUtil( - storage::FileSystemType type) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - return &async_file_util_; -} - -std::unique_ptr<storage::FileStreamReader> -RecentBackendDelegate::CreateFileStreamReader( - const storage::FileSystemURL& url, - int64_t offset, - int64_t max_bytes_to_read, - const base::Time& expected_modification_time, - storage::FileSystemContext* context) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - NOTIMPLEMENTED(); // TODO(nya): Implement this function. - return nullptr; -} - -std::unique_ptr<storage::FileStreamWriter> -RecentBackendDelegate::CreateFileStreamWriter( - const storage::FileSystemURL& url, - int64_t offset, - storage::FileSystemContext* context) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - NOTREACHED(); // Read-only file system. - return nullptr; -} - -storage::WatcherManager* RecentBackendDelegate::GetWatcherManager( - storage::FileSystemType type) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - NOTREACHED(); // Never called by chromeos::FileSystemBackend. - return nullptr; -} - -void RecentBackendDelegate::GetRedirectURLForContents( - const storage::FileSystemURL& url, - const storage::URLCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - NOTREACHED(); // Never called by chromeos::FileSystemBackend. - callback.Run(GURL()); -} - -} // namespace chromeos
diff --git a/chrome/browser/chromeos/fileapi/recent_backend_delegate.h b/chrome/browser/chromeos/fileapi/recent_backend_delegate.h deleted file mode 100644 index 74d4034..0000000 --- a/chrome/browser/chromeos/fileapi/recent_backend_delegate.h +++ /dev/null
@@ -1,48 +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. - -#ifndef CHROME_BROWSER_CHROMEOS_FILEAPI_RECENT_BACKEND_DELEGATE_H_ -#define CHROME_BROWSER_CHROMEOS_FILEAPI_RECENT_BACKEND_DELEGATE_H_ - -#include <memory> - -#include "base/macros.h" -#include "chrome/browser/chromeos/fileapi/file_system_backend_delegate.h" -#include "chrome/browser/chromeos/fileapi/recent_async_file_util.h" - -namespace chromeos { - -// Implements recent file system. -class RecentBackendDelegate : public FileSystemBackendDelegate { - public: - RecentBackendDelegate(); - ~RecentBackendDelegate() override; - - // FileSystemBackend::Delegate overrides. - storage::AsyncFileUtil* GetAsyncFileUtil( - storage::FileSystemType type) override; - std::unique_ptr<storage::FileStreamReader> CreateFileStreamReader( - const storage::FileSystemURL& url, - int64_t offset, - int64_t max_bytes_to_read, - const base::Time& expected_modification_time, - storage::FileSystemContext* context) override; - std::unique_ptr<storage::FileStreamWriter> CreateFileStreamWriter( - const storage::FileSystemURL& url, - int64_t offset, - storage::FileSystemContext* context) override; - storage::WatcherManager* GetWatcherManager( - storage::FileSystemType type) override; - void GetRedirectURLForContents(const storage::FileSystemURL& url, - const storage::URLCallback& callback) override; - - private: - RecentAsyncFileUtil async_file_util_; - - DISALLOW_COPY_AND_ASSIGN(RecentBackendDelegate); -}; - -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_FILEAPI_RECENT_BACKEND_DELEGATE_H_
diff --git a/chrome/browser/chromeos/fileapi/recent_model.cc b/chrome/browser/chromeos/fileapi/recent_model.cc index 6ab804aa..1aa38d7 100644 --- a/chrome/browser/chromeos/fileapi/recent_model.cc +++ b/chrome/browser/chromeos/fileapi/recent_model.cc
@@ -54,15 +54,17 @@ : RecentModel(CreateDefaultSources(profile)) {} RecentModel::RecentModel(std::vector<std::unique_ptr<RecentSource>> sources) - : sources_(std::move(sources)), weak_ptr_factory_(this) {} + : sources_(std::move(sources)), weak_ptr_factory_(this) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); +} RecentModel::~RecentModel() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_CURRENTLY_ON(BrowserThread::UI); } void RecentModel::GetRecentFiles(RecentContext context, GetRecentFilesCallback callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // Use cache if available. if (cached_files_.has_value()) { @@ -95,7 +97,7 @@ } void RecentModel::OnGetRecentFiles(RecentFileList files) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_LT(0, num_inflight_sources_); @@ -109,7 +111,7 @@ } void RecentModel::OnGetRecentFilesCompleted() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_EQ(0, num_inflight_sources_); DCHECK(!cached_files_.has_value()); @@ -135,7 +137,7 @@ } void RecentModel::ClearCache() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_CURRENTLY_ON(BrowserThread::UI); cached_files_.reset(); }
diff --git a/chrome/browser/chromeos/fileapi/recent_model.h b/chrome/browser/chromeos/fileapi/recent_model.h index 5e39252..b6288ba1 100644 --- a/chrome/browser/chromeos/fileapi/recent_model.h +++ b/chrome/browser/chromeos/fileapi/recent_model.h
@@ -31,7 +31,7 @@ // Provides a list of recently modified files. // -// All member functions must be called on the IO thread unless stated otherwise. +// All member functions must be called on the UI thread. class RecentModel : public KeyedService { public: using RecentFileList = std::vector<storage::FileSystemURL>; @@ -41,11 +41,9 @@ ~RecentModel() override; // Returns an instance for the given profile. - // This function must be called on the UI thread. static RecentModel* GetForProfile(Profile* profile); // Creates an instance with given sources. Only for testing. - // This function can be called on any thread. static std::unique_ptr<RecentModel> CreateForTest( std::vector<std::unique_ptr<RecentSource>> sources);
diff --git a/chrome/browser/chromeos/fileapi/recent_source.h b/chrome/browser/chromeos/fileapi/recent_source.h index 1c65f805..bbe745a 100644 --- a/chrome/browser/chromeos/fileapi/recent_source.h +++ b/chrome/browser/chromeos/fileapi/recent_source.h
@@ -22,7 +22,7 @@ // local directories and cloud storages. To provide files to Recent file // system, this interface should be implemented for each source. // -// All member functions must be called on the IO thread. +// All member functions must be called on the UI thread. class RecentSource { public: using RecentFileList = std::vector<storage::FileSystemURL>;
diff --git a/chrome/browser/chromeos/fileapi/test/fake_recent_source.h b/chrome/browser/chromeos/fileapi/test/fake_recent_source.h index 3c02d6f57..214992ed 100644 --- a/chrome/browser/chromeos/fileapi/test/fake_recent_source.h +++ b/chrome/browser/chromeos/fileapi/test/fake_recent_source.h
@@ -15,7 +15,7 @@ // Fake implementation of RecentSource that returns a canned set of files. // -// All member functions must be called on the IO thread. +// All member functions must be called on the UI thread. class FakeRecentSource : public RecentSource { public: FakeRecentSource();
diff --git a/chrome/browser/chromeos/first_run/first_run.cc b/chrome/browser/chromeos/first_run/first_run.cc index ea49346..9b211159 100644 --- a/chrome/browser/chromeos/first_run/first_run.cc +++ b/chrome/browser/chromeos/first_run/first_run.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/prefs/pref_service_syncable_util.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/ui/extensions/app_launch_params.h" #include "chrome/browser/ui/extensions/application_launch.h" #include "chrome/common/chrome_switches.h" @@ -25,6 +26,9 @@ #include "components/arc/arc_service_manager.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" +#include "components/signin/core/browser/account_info.h" +#include "components/signin/core/browser/account_tracker_service.h" +#include "components/signin/core/browser/signin_manager.h" #include "components/sync_preferences/pref_service_syncable.h" #include "components/user_manager/user_manager.h" #include "content/public/browser/notification_observer.h" @@ -109,9 +113,21 @@ DCHECK(content::Details<const user_manager::User>(details).ptr() == ProfileHelper::Get()->GetUserByProfile(profile_)); + // Whether the account is supported for voice interaction. + bool account_supported = false; + SigninManagerBase* signin_manager = + SigninManagerFactory::GetForProfile(profile_); + if (signin_manager) { + std::string hosted_domain = + signin_manager->GetAuthenticatedAccountInfo().hosted_domain; + if (hosted_domain == AccountTrackerService::kNoHostedDomainFound || + hosted_domain == "google.com") + account_supported = true; + } + // If voice interaction value prop needs to be shown, the tutorial will be // shown after the voice interaction OOBE flow. - if (arc::IsArcPlayStoreEnabledForProfile(profile_) && + if (account_supported && arc::IsArcPlayStoreEnabledForProfile(profile_) && !profile_->GetPrefs()->GetBoolean( prefs::kArcVoiceInteractionValuePropAccepted)) { auto* service =
diff --git a/chrome/browser/chromeos/power/cpu_data_collector.cc b/chrome/browser/chromeos/power/cpu_data_collector.cc index 8ed28c2..e9e21e1 100644 --- a/chrome/browser/chromeos/power/cpu_data_collector.cc +++ b/chrome/browser/chromeos/power/cpu_data_collector.cc
@@ -50,6 +50,11 @@ const char kCpuFreqTimeInStatePathSuffixFormat[] = "/cpu%d/cpufreq/stats/time_in_state"; +// Format of the suffix of the path to the folder which contains time in state +// file. If the folder does not exist, current platform does not produce +// discrete CPU frequency data. +const char kCpuFreqStatsPathSuffixFormat[] = "/cpu%d/cpufreq/stats"; + // The path to the file which contains cpu freq state information of a CPU // in 3.14.0 or newer kernels. const char kCpuFreqAllTimeInStatePath[] = @@ -235,12 +240,23 @@ return; } } else { + freq_samples->clear(); + const std::string cpu_freq_stats_path_format = base::StringPrintf( + "%s%s", kCpuDataPathBase, kCpuFreqStatsPathSuffixFormat); + const base::FilePath cpu_freq_stats_path( + base::StringPrintf(cpu_freq_stats_path_format.c_str(), cpu)); + if (!base::PathExists(cpu_freq_stats_path)) { + // If the path to 'stats' folder for a single CPU is missing, then + // current platform does not produce discrete CPU frequency data. + // This could happen when intel_pstate driver is used for cpufreq + // governor. Error message should not printed in this case. + return; + } // If the path to the 'time_in_state' for a single CPU is missing, // then 'time_in_state' for all CPUs is missing. This could happen // on a VM where the 'cpufreq_stats' kernel module is not loaded. LOG_IF(ERROR, base::SysInfo::IsRunningOnChromeOS()) << "CPU freq stats not available in sysfs."; - freq_samples->clear(); return; } }
diff --git a/chrome/browser/chromeos/power/peripheral_battery_observer.cc b/chrome/browser/chromeos/power/peripheral_battery_observer.cc index 6a254f6..2d447b81 100644 --- a/chrome/browser/chromeos/power/peripheral_battery_observer.cc +++ b/chrome/browser/chromeos/power/peripheral_battery_observer.cc
@@ -8,6 +8,7 @@ #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" +#include "ash/system/system_notifier.h" #include "base/bind.h" #include "base/macros.h" #include "base/strings/string16.h" @@ -26,7 +27,11 @@ #include "device/bluetooth/bluetooth_device.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/events/devices/input_device_manager.h" +#include "ui/events/devices/touchscreen_device.h" #include "ui/gfx/image/image.h" +#include "ui/message_center/message_center.h" +#include "ui/message_center/notification.h" namespace chromeos { @@ -40,6 +45,8 @@ // seconds. const int kNotificationIntervalSec = 60; +// TODO(sammiequon): Add a notification url to chrome://settings/stylus once +// battery related information is shown there. const char kNotificationOriginUrl[] = "chrome://peripheral-battery"; const char kNotifierId[] = "power.peripheral-battery"; @@ -72,6 +79,20 @@ return address; } +// Checks if the device is an external stylus. +bool IsStylusDevice(const std::string& bluetooth_address, + const std::string& model_name) { + for (const ui::TouchscreenDevice& device : + ui::InputDeviceManager::GetInstance()->GetTouchscreenDevices()) { + if (device.is_stylus && device.name == model_name && + ExtractBluetoothAddress(device.sys_path.value()) == bluetooth_address) { + return true; + } + } + + return false; +} + class PeripheralBatteryNotificationDelegate : public NotificationDelegate { public: explicit PeripheralBatteryNotificationDelegate(const std::string& id) @@ -90,6 +111,9 @@ } // namespace +const char PeripheralBatteryObserver::kStylusNotificationId[] = + "stylus-battery"; + PeripheralBatteryObserver::PeripheralBatteryObserver() : testing_clock_(NULL), notification_profile_(NULL), @@ -143,7 +167,7 @@ // below kLowBatteryLevel. // 2. The battery level is in record and it drops below kLowBatteryLevel. if (batteries_.find(address) == batteries_.end()) { - BatteryInfo battery(name, level, base::TimeTicks()); + BatteryInfo battery{name, level, base::TimeTicks()}; if (level <= kLowBatteryLevel) { if (PostNotification(address, battery)) battery.last_notification_timestamp = testing_clock_ ? @@ -203,6 +227,30 @@ base::TimeDelta::FromSeconds(kNotificationIntervalSec)) return false; + // Stylus battery notifications have a different icon and message. They are + // also system notifications. + // TODO(sammiequon): Change non-stylus notifications to also be system + // notifications. + if (IsStylusDevice(address, battery.name)) { + auto notification = base::MakeUnique<message_center::Notification>( + message_center::NOTIFICATION_TYPE_SIMPLE, kStylusNotificationId, + l10n_util::GetStringUTF16( + IDS_ASH_LOW_STYLUS_BATTERY_NOTIFICATION_TITLE), + l10n_util::GetStringUTF16(IDS_ASH_LOW_STYLUS_BATTERY_NOTIFICATION_BODY), + ui::ResourceBundle::GetSharedInstance().GetImageNamed( + IDR_NOTIFICATION_STYLUS_BATTERY_LOW), + base::string16(), GURL(), + message_center::NotifierId( + message_center::NotifierId::SYSTEM_COMPONENT, + ash::system_notifier::kNotifierStylusBattery), + message_center::RichNotificationData(), nullptr); + notification->SetSystemPriority(); + + message_center::MessageCenter::Get()->AddNotification( + std::move(notification)); + return true; + } + NotificationUIManager* notification_manager = g_browser_process->notification_ui_manager(); @@ -229,6 +277,13 @@ } void PeripheralBatteryObserver::CancelNotification(const std::string& address) { + const auto it = batteries_.find(address); + if (it != batteries_.end() && IsStylusDevice(address, it->second.name)) { + message_center::MessageCenter::Get()->RemoveNotification( + kStylusNotificationId, false /* by_user */); + return; + } + // If last_used_profile_ is NULL then no notification has been posted yet. if (notification_profile_) { g_browser_process->notification_ui_manager()->CancelById(
diff --git a/chrome/browser/chromeos/power/peripheral_battery_observer.h b/chrome/browser/chromeos/power/peripheral_battery_observer.h index d30aafd46..c3d43bc 100644 --- a/chrome/browser/chromeos/power/peripheral_battery_observer.h +++ b/chrome/browser/chromeos/power/peripheral_battery_observer.h
@@ -24,9 +24,12 @@ // This observer listens for peripheral device battery status and shows // notifications for low battery conditions. +// TODO(sammiequon): Investigate whether we can move this class to //ash. class PeripheralBatteryObserver : public PowerManagerClient::Observer, public device::BluetoothAdapter::Observer { public: + static const char kStylusNotificationId[]; + // This class registers/unregisters itself as an observer in ctor/dtor. PeripheralBatteryObserver(); ~PeripheralBatteryObserver() override; @@ -51,19 +54,10 @@ FRIEND_TEST_ALL_PREFIXES(PeripheralBatteryObserverTest, DeviceRemove); struct BatteryInfo { - BatteryInfo() : level(-1) {} - BatteryInfo(const std::string& name, - int level, - base::TimeTicks notification_timestamp) - : name(name), - level(level), - last_notification_timestamp(notification_timestamp) { - } - // Human readable name for the device. It is changeable. std::string name; // Battery level within range [0, 100], and -1 for unknown level. - int level; + int level = -1; base::TimeTicks last_notification_timestamp; };
diff --git a/chrome/browser/chromeos/power/peripheral_battery_observer_browsertest.cc b/chrome/browser/chromeos/power/peripheral_battery_observer_browsertest.cc index 92a53894..992e0fa 100644 --- a/chrome/browser/chromeos/power/peripheral_battery_observer_browsertest.cc +++ b/chrome/browser/chromeos/power/peripheral_battery_observer_browsertest.cc
@@ -16,6 +16,10 @@ #include "content/public/test/test_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/devices/touchscreen_device.h" +#include "ui/events/test/device_data_manager_test_api.h" +#include "ui/message_center/message_center.h" +#include "ui/message_center/notification.h" using ::testing::_; using ::testing::InSequence; @@ -90,6 +94,10 @@ NotificationUIManager::GetProfileID( ProfileManager::GetPrimaryUserProfile())) != NULL); + // Verify that the low-battery notification for stylus does not show up. + EXPECT_TRUE(message_center::MessageCenter::Get()->FindVisibleNotificationById( + PeripheralBatteryObserver::kStylusNotificationId) == nullptr); + // Level -1 at time 115, cancel previous notification clock.Advance(base::TimeDelta::FromSeconds(5)); observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, @@ -168,4 +176,45 @@ ProfileManager::GetPrimaryUserProfile())) != NULL); } +IN_PROC_BROWSER_TEST_F(PeripheralBatteryObserverTest, StylusNotification) { + const std::string kTestStylusName = "test_stylus"; + + // Add an external stylus to our test device manager. + ui::TouchscreenDevice stylus(0 /* id */, ui::INPUT_DEVICE_EXTERNAL, + kTestStylusName, gfx::Size(), + 1 /* touch_points */); + stylus.sys_path = base::FilePath(kTestBatteryPath); + stylus.is_stylus = true; + + ui::test::DeviceDataManagerTestAPI test_api; + test_api.SetTouchscreenDevices({stylus}); + + message_center::MessageCenter* message_center = + message_center::MessageCenter::Get(); + + // Verify that when the battery level is 50, no stylus low battery + // notification is shown. + observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, kTestStylusName, + 50); + EXPECT_TRUE(message_center->FindVisibleNotificationById( + PeripheralBatteryObserver::kStylusNotificationId) == nullptr); + + // Verify that when the battery level is 5, a stylus low battery notification + // is shown. Also check that a non stylus device low battery notification will + // not show up. + observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, kTestStylusName, + 5); + EXPECT_TRUE(message_center->FindVisibleNotificationById( + PeripheralBatteryObserver::kStylusNotificationId) != nullptr); + EXPECT_TRUE(message_center->FindVisibleNotificationById( + kTestBatteryAddress) == nullptr); + + // Verify that when the battery level is -1, the previous stylus low battery + // notification is cancelled. + observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, kTestStylusName, + -1); + EXPECT_TRUE(message_center->FindVisibleNotificationById( + PeripheralBatteryObserver::kStylusNotificationId) == nullptr); +} + } // namespace chromeos
diff --git a/chrome/browser/component_updater/cros_component_installer.cc b/chrome/browser/component_updater/cros_component_installer.cc index fc5319ac..5dab04f 100644 --- a/chrome/browser/component_updater/cros_component_installer.cc +++ b/chrome/browser/component_updater/cros_component_installer.cc
@@ -18,11 +18,19 @@ #include "chromeos/dbus/image_loader_client.h" #endif // defined(OS_CHROMEOS) -#define CONFIG_MAP_CONTENT \ - {{"epson-inkjet-printer-escpr", \ - {{"env_version", "2.1"}, \ - {"sha2hashstr", \ - "1913a5e0a6cad30b6f03e176177e0d7ed62c5d6700a9c66da556d7c3f5d6a47e"}}}}; +#define CONFIG_MAP_CONTENT \ + {{"epson-inkjet-printer-escpr", \ + {{"env_version", "2.1"}, \ + {"sha2hashstr", \ + "1913a5e0a6cad30b6f03e176177e0d7ed62c5d6700a9c66da556d7c3f5d6a47e"}}}, \ + {"cros-termina", \ + {{"env_version", "1.1"}, \ + {"sha2hashstr", \ + "e9d960f84f628e1f42d05de4046bb5b3154b6f1f65c08412c6af57a29aecaffb"}}}, \ + {"star-cups-driver", \ + {{"env_version", "1.1"}, \ + {"sha2hashstr", \ + "6d24de30f671da5aee6d463d9e446cafe9ddac672800a9defe86877dcde6c466"}}}}; using content::BrowserThread;
diff --git a/chrome/browser/component_updater/cros_component_installer.h b/chrome/browser/component_updater/cros_component_installer.h index ad07fbb8..9a580201 100644 --- a/chrome/browser/component_updater/cros_component_installer.h +++ b/chrome/browser/component_updater/cros_component_installer.h
@@ -95,7 +95,11 @@ private: FRIEND_TEST_ALL_PREFIXES(CrOSComponentInstallerTest, - RegisterComponentSuccess); + RegisterComponentSuccessEscpr); + FRIEND_TEST_ALL_PREFIXES(CrOSComponentInstallerTest, + RegisterComponentSuccessStarCupsDriver); + FRIEND_TEST_ALL_PREFIXES(CrOSComponentInstallerTest, + RegisterComponentSuccessTermina); FRIEND_TEST_ALL_PREFIXES(CrOSComponentInstallerTest, RegisterComponentFail); CrOSComponent() {} static void RegisterResult(ComponentUpdateService* cus,
diff --git a/chrome/browser/component_updater/cros_component_installer_unittest.cc b/chrome/browser/component_updater/cros_component_installer_unittest.cc index 20fbfdf..6766a22 100644 --- a/chrome/browser/component_updater/cros_component_installer_unittest.cc +++ b/chrome/browser/component_updater/cros_component_installer_unittest.cc
@@ -63,7 +63,7 @@ ASSERT_EQ(bppp.IsCompatibleCrOSComponent("a"), true); } -TEST_F(CrOSComponentInstallerTest, RegisterComponentSuccess) { +TEST_F(CrOSComponentInstallerTest, RegisterComponentSuccessEscpr) { CrOSMockComponentUpdateService cus; EXPECT_CALL(cus, RegisterComponent(testing::_)).Times(1); component_updater::CrOSComponent::InstallComponent( @@ -71,6 +71,22 @@ RunUntilIdle(); } +TEST_F(CrOSComponentInstallerTest, RegisterComponentSuccessStarCupsDriver) { + CrOSMockComponentUpdateService cus; + EXPECT_CALL(cus, RegisterComponent(testing::_)).Times(1); + component_updater::CrOSComponent::InstallComponent(&cus, "star-cups-driver", + base::Bind(load_callback)); + RunUntilIdle(); +} + +TEST_F(CrOSComponentInstallerTest, RegisterComponentSuccessTermina) { + CrOSMockComponentUpdateService cus; + EXPECT_CALL(cus, RegisterComponent(testing::_)).Times(1); + component_updater::CrOSComponent::InstallComponent(&cus, "cros-termina", + base::Bind(load_callback)); + RunUntilIdle(); +} + TEST_F(CrOSComponentInstallerTest, RegisterComponentFail) { CrOSMockComponentUpdateService cus; EXPECT_CALL(cus, RegisterComponent(testing::_)).Times(0);
diff --git a/chrome/browser/data_usage/tab_id_annotator.cc b/chrome/browser/data_usage/tab_id_annotator.cc index 2754dc74..b5eca9c 100644 --- a/chrome/browser/data_usage/tab_id_annotator.cc +++ b/chrome/browser/data_usage/tab_id_annotator.cc
@@ -76,7 +76,7 @@ DCHECK(data_use); TabIdProvider* existing_tab_id_provider = reinterpret_cast<TabIdProvider*>( - request->GetUserData(TabIdProvider::kUserDataKey)); + request->GetUserData(TabIdProvider::kTabIdProviderUserDataKey)); if (existing_tab_id_provider) { existing_tab_id_provider->ProvideTabId( base::Bind(&AnnotateDataUse, base::Passed(&data_use), callback)); @@ -112,7 +112,8 @@ tab_id_provider->ProvideTabId( base::Bind(&AnnotateDataUse, base::Passed(&data_use), callback)); - request->SetUserData(TabIdProvider::kUserDataKey, std::move(tab_id_provider)); + request->SetUserData(TabIdProvider::kTabIdProviderUserDataKey, + std::move(tab_id_provider)); } } // namespace chrome_browser_data_usage
diff --git a/chrome/browser/data_usage/tab_id_provider.cc b/chrome/browser/data_usage/tab_id_provider.cc index 247dccc8..b844b5a0 100644 --- a/chrome/browser/data_usage/tab_id_provider.cc +++ b/chrome/browser/data_usage/tab_id_provider.cc
@@ -120,7 +120,8 @@ } // static -const void* const TabIdProvider::kUserDataKey = &TabIdProvider::kUserDataKey; +const void* const TabIdProvider::kTabIdProviderUserDataKey = + &TabIdProvider::kTabIdProviderUserDataKey; void TabIdProvider::OnTabIdReady(URLRequestTabInfo tab_info) { DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/chrome/browser/data_usage/tab_id_provider.h b/chrome/browser/data_usage/tab_id_provider.h index f3acaac..f7da97f 100644 --- a/chrome/browser/data_usage/tab_id_provider.h +++ b/chrome/browser/data_usage/tab_id_provider.h
@@ -64,7 +64,7 @@ base::WeakPtr<TabIdProvider> GetWeakPtr(); - static const void* const kUserDataKey; + static const void* const kTabIdProviderUserDataKey; private: class CallbackRunner;
diff --git a/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc b/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc index 2bcaea4..d316dde 100644 --- a/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc +++ b/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc
@@ -9,6 +9,7 @@ #include <vector> #include "base/memory/ptr_util.h" +#include "build/build_config.h" #include "chrome/browser/data_use_measurement/chrome_data_use_recorder.h" #include "components/data_use_measurement/content/content_url_request_classifier.h" #include "components/data_use_measurement/core/data_use_recorder.h" @@ -24,10 +25,25 @@ namespace data_use_measurement { +namespace { + +bool IsDisabledPlatform() { +#if defined(OS_MACOSX) + // TODO(rajendrant): Fix mac os specific race conditions and enable. + // crbug.com/753559 + return true; +#else + return false; +#endif +} + +} // namespace + // static -const void* const - ChromeDataUseAscriber::DataUseRecorderEntryAsUserData::kUserDataKey = - &ChromeDataUseAscriber::DataUseRecorderEntryAsUserData::kUserDataKey; +const void* const ChromeDataUseAscriber::DataUseRecorderEntryAsUserData:: + kDataUseAscriberUserDataKey = + &ChromeDataUseAscriber::DataUseRecorderEntryAsUserData:: + kDataUseAscriberUserDataKey; ChromeDataUseAscriber::DataUseRecorderEntryAsUserData:: DataUseRecorderEntryAsUserData(DataUseRecorderEntry entry) @@ -67,8 +83,9 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); // If a DataUseRecorder has already been set as user data, then return that. - auto* user_data = static_cast<DataUseRecorderEntryAsUserData*>( - request.GetUserData(DataUseRecorderEntryAsUserData::kUserDataKey)); + auto* user_data = + static_cast<DataUseRecorderEntryAsUserData*>(request.GetUserData( + DataUseRecorderEntryAsUserData::kDataUseAscriberUserDataKey)); return user_data ? &(*user_data->recorder_entry()) : nullptr; } @@ -78,8 +95,9 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); // If a DataUseRecorder has already been set as user data, then return that. - auto* user_data = static_cast<DataUseRecorderEntryAsUserData*>( - request->GetUserData(DataUseRecorderEntryAsUserData::kUserDataKey)); + auto* user_data = + static_cast<DataUseRecorderEntryAsUserData*>(request->GetUserData( + DataUseRecorderEntryAsUserData::kDataUseAscriberUserDataKey)); if (user_data) return user_data->recorder_entry(); @@ -168,6 +186,9 @@ bool started) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (IsDisabledPlatform()) + return; + ChromeDataUseRecorder* recorder = GetDataUseRecorder(request); if (!recorder) @@ -193,6 +214,9 @@ void ChromeDataUseAscriber::OnUrlRequestDestroyed(net::URLRequest* request) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (IsDisabledPlatform()) + return; + // TODO(rajendrant): GetDataUseRecorder is sufficient and // GetOrCreateDataUseRecorderEntry is not needed. The entry gets created in // DataUseAscriber::OnBeforeUrlRequest(). @@ -242,6 +266,9 @@ int main_render_process_id, int main_render_frame_id) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (IsDisabledPlatform()) + return; + const auto render_frame = RenderFrameHostID(render_process_id, render_frame_id); @@ -270,6 +297,8 @@ int main_render_process_id, int main_render_frame_id) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (IsDisabledPlatform()) + return; RenderFrameHostID key(render_process_id, render_frame_id); @@ -301,6 +330,9 @@ int render_process_id, int render_frame_id) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (IsDisabledPlatform()) + return; + main_render_frame_entry_map_ .find(RenderFrameHostID(render_process_id, render_frame_id)) ->second.pending_navigation_global_request_id = global_request_id; @@ -315,6 +347,9 @@ base::TimeTicks time) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (IsDisabledPlatform()) + return; + RenderFrameHostID main_frame(render_process_id, render_frame_id); auto main_frame_it = main_render_frame_entry_map_.find(main_frame); @@ -457,8 +492,9 @@ net::URLRequest* request, DataUseRecorderEntry entry) { entry->AddPendingURLRequest(request); - request->SetUserData(DataUseRecorderEntryAsUserData::kUserDataKey, - base::MakeUnique<DataUseRecorderEntryAsUserData>(entry)); + request->SetUserData( + DataUseRecorderEntryAsUserData::kDataUseAscriberUserDataKey, + base::MakeUnique<DataUseRecorderEntryAsUserData>(entry)); } void ChromeDataUseAscriber::WasShownOrHidden(int main_render_process_id, @@ -466,6 +502,9 @@ bool visible) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (IsDisabledPlatform()) + return; + auto main_frame_it = main_render_frame_entry_map_.find( RenderFrameHostID(main_render_process_id, main_render_frame_id)); if (main_frame_it != main_render_frame_entry_map_.end()) { @@ -481,6 +520,9 @@ int new_render_frame_id) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (IsDisabledPlatform()) + return; + auto old_frame_iter = main_render_frame_entry_map_.find( RenderFrameHostID(old_render_process_id, old_render_frame_id));
diff --git a/chrome/browser/data_use_measurement/chrome_data_use_ascriber.h b/chrome/browser/data_use_measurement/chrome_data_use_ascriber.h index 8023ed3c..eb9acad 100644 --- a/chrome/browser/data_use_measurement/chrome_data_use_ascriber.h +++ b/chrome/browser/data_use_measurement/chrome_data_use_ascriber.h
@@ -129,7 +129,7 @@ DataUseRecorderEntry recorder_entry() { return entry_; } - static const void* const kUserDataKey; + static const void* const kDataUseAscriberUserDataKey; private: DataUseRecorderEntry entry_;
diff --git a/chrome/browser/data_use_measurement/chrome_data_use_ascriber_unittest.cc b/chrome/browser/data_use_measurement/chrome_data_use_ascriber_unittest.cc index 0c52675..290b5a5 100644 --- a/chrome/browser/data_use_measurement/chrome_data_use_ascriber_unittest.cc +++ b/chrome/browser/data_use_measurement/chrome_data_use_ascriber_unittest.cc
@@ -9,6 +9,7 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "build/build_config.h" #include "components/data_use_measurement/core/data_use_recorder.h" #include "content/public/browser/resource_request_info.h" #include "content/public/common/browser_side_navigation_policy.h" @@ -21,6 +22,8 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#ifndef OS_MACOSX + namespace { int kRenderProcessId = 1; @@ -457,3 +460,5 @@ } } // namespace data_use_measurement + +#endif // OS_MACOSX
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc b/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc index 09a5063..534533b 100644 --- a/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc +++ b/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc
@@ -270,7 +270,7 @@ } #endif // defined(OS_CHROMEOS) -bool FeedbackPrivateSendFeedbackFunction::RunAsync() { +ExtensionFunction::ResponseAction FeedbackPrivateSendFeedbackFunction::Run() { std::unique_ptr<feedback_private::SendFeedback::Params> params( feedback_private::SendFeedback::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params); @@ -332,15 +332,14 @@ browser_context(), feedback_data, base::Bind(&FeedbackPrivateSendFeedbackFunction::OnCompleted, this)); - return true; + return RespondLater(); } void FeedbackPrivateSendFeedbackFunction::OnCompleted( bool success) { - results_ = feedback_private::SendFeedback::Results::Create( - success ? feedback_private::STATUS_SUCCESS : - feedback_private::STATUS_DELAYED); - SendResponse(true); + Respond(OneArgument(base::MakeUnique<base::Value>( + feedback_private::ToString(success ? feedback_private::STATUS_SUCCESS + : feedback_private::STATUS_DELAYED)))); if (!success) { // Sending the feedback has been delayed as the user is offline. Show a
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_private_api.h b/chrome/browser/extensions/api/feedback_private/feedback_private_api.h index ef781bd..58c6f5f6 100644 --- a/chrome/browser/extensions/api/feedback_private/feedback_private_api.h +++ b/chrome/browser/extensions/api/feedback_private/feedback_private_api.h
@@ -7,7 +7,6 @@ #include <memory> -#include "chrome/browser/extensions/chrome_extension_function.h" #include "chrome/common/extensions/api/feedback_private.h" #include "components/feedback/system_logs/system_logs_source.h" #include "extensions/browser/browser_context_keyed_api_factory.h" @@ -129,15 +128,14 @@ #endif // defined(OS_CHROMEOS) }; -class FeedbackPrivateSendFeedbackFunction - : public ChromeAsyncExtensionFunction { +class FeedbackPrivateSendFeedbackFunction : public UIThreadExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("feedbackPrivate.sendFeedback", FEEDBACKPRIVATE_SENDFEEDBACK); protected: ~FeedbackPrivateSendFeedbackFunction() override {} - bool RunAsync() override; + ResponseAction Run() override; private: void OnCompleted(bool success);
diff --git a/chrome/browser/extensions/api/notifications/notifications_api.cc b/chrome/browser/extensions/api/notifications/notifications_api.cc index da49e6a0..4e3a9bf 100644 --- a/chrome/browser/extensions/api/notifications/notifications_api.cc +++ b/chrome/browser/extensions/api/notifications/notifications_api.cc
@@ -569,6 +569,11 @@ SetResult(base::MakeUnique<base::Value>(notification_id)); + // TODO(crbug.com/749402): Cap the length of notification Ids to a certain + // limit if the histogram indicates that this is safe to do. + UMA_HISTOGRAM_COUNTS_1000("Notifications.ExtensionNotificationIdLength", + notification_id.size()); + // TODO(dewittj): Add more human-readable error strings if this fails. if (!CreateNotification(notification_id, ¶ms_->options)) return false;
diff --git a/chrome/browser/extensions/bookmark_app_url_redirector_browsertest.cc b/chrome/browser/extensions/bookmark_app_url_redirector_browsertest.cc index ac53115..c138d9c 100644 --- a/chrome/browser/extensions/bookmark_app_url_redirector_browsertest.cc +++ b/chrome/browser/extensions/bookmark_app_url_redirector_browsertest.cc
@@ -7,11 +7,15 @@ #include "base/test/scoped_feature_list.h" #include "chrome/browser/extensions/bookmark_app_helper.h" #include "chrome/browser/extensions/extension_browsertest.h" +#include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/extensions/app_launch_params.h" +#include "chrome/browser/ui/extensions/application_launch.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_features.h" #include "chrome/common/web_application_info.h" #include "chrome/test/base/ui_test_utils.h" +#include "content/public/browser/notification_details.h" #include "content/public/browser/notification_service.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_utils.h" @@ -77,13 +81,20 @@ ASSERT_EQ(++num_extensions, ExtensionRegistry::Get(profile())->enabled_extensions().size()); + + test_bookmark_app_ = + content::Details<const Extension>(windowed_observer.details()).ptr(); } Browser* OpenTestBookmarkApp() { GURL app_url = embedded_test_server()->GetURL(kAppUrlPath); ui_test_utils::UrlLoadObserver url_observer( app_url, content::NotificationService::AllSources()); - ui_test_utils::NavigateToURL(browser(), app_url); + + OpenApplication(AppLaunchParams( + profile(), test_bookmark_app_, extensions::LAUNCH_CONTAINER_WINDOW, + WindowOpenDisposition::CURRENT_TAB, SOURCE_CHROME_INTERNAL)); + url_observer.Wait(); return chrome::FindLastActive(); @@ -123,6 +134,7 @@ void ResetFeatureList() { scoped_feature_list_.reset(); } private: + const Extension* test_bookmark_app_; std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_; }; @@ -172,6 +184,58 @@ initial_tab->GetLastCommittedURL()); } +// Tests that navigating to a in-scope URL using the omnibox *does not* +// open the Bookmark App. +IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest, + OmniboxNavigationInScope) { + InstallTestBookmarkApp(); + + content::WebContents* initial_tab = + browser()->tab_strip_model()->GetActiveWebContents(); + int num_tabs = browser()->tab_strip_model()->count(); + size_t num_browsers = chrome::GetBrowserCount(profile()); + + GURL in_scope_url = embedded_test_server()->GetURL(kInScopeUrlPath); + ui_test_utils::UrlLoadObserver url_observer( + in_scope_url, content::NotificationService::AllSources()); + chrome::NavigateParams params(browser(), in_scope_url, + ui::PAGE_TRANSITION_TYPED); + ui_test_utils::NavigateToURL(¶ms); + url_observer.Wait(); + + EXPECT_EQ(num_tabs, browser()->tab_strip_model()->count()); + EXPECT_EQ(num_browsers, chrome::GetBrowserCount(profile())); + EXPECT_EQ(browser(), chrome::FindLastActive()); + + EXPECT_EQ(in_scope_url, initial_tab->GetLastCommittedURL()); +} + +// Tests that navigating to an out-of-scope URL with the same origin as the +// installed Bookmark App *does not* open the Bookmark App. +IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest, + OmniboxNavigationOutOfScope) { + InstallTestBookmarkApp(); + + content::WebContents* initial_tab = + browser()->tab_strip_model()->GetActiveWebContents(); + int num_tabs = browser()->tab_strip_model()->count(); + size_t num_browsers = chrome::GetBrowserCount(profile()); + + GURL out_of_scope_url = embedded_test_server()->GetURL(kOutOfScopeUrlPath); + ui_test_utils::UrlLoadObserver url_observer( + out_of_scope_url, content::NotificationService::AllSources()); + chrome::NavigateParams params(browser(), out_of_scope_url, + ui::PAGE_TRANSITION_TYPED); + ui_test_utils::NavigateToURL(¶ms); + url_observer.Wait(); + + EXPECT_EQ(num_tabs, browser()->tab_strip_model()->count()); + EXPECT_EQ(num_browsers, chrome::GetBrowserCount(profile())); + EXPECT_EQ(browser(), chrome::FindLastActive()); + + EXPECT_EQ(out_of_scope_url, initial_tab->GetLastCommittedURL()); +} + // Tests that clicking a link with target="_self" to the apps app_url opens the // Bookmark App. IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest, AppUrl) {
diff --git a/chrome/browser/feature_engagement/DEPS b/chrome/browser/feature_engagement/DEPS index fe5dacf0..798c9a85 100644 --- a/chrome/browser/feature_engagement/DEPS +++ b/chrome/browser/feature_engagement/DEPS
@@ -1,4 +1,11 @@ include_rules = [ + "+chrome/browser/ui/views/tabs/new_tab_button.h", "+components/feature_engagement", "+components/keyed_service", ] + +specific_include_rules = { + ".*test.*": [ + "+chrome/browser/ui/views", + ], +}
diff --git a/chrome/browser/feature_engagement/new_tab/new_tab_tracker.cc b/chrome/browser/feature_engagement/new_tab/new_tab_tracker.cc index c3d52b7c..e735dde 100644 --- a/chrome/browser/feature_engagement/new_tab/new_tab_tracker.cc +++ b/chrome/browser/feature_engagement/new_tab/new_tab_tracker.cc
@@ -4,10 +4,12 @@ #include "chrome/browser/feature_engagement/new_tab/new_tab_tracker.h" +#include "base/feature_list.h" #include "base/time/time.h" #include "chrome/browser/feature_engagement/tracker_factory.h" #include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/views/tabs/new_tab_button.h" #include "chrome/common/pref_names.h" #include "components/feature_engagement/public/event_constants.h" #include "components/feature_engagement/public/feature_constants.h" @@ -38,10 +40,6 @@ registry->RegisterIntegerPref(prefs::kSessionTimeTotal, 0); } -void NewTabTracker::DismissNewTabTracker() { - GetFeatureTracker()->Dismissed(kIPHNewTabFeature); -} - void NewTabTracker::OnNewTabOpened() { GetFeatureTracker()->NotifyEvent(events::kNewTabOpened); } @@ -59,6 +57,10 @@ ShowPromo(); } +void NewTabTracker::OnPromoClosed() { + GetFeatureTracker()->Dismissed(kIPHNewTabFeature); +} + bool NewTabTracker::ShouldShowPromo() { return GetFeatureTracker()->ShouldTriggerHelpUI(kIPHNewTabFeature); } @@ -77,10 +79,7 @@ } void NewTabTracker::ShowPromo() { - // TODO(crbug.com/737830): Call the promo. - - // Clears the flag for whether there is any in-product help being displayed. - GetFeatureTracker()->Dismissed(kIPHNewTabFeature); + NewTabButton::ShowPromoForLastActiveBrowser(); } Tracker* NewTabTracker::GetFeatureTracker() {
diff --git a/chrome/browser/feature_engagement/new_tab/new_tab_tracker.h b/chrome/browser/feature_engagement/new_tab/new_tab_tracker.h index 8bba7b5..5cb02f8 100644 --- a/chrome/browser/feature_engagement/new_tab/new_tab_tracker.h +++ b/chrome/browser/feature_engagement/new_tab/new_tab_tracker.h
@@ -26,8 +26,6 @@ static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); - // Clears the flag for whether there is any in-product help being displayed. - void DismissNewTabTracker(); // Alerts the new tab tracker that a new tab was opened. void OnNewTabOpened(); // Alerts the new tab tracker that the omnibox has been used. @@ -36,6 +34,8 @@ void OnSessionTimeMet(); // Checks if the promo should be displayed since the omnibox is on focus. void OnOmniboxFocused(); + // Clears the flag for whether there is any in-product help being displayed. + void OnPromoClosed(); // Returns whether or not the promo should be displayed. bool ShouldShowPromo(); @@ -53,9 +53,6 @@ // more than two hours. bool HasEnoughSessionTimeElapsed(); - // Returns whether the NewTabInProductHelp field trial is enabled. - bool IsIPHNewTabEnabled(); - // Sets the NewTabInProductHelp pref to true and calls the New Tab Promo. void ShowPromo(); @@ -66,7 +63,7 @@ // Updates the pref that stores active session time per user unless the // new tab in-product help has been displayed already. - virtual void UpdateSessionTime(base::TimeDelta elapsed); + void UpdateSessionTime(base::TimeDelta elapsed); // metrics::DesktopSessionDurationTracker::Observer:: void OnSessionEnded(base::TimeDelta delta) override;
diff --git a/chrome/browser/feature_engagement/new_tab/new_tab_tracker_browsertest.cc b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_browsertest.cc new file mode 100644 index 0000000..9c638fb --- /dev/null +++ b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_browsertest.cc
@@ -0,0 +1,135 @@ +// 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 "chrome/browser/feature_engagement/new_tab/new_tab_tracker.h" + +#include "base/run_loop.h" +#include "chrome/browser/feature_engagement/new_tab/new_tab_tracker_factory.h" +#include "chrome/browser/feature_engagement/tracker_factory.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/views/feature_promos/new_tab_promo_bubble_view.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/location_bar/location_bar_view.h" +#include "chrome/browser/ui/views/tabs/new_tab_button.h" +#include "chrome/browser/ui/views/tabs/tab_strip.h" +#include "chrome/grit/generated_resources.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/interactive_test_utils.h" +#include "components/feature_engagement/public/event_constants.h" +#include "components/feature_engagement/public/feature_constants.h" +#include "components/feature_engagement/public/tracker.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" +#include "components/keyed_service/core/keyed_service.h" +#include "components/omnibox/browser/omnibox_edit_model.h" +#include "components/omnibox/browser/omnibox_view.h" +#include "components/sync_preferences/testing_pref_service_syncable.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/views/widget/widget.h" +#include "url/gurl.h" + +namespace feature_engagement { + +namespace { + +MATCHER_P(IsFeature, feature, "") { + return arg.name == feature.name; +} + +class MockTracker : public Tracker { + public: + MockTracker() = default; + MOCK_METHOD1(NotifyEvent, void(const std::string& event)); + TriggerState GetTriggerState(const base::Feature& feature) override { + return Tracker::TriggerState::HAS_NOT_BEEN_DISPLAYED; + } + MOCK_METHOD1(ShouldTriggerHelpUI, bool(const base::Feature& feature)); + MOCK_METHOD1(Dismissed, void(const base::Feature& feature)); + MOCK_METHOD0(IsInitialized, bool()); + void AddOnInitializedCallback(OnInitializedCallback callback) override {} +}; + +std::unique_ptr<KeyedService> BuildTestTrackerFactory( + content::BrowserContext* context) { + return base::MakeUnique<testing::StrictMock<MockTracker>>(); +} + +class NewTabTrackerBrowserTest : public InProcessBrowserTest { + public: + NewTabTrackerBrowserTest() = default; + ~NewTabTrackerBrowserTest() override = default; + + void SetUpOnMainThread() override { + TrackerFactory::GetInstance()->SetTestingFactoryAndUse( + browser()->profile(), &BuildTestTrackerFactory); + + // Ensure all initialization is finished. + base::RunLoop().RunUntilIdle(); + + feature_engagement_tracker_ = static_cast<MockTracker*>( + TrackerFactory::GetForBrowserContext(browser()->profile())); + + EXPECT_CALL(*feature_engagement_tracker_, IsInitialized()) + .WillOnce(::testing::Return(true)); + + ASSERT_TRUE(TrackerFactory::GetForBrowserContext(browser()->profile()) + ->IsInitialized()); + } + + GURL GetGoogleURL() { return GURL("http://www.google.com/"); } + + protected: + // Owned by the Profile. + MockTracker* feature_engagement_tracker_; +}; + +} // namespace + +IN_PROC_BROWSER_TEST_F(NewTabTrackerBrowserTest, TestShowPromo) { + // Bypassing the 2 hour active session time requirement. + EXPECT_CALL(*feature_engagement_tracker_, NotifyEvent(events::kSessionTime)); + NewTabTrackerFactory::GetInstance() + ->GetForProfile(browser()->profile()) + ->OnSessionTimeMet(); + + // Navigate in the omnibox. + EXPECT_CALL(*feature_engagement_tracker_, + NotifyEvent(events::kOmniboxInteraction)); + ui_test_utils::NavigateToURL(browser(), GetGoogleURL()); + OmniboxView* omnibox_view = + browser()->window()->GetLocationBar()->GetOmniboxView(); + omnibox_view->OnBeforePossibleChange(); + omnibox_view->SetUserText(base::ASCIIToUTF16("http://www.chromium.org/")); + omnibox_view->OnAfterPossibleChange(true); + omnibox_view->model()->AcceptInput(WindowOpenDisposition::CURRENT_TAB, false); + + // Focus on the omnibox. + EXPECT_CALL(*feature_engagement_tracker_, + ShouldTriggerHelpUI(IsFeature(kIPHNewTabFeature))) + .WillOnce(::testing::Return(true)) + .WillRepeatedly(::testing::Return(false)); + chrome::FocusLocationBar(browser()); + + EXPECT_TRUE(BrowserView::GetBrowserViewForBrowser(browser()) + ->tabstrip() + ->new_tab_button() + ->new_tab_promo() + ->GetWidget() + ->IsVisible()); + + // Tracker::Dismissed() must be invoked when the promo is closed. This will + // clear the flag for whether there is any in-product help being displayed. + EXPECT_CALL(*feature_engagement_tracker_, + Dismissed(IsFeature(kIPHNewTabFeature))); + + BrowserView::GetBrowserViewForBrowser(browser()) + ->tabstrip() + ->new_tab_button() + ->new_tab_promo() + ->GetWidget() + ->Close(); +} + +} // namespace feature_engagement
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 28578c3..8588062d 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -2392,6 +2392,11 @@ const char kWebVrAutopresentDescription[] = "Allows auto presentation of WebVr content from trusted first-party apps"; +const char kWebVrVsyncAlignName[] = "Enable WebVR VSync-aligned timing"; +const char kWebVrVsyncAlignDescription[] = + "Enabling this option aligns WebVR application rendering with VSync " + "for smoother animations."; + #endif // defined(OS_ANDROID) const char kWebvrExperimentalRenderingName[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 5370c7f..7e86e338 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1535,6 +1535,9 @@ extern const char kWebVrAutopresentName[]; extern const char kWebVrAutopresentDescription[]; +extern const char kWebVrVsyncAlignName[]; +extern const char kWebVrVsyncAlignDescription[]; + #endif // OS_ANDROID extern const char kWebvrExperimentalRenderingName[];
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc index 7817d3f0..39d0f76 100644 --- a/chrome/browser/media/encrypted_media_browsertest.cc +++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -753,11 +753,14 @@ // When CDM crashes, we should still get a decode error and all sessions should // be closed. IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, CDMCrashDuringDecode) { - // TODO(xhwang): Handle mojo CDM crash correctly. See http://crbug.com/730766 +// TODO(xhwang): This test times out when using mojo CDM, possibly due to the +// crash pop-up dialog. See http://crbug.com/730766 +#if defined(OS_WIN) if (IsUsingMojoCdm()) { DVLOG(0) << "Skipping test; Not working with mojo CDM yet."; return; } +#endif // defined(OS_WIN) IgnorePluginCrash(); TestNonPlaybackCases(kExternalClearKeyCrashKeySystem, @@ -766,9 +769,9 @@ // Testing that the media browser test does fail on CDM crash. IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, CDMExpectedCrash) { - // TODO(xhwang): Handle mojo CDM crash correctly. See http://crbug.com/730766 + // PluginCrashed() is only called when the CDM is running as a plugin. if (IsUsingMojoCdm()) { - DVLOG(0) << "Skipping test; Not working with mojo CDM yet."; + DVLOG(0) << "Skipping test; Pepper CDM specific."; return; }
diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.cc b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.cc index 7e9ca2d..37402d6f 100644 --- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.cc +++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.cc
@@ -40,6 +40,11 @@ MediaSinkServiceBase::StopTimer(); } +void CastMediaSinkServiceImpl::RecordDeviceCounts() { + metrics_.RecordDeviceCountsIfNeeded(current_sinks_.size(), + current_service_ip_endpoints_.size()); +} + void CastMediaSinkServiceImpl::OpenChannels( std::vector<MediaSinkInternal> cast_sinks) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h index 95e883a..7b905e337 100644 --- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h +++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h
@@ -11,6 +11,7 @@ #include "base/gtest_prod_util.h" #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" +#include "chrome/browser/media/router/discovery/media_sink_discovery_metrics.h" #include "chrome/browser/media/router/discovery/media_sink_service_base.h" #include "components/cast_channel/cast_channel_enum.h" #include "components/cast_channel/cast_socket.h" @@ -40,6 +41,9 @@ void Start() override; void Stop() override; + // MediaSinkServiceBase implementation + void RecordDeviceCounts() override; + // Opens cast channels on the IO thread. virtual void OpenChannels(std::vector<MediaSinkInternal> cast_sinks); @@ -79,6 +83,8 @@ // removing Cast channels. cast_channel::CastSocketService* const cast_socket_service_; + CastDeviceCountMetrics metrics_; + SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(CastMediaSinkServiceImpl);
diff --git a/chrome/browser/metrics/chromeos_metrics_provider.cc b/chrome/browser/metrics/chromeos_metrics_provider.cc index 09aaaba8..67206d9 100644 --- a/chrome/browser/metrics/chromeos_metrics_provider.cc +++ b/chrome/browser/metrics/chromeos_metrics_provider.cc
@@ -103,6 +103,15 @@ pref->SetInteger(path, value + 1); } +// Called on a background thread to load hardware class information. +std::string GetHardwareClassOnBackgroundThread() { + base::ThreadRestrictions::AssertWaitAllowed(); + std::string hardware_class; + chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic( + "hardware_class", &hardware_class); + return hardware_class; +} + } // namespace ChromeOSMetricsProvider::ChromeOSMetricsProvider() @@ -178,21 +187,14 @@ const base::Closure& callback) { // Run the (potentially expensive) task in the background to avoid blocking // the UI thread. - base::PostTaskWithTraitsAndReply( + base::PostTaskWithTraitsAndReplyWithResult( FROM_HERE, {base::MayBlock(), base::WithBaseSyncPrimitives(), base::TaskPriority::BACKGROUND, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, - base::BindOnce( - &ChromeOSMetricsProvider::InitTaskGetHardwareClassOnBackgroundThread, - weak_ptr_factory_.GetWeakPtr()), - callback); -} - -void ChromeOSMetricsProvider::InitTaskGetHardwareClassOnBackgroundThread() { - base::ThreadRestrictions::AssertWaitAllowed(); - chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic( - "hardware_class", &hardware_class_); + base::BindOnce(&GetHardwareClassOnBackgroundThread), + base::BindOnce(&ChromeOSMetricsProvider::SetHardwareClass, + weak_ptr_factory_.GetWeakPtr(), callback)); } void ChromeOSMetricsProvider::InitTaskGetBluetoothAdapter( @@ -349,6 +351,12 @@ callback.Run(); } +void ChromeOSMetricsProvider::SetHardwareClass(base::Closure callback, + std::string hardware_class) { + hardware_class_ = hardware_class; + callback.Run(); +} + void ChromeOSMetricsProvider::RecordEnrollmentStatus() { UMA_HISTOGRAM_ENUMERATION( "UMA.EnrollmentStatus", GetEnrollmentStatus(), ENROLLMENT_STATUS_MAX);
diff --git a/chrome/browser/metrics/chromeos_metrics_provider.h b/chrome/browser/metrics/chromeos_metrics_provider.h index c61fc48..a1dce11 100644 --- a/chrome/browser/metrics/chromeos_metrics_provider.h +++ b/chrome/browser/metrics/chromeos_metrics_provider.h
@@ -69,9 +69,6 @@ metrics::ChromeUserMetricsExtension* uma_proto) override; private: - // Called on a background thread to load hardware class information. - void InitTaskGetHardwareClassOnBackgroundThread(); - // Update the number of users logged into a multi-profile session. // If the number of users change while the log is open, the call invalidates // the user count value. @@ -83,6 +80,9 @@ void SetBluetoothAdapter(base::Closure callback, scoped_refptr<device::BluetoothAdapter> adapter); + // Sets the hardware class, then calls the callback. + void SetHardwareClass(base::Closure callback, std::string hardware_class); + // Writes info about paired Bluetooth devices on this system. void WriteBluetoothProto(metrics::SystemProfileProto* system_profile_proto);
diff --git a/chrome/browser/offline_pages/background_loader_offliner.cc b/chrome/browser/offline_pages/background_loader_offliner.cc index 2c11a3ea..223f6f8 100644 --- a/chrome/browser/offline_pages/background_loader_offliner.cc +++ b/chrome/browser/offline_pages/background_loader_offliner.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/offline_pages/background_loader_offliner.h" +#include <utility> + #include "base/bind.h" #include "base/json/json_writer.h" #include "base/metrics/histogram_functions.h" @@ -16,12 +18,16 @@ #include "chrome/browser/offline_pages/offliner_helper.h" #include "chrome/browser/offline_pages/offliner_user_data.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/common/chrome_isolated_world_ids.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h" +#include "components/offline_pages/content/renovations/render_frame_script_injector.h" #include "components/offline_pages/core/background/offliner_policy.h" #include "components/offline_pages/core/background/save_page_request.h" #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/offline_page_model.h" +#include "components/offline_pages/core/renovations/page_renovation_loader.h" +#include "components/offline_pages/core/renovations/page_renovator.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/mhtml_extra_parts.h" #include "content/public/browser/navigation_handle.h" @@ -205,11 +211,25 @@ completion_callback_ = completion_callback; progress_callback_ = progress_callback; + if (IsOfflinePagesRenovationsEnabled()) { + // Lazily create PageRenovationLoader + if (!page_renovation_loader_) + page_renovation_loader_ = base::MakeUnique<PageRenovationLoader>(); + + // Set up PageRenovator for this offlining instance. + auto script_injector = base::MakeUnique<RenderFrameScriptInjector>( + loader_->web_contents()->GetMainFrame(), + chrome::ISOLATED_WORLD_ID_CHROME_INTERNAL); + page_renovator_ = base::MakeUnique<PageRenovator>( + page_renovation_loader_.get(), std::move(script_injector), + request.url()); + } + // Load page attempt. loader_.get()->LoadPage(request.url()); snapshot_controller_ = SnapshotController::CreateForBackgroundOfflining( - base::ThreadTaskRunnerHandle::Get(), this, false); + base::ThreadTaskRunnerHandle::Get(), this, (bool)page_renovator_); return true; } @@ -470,8 +490,11 @@ } void BackgroundLoaderOffliner::RunRenovations() { - // TODO(collinbaker): run renovations from here. - snapshot_controller_->RenovationsCompleted(); + if (page_renovator_) { + page_renovator_->RunRenovations( + base::Bind(&BackgroundLoaderOffliner::RenovationsCompleted, + weak_ptr_factory_.GetWeakPtr())); + } } void BackgroundLoaderOffliner::OnPageSaved(SavePageResult save_result, @@ -563,4 +586,8 @@ signal_data_.SetDouble(signal_name, delay); } +void BackgroundLoaderOffliner::RenovationsCompleted() { + snapshot_controller_->RenovationsCompleted(); +} + } // namespace offline_pages
diff --git a/chrome/browser/offline_pages/background_loader_offliner.h b/chrome/browser/offline_pages/background_loader_offliner.h index cf50bc11..e9942e8 100644 --- a/chrome/browser/offline_pages/background_loader_offliner.h +++ b/chrome/browser/offline_pages/background_loader_offliner.h
@@ -26,6 +26,9 @@ class OfflinerPolicy; class OfflinePageModel; +class PageRenovationLoader; +class PageRenovator; + struct RequestStats { int requested; int completed; @@ -105,6 +108,9 @@ // Called to add a loading signal as we observe it. void AddLoadingSignal(const char* signal_name); + // Called by PageRenovator callback when renovations complete. + void RenovationsCompleted(); + void DeleteOfflinePageCallback(const SavePageRequest& request, DeletePageResult result); @@ -132,6 +138,11 @@ // Whether we are on a low-end device. bool is_low_end_device_; + // PageRenovationLoader must live longer than the PageRenovator. + std::unique_ptr<PageRenovationLoader> page_renovation_loader_; + // Per-offliner PageRenovator instance. + std::unique_ptr<PageRenovator> page_renovator_; + // Save state. SaveState save_state_; // Page load state.
diff --git a/chrome/browser/offline_pages/prefetch/prefetch_importer_impl.cc b/chrome/browser/offline_pages/prefetch/prefetch_importer_impl.cc index 3e84c67..e30909b 100644 --- a/chrome/browser/offline_pages/prefetch/prefetch_importer_impl.cc +++ b/chrome/browser/offline_pages/prefetch/prefetch_importer_impl.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/offline_pages/offline_page_model_factory.h" #include "chrome/common/chrome_constants.h" #include "components/offline_pages/core/offline_page_model.h" +#include "components/offline_pages/core/prefetch/prefetch_item.h" #include "content/public/browser/browser_context.h" #include "url/gurl.h" @@ -34,22 +35,17 @@ } // namespace PrefetchImporterImpl::PrefetchImporterImpl( + PrefetchDispatcher* dispatcher, content::BrowserContext* context, scoped_refptr<base::TaskRunner> background_task_runner) - : context_(context), + : PrefetchImporter(dispatcher), + context_(context), background_task_runner_(background_task_runner), weak_ptr_factory_(this) {} PrefetchImporterImpl::~PrefetchImporterImpl() = default; -void PrefetchImporterImpl::ImportFile(const GURL& url, - const GURL& original_url, - const base::string16& title, - int64_t offline_id, - const ClientId& client_id, - const base::FilePath& file_path, - int64_t file_size, - const CompletedCallback& callback) { +void PrefetchImporterImpl::ImportArchive(const PrefetchArchiveInfo& archive) { // The target file name will be auto generated based on GUID to prevent any // name collision. base::FilePath archives_dir = @@ -57,27 +53,33 @@ base::FilePath dest_path = archives_dir.Append(base::GenerateGUID()).AddExtension(kMHTMLExtension); - OfflinePageItem offline_page(url, offline_id, client_id, dest_path, file_size, - base::Time::Now()); + GURL url, original_url; + if (archive.url != archive.final_archived_url) { + url = archive.final_archived_url; + original_url = archive.url; + } else { + url = archive.url; + original_url = archive.url; + } + OfflinePageItem offline_page(url, archive.offline_id, archive.client_id, + dest_path, archive.file_size, base::Time::Now()); offline_page.original_url = original_url; - offline_page.title = title; + offline_page.title = archive.title; // Moves the file from download directory to offline archive directory. The // file move operation should be done on background thread. background_task_runner_->PostTask( FROM_HERE, - base::Bind( - &MoveFile, file_path, dest_path, - base::RetainedRef(base::ThreadTaskRunnerHandle::Get()), - base::Bind(&PrefetchImporterImpl::OnMoveFileDone, - weak_ptr_factory_.GetWeakPtr(), offline_page, callback))); + base::Bind(&MoveFile, archive.file_path, dest_path, + base::RetainedRef(base::ThreadTaskRunnerHandle::Get()), + base::Bind(&PrefetchImporterImpl::OnMoveFileDone, + weak_ptr_factory_.GetWeakPtr(), offline_page))); } void PrefetchImporterImpl::OnMoveFileDone(const OfflinePageItem& offline_page, - const CompletedCallback& callback, bool success) { if (!success) { - callback.Run(false, OfflinePageModel::kInvalidOfflineId); + NotifyImportCompleted(OfflinePageModel::kInvalidOfflineId, false); return; } @@ -85,15 +87,14 @@ OfflinePageModelFactory::GetForBrowserContext(context_); DCHECK(offline_page_model); - offline_page_model->AddPage( - offline_page, base::Bind(&PrefetchImporterImpl::OnFileImported, - weak_ptr_factory_.GetWeakPtr(), callback)); + offline_page_model->AddPage(offline_page, + base::Bind(&PrefetchImporterImpl::OnPageAdded, + weak_ptr_factory_.GetWeakPtr())); } -void PrefetchImporterImpl::OnFileImported(const CompletedCallback& callback, - AddPageResult result, - int64_t offline_id) { - callback.Run(result == AddPageResult::SUCCESS, offline_id); +void PrefetchImporterImpl::OnPageAdded(AddPageResult result, + int64_t offline_id) { + NotifyImportCompleted(offline_id, result == AddPageResult::SUCCESS); } } // namespace offline_pages
diff --git a/chrome/browser/offline_pages/prefetch/prefetch_importer_impl.h b/chrome/browser/offline_pages/prefetch/prefetch_importer_impl.h index 13453f52..b92e921 100644 --- a/chrome/browser/offline_pages/prefetch/prefetch_importer_impl.h +++ b/chrome/browser/offline_pages/prefetch/prefetch_importer_impl.h
@@ -27,27 +27,18 @@ // The implementation of PrefetchImporter. class PrefetchImporterImpl : public PrefetchImporter { public: - PrefetchImporterImpl(content::BrowserContext* context, + PrefetchImporterImpl(PrefetchDispatcher* dispatcher, + content::BrowserContext* context, scoped_refptr<base::TaskRunner> background_task_runner); ~PrefetchImporterImpl() override; // PrefetchImporter implementation. - void ImportFile(const GURL& url, - const GURL& original_url, - const base::string16& title, - int64_t offline_id, - const ClientId& client_id, - const base::FilePath& file_path, - int64_t file_size, - const CompletedCallback& callback) override; + void ImportArchive(const PrefetchArchiveInfo& archive) override; private: void OnMoveFileDone(const OfflinePageItem& offline_page, - const CompletedCallback& callback, bool success); - void OnFileImported(const CompletedCallback& callback, - AddPageResult result, - int64_t offline_id); + void OnPageAdded(AddPageResult result, int64_t offline_id); content::BrowserContext* context_; scoped_refptr<base::TaskRunner> background_task_runner_;
diff --git a/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc b/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc index d4d7791..8c9a8d3b 100644 --- a/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc +++ b/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc
@@ -84,8 +84,8 @@ DownloadServiceFactory::GetForBrowserContext(context), chrome::GetChannel()); - auto prefetch_importer = - base::MakeUnique<PrefetchImporterImpl>(context, background_task_runner); + auto prefetch_importer = base::MakeUnique<PrefetchImporterImpl>( + prefetch_dispatcher.get(), context, background_task_runner); std::unique_ptr<PrefetchBackgroundTaskHandler> prefetch_background_task_handler =
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc index 9d797e6..4b7db57 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -170,7 +170,7 @@ password_reuse_detection_manager_(this), #endif driver_factory_(nullptr), - credential_manager_impl_(web_contents, this), + content_credential_manager_(this), password_manager_client_bindings_(web_contents, this), observer_(nullptr), credentials_filter_(this, @@ -487,11 +487,12 @@ metrics_recorder_.reset(); } - // From this point on, the CredentialManagerImpl will service API calls in the - // context of the new WebContents::GetLastCommittedURL, which may very well be - // cross-origin. Disconnect existing client, and drop pending requests. + // From this point on, the ContentCredentialManager will service API calls in + // the context of the new WebContents::GetLastCommittedURL, which may very + // well be cross-origin. Disconnect existing client, and drop pending + // requests. if (!navigation_handle->IsSameDocument()) - credential_manager_impl_.DisconnectBinding(); + content_credential_manager_.DisconnectBinding(); // TODO(crbug.com/706392): Fix password reuse detection for Android. #if !defined(OS_ANDROID) @@ -771,7 +772,7 @@ if (!instance) return; - instance->credential_manager_impl_.BindRequest(std::move(request)); + instance->content_credential_manager_.BindRequest(std::move(request)); } // static
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.h b/chrome/browser/password_manager/chrome_password_manager_client.h index 9c01080..1892af2 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.h +++ b/chrome/browser/password_manager/chrome_password_manager_client.h
@@ -13,8 +13,8 @@ #include "base/optional.h" #include "build/build_config.h" #include "components/autofill/content/common/autofill_driver.mojom.h" +#include "components/password_manager/content/browser/content_credential_manager.h" #include "components/password_manager/content/browser/content_password_manager_driver_factory.h" -#include "components/password_manager/content/browser/credential_manager_impl.h" #include "components/password_manager/core/browser/password_manager.h" #include "components/password_manager/core/browser/password_manager_client.h" #include "components/password_manager/core/browser/password_manager_metrics_recorder.h" @@ -142,7 +142,7 @@ #if defined(UNIT_TEST) bool was_store_ever_called() const { return was_store_ever_called_; } bool has_binding_for_credential_manager() const { - return credential_manager_impl_.HasBinding(); + return content_credential_manager_.HasBinding(); } #endif @@ -206,7 +206,7 @@ // As a mojo service, will be registered into service registry // of the main frame host by ChromeContentBrowserClient // once main frame host was created. - password_manager::CredentialManagerImpl credential_manager_impl_; + password_manager::ContentCredentialManager content_credential_manager_; content::WebContentsFrameBindingSet<autofill::mojom::PasswordManagerClient> password_manager_client_bindings_;
diff --git a/chrome/browser/password_manager/credential_manager_browsertest.cc b/chrome/browser/password_manager/credential_manager_browsertest.cc index 3d736459..6140a4bd 100644 --- a/chrome/browser/password_manager/credential_manager_browsertest.cc +++ b/chrome/browser/password_manager/credential_manager_browsertest.cc
@@ -89,9 +89,9 @@ // be serviced in the context of the initial document. // // If |preestablish_mojo_pipe| is set, then the CredentialManagerClient will - // establish the Mojo connection to the CredentialManagerImpl ahead of time, - // instead of letting the Mojo connection be established on-demand when the - // call to store() triggered from the unload handler. + // establish the Mojo connection to the ContentCredentialManager ahead of + // time, instead of letting the Mojo connection be established on-demand when + // the call to store() triggered from the unload handler. void TestStoreInUnloadHandlerForSameSiteNavigation( bool preestablish_mojo_pipe) { // Use URLs that differ on subdomains so we can tell which one was used for @@ -124,7 +124,7 @@ ASSERT_EQ(old_rfh, WebContents()->GetMainFrame()); // Ensure that the old document no longer has a Mojo connection to the - // CredentialManagerImpl, nor can it get one later. + // ContentCredentialManager, nor can it get one later. // // The sequence of events for same-RFH navigations is as follows: // 1.) FrameHostMsg_DidStartProvisionalLoad @@ -138,10 +138,10 @@ // // After Step 2.1, the old Document cannot issue a new Mojo InterfaceRequest // anymore. Plus, because the AssociatedInterfaceRegistry, through which the - // associated interface to the CredentialManagerImpl is retrieved, is itself - // Channel-associated, any InterfaceRequest messages that may have been - // issued before or during Step 2.1, will be guaranteed to arrive to the - // browser side before FrameHostMsg_DidCommitProvisionalLoad in Step 3. + // associated interface to the ContentCredentialManager is retrieved, is + // itself Channel-associated, any InterfaceRequest messages that may have + // been issued before or during Step 2.1, will be guaranteed to arrive to + // the browser side before FrameHostMsg_DidCommitProvisionalLoad in Step 3. // // Hence it is sufficient to check that the Mojo connection is closed now. EXPECT_FALSE(client->has_binding_for_credential_manager()); @@ -181,9 +181,9 @@ // handler before a cross-site transfer navigation, the request is ignored. // // If |preestablish_mojo_pipe| is set, then the CredentialManagerClient will - // establish the Mojo connection to the CredentialManagerImpl ahead of time, - // instead of letting the Mojo connection be established on-demand when the - // call to store() triggered from the unload handler. + // establish the Mojo connection to the ContentCredentialManager ahead of + // time, instead of letting the Mojo connection be established on-demand when + // the call to store() triggered from the unload handler. void TestStoreInUnloadHandlerForCrossSiteNavigation( bool preestablish_mojo_pipe) { const GURL a_url = https_test_server().GetURL("a.com", "/title1.html"); @@ -216,8 +216,9 @@ // Ensure that the navigator.credentials.store() call is never serviced. // The sufficient conditions for this are: // -- The swapped out RFH is destroyed, so the RenderFrame cannot - // establish a new Mojo connection to CredentialManagerImpl anymore. - // -- There is no already existing Mojo connection to CredentialManagerImpl + // establish a new Mojo connection to ContentCredentialManager anymore. + // -- There is no already existing Mojo connection to + // ContentCredentialManager // either, which could be used to call store() in the future. // -- There have not been any calls to store() in the past. rfh_destruction_observer.WaitUntilDeleted();
diff --git a/chrome/browser/platform_util_unittest.cc b/chrome/browser/platform_util_unittest.cc index 888284b..953b251a 100644 --- a/chrome/browser/platform_util_unittest.cc +++ b/chrome/browser/platform_util_unittest.cc
@@ -5,7 +5,6 @@ #include "chrome/browser/platform_util.h" #include <memory> -#include <vector> #include "base/bind.h" #include "base/callback.h" @@ -60,8 +59,7 @@ // New FileSystemBackend that uses our MockSpecialStoragePolicy. additional_backends->push_back( base::MakeUnique<chromeos::FileSystemBackend>( - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - external_mount_points, + nullptr, nullptr, nullptr, nullptr, nullptr, external_mount_points, storage::ExternalMountPoints::GetSystemInstance())); } };
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index f4f3fb2..d989ec5 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -10,6 +10,7 @@ #include <utility> #include <vector> +#include "ash/public/cpp/ash_pref_names.h" #include "base/bind.h" #include "base/macros.h" #include "base/memory/ptr_util.h" @@ -491,7 +492,7 @@ ash::prefs::kShowLogoutButtonInTray, base::Value::Type::BOOLEAN }, { key::kShelfAutoHideBehavior, - prefs::kShelfAutoHideBehaviorLocal, + ash::prefs::kShelfAutoHideBehaviorLocal, base::Value::Type::STRING }, { key::kSessionLengthLimit, prefs::kSessionLengthLimit,
diff --git a/chrome/browser/printing/background_printing_manager.cc b/chrome/browser/printing/background_printing_manager.cc index fd10907..d1ca0dcc 100644 --- a/chrome/browser/printing/background_printing_manager.cc +++ b/chrome/browser/printing/background_printing_manager.cc
@@ -67,7 +67,8 @@ void BackgroundPrintingManager::OwnPrintPreviewDialog( WebContents* preview_dialog) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(PrintPreviewDialogController::IsPrintPreviewDialog(preview_dialog)); + DCHECK(PrintPreviewDialogController::IsPrintPreviewURL( + preview_dialog->GetURL())); CHECK(!HasPrintPreviewDialog(preview_dialog)); printing_contents_map_[preview_dialog] =
diff --git a/chrome/browser/printing/print_preview_dialog_controller.cc b/chrome/browser/printing/print_preview_dialog_controller.cc index 780928be..ba6ea65 100644 --- a/chrome/browser/printing/print_preview_dialog_controller.cc +++ b/chrome/browser/printing/print_preview_dialog_controller.cc
@@ -241,11 +241,6 @@ } // static -bool PrintPreviewDialogController::IsPrintPreviewDialog(WebContents* contents) { - return IsPrintPreviewURL(contents->GetURL()); -} - -// static bool PrintPreviewDialogController::IsPrintPreviewURL(const GURL& url) { return (url.SchemeIs(content::kChromeUIScheme) && url.host_piece() == chrome::kChromeUIPrintHost);
diff --git a/chrome/browser/printing/print_preview_dialog_controller.h b/chrome/browser/printing/print_preview_dialog_controller.h index 85e9880a..b5d8821 100644 --- a/chrome/browser/printing/print_preview_dialog_controller.h +++ b/chrome/browser/printing/print_preview_dialog_controller.h
@@ -42,6 +42,9 @@ // Call this instead of GetOrCreatePreviewDialog(). static void PrintPreview(content::WebContents* initiator); + // Returns true if |url| is a print preview url. + static bool IsPrintPreviewURL(const GURL& url); + // Get/Create the print preview dialog for |initiator|. // Exposed for unit tests. content::WebContents* GetOrCreatePreviewDialog( @@ -66,12 +69,6 @@ const content::NotificationSource& source, const content::NotificationDetails& details) override; - // Returns true if |contents| is a print preview dialog. - static bool IsPrintPreviewDialog(content::WebContents* contents); - - // Returns true if |url| is a print preview url. - static bool IsPrintPreviewURL(const GURL& url); - // Erase the initiator info associated with |preview_dialog|. void EraseInitiatorInfo(content::WebContents* preview_dialog);
diff --git a/chrome/browser/printing/print_view_manager.cc b/chrome/browser/printing/print_view_manager.cc index fa54bcc..9b81375 100644 --- a/chrome/browser/printing/print_view_manager.cc +++ b/chrome/browser/printing/print_view_manager.cc
@@ -59,7 +59,7 @@ print_preview_state_(NOT_PREVIEWING), print_preview_rfh_(nullptr), scripted_print_preview_rph_(nullptr) { - if (PrintPreviewDialogController::IsPrintPreviewDialog(web_contents)) { + if (PrintPreviewDialogController::IsPrintPreviewURL(web_contents->GetURL())) { EnableInternalPDFPluginForContents( web_contents->GetRenderProcessHost()->GetID(), web_contents->GetMainFrame()->GetRoutingID()); @@ -146,7 +146,8 @@ void PrintViewManager::RenderFrameCreated( content::RenderFrameHost* render_frame_host) { - if (PrintPreviewDialogController::IsPrintPreviewDialog(web_contents())) { + if (PrintPreviewDialogController::IsPrintPreviewURL( + web_contents()->GetURL())) { EnableInternalPDFPluginForContents(render_frame_host->GetProcess()->GetID(), render_frame_host->GetRoutingID()); }
diff --git a/chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.cc b/chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.cc index 9548aea4..5a6ff38d 100644 --- a/chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.cc +++ b/chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.cc
@@ -109,15 +109,11 @@ } void ResourceCoordinatorWebContentsObserver::WasShown() { - tab_resource_coordinator_->SendEvent( - resource_coordinator::EventType::kOnWebContentsShown); tab_resource_coordinator_->SetProperty( resource_coordinator::mojom::PropertyType::kVisible, true); } void ResourceCoordinatorWebContentsObserver::WasHidden() { - tab_resource_coordinator_->SendEvent( - resource_coordinator::EventType::kOnWebContentsHidden); tab_resource_coordinator_->SetProperty( resource_coordinator::mojom::PropertyType::kVisible, false); } @@ -145,6 +141,19 @@ process_resource_coordinator->AddChild(*frame_resource_coordinator); } +void ResourceCoordinatorWebContentsObserver::TitleWasSet( + content::NavigationEntry* entry, + bool explicit_set) { + // Ignore first time title updated event, since it happens as part of loading + // process. + if (!first_time_title_updated_) { + first_time_title_updated_ = true; + return; + } + tab_resource_coordinator_->SendEvent( + resource_coordinator::mojom::Event::kTitleUpdated); +} + void ResourceCoordinatorWebContentsObserver::UpdateUkmRecorder( const GURL& url) { if (!base::FeatureList::IsEnabled(ukm::kUkmFeature)) {
diff --git a/chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.h b/chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.h index 0cef5d5..a08264a 100644 --- a/chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.h +++ b/chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.h
@@ -37,6 +37,7 @@ void WasHidden() override; void DidFinishNavigation( content::NavigationHandle* navigation_handle) override; + void TitleWasSet(content::NavigationEntry* entry, bool explicit_set) override; void EnsureUkmRecorderInterface(); void MaybeSetUkmRecorderInterface(bool ukm_recorder_already_initialized); @@ -52,6 +53,7 @@ std::unique_ptr<resource_coordinator::ResourceCoordinatorInterface> tab_resource_coordinator_; ukm::SourceId ukm_source_id_; + bool first_time_title_updated_ = false; resource_coordinator::mojom::ServiceCallbacksPtr service_callbacks_;
diff --git a/chrome/browser/resources/chromeos/login/md_top_header_bar.css b/chrome/browser/resources/chromeos/login/md_top_header_bar.css index ed65f74..1914131 100644 --- a/chrome/browser/resources/chromeos/login/md_top_header_bar.css +++ b/chrome/browser/resources/chromeos/login/md_top_header_bar.css
@@ -17,11 +17,11 @@ .new-note-action-container { display: flex; flex: 0; - height: 56px; + height: 48px; justify-content: flex-end; - min-width: 56px; + min-width: 48px; overflow: hidden; - width: 56px; + width: 48px; z-index: 1; } @@ -42,13 +42,13 @@ .new-note-action { -webkit-tap-highlight-color: transparent; background-color: rgba(0, 0, 0, 0.2); - border-radius: 0 0 0 48px; + border-radius: 0 0 0 44px; cursor: pointer; display: flex; - height: 48px; + height: 44px; justify-content: flex-end; transition: all 300ms ease-in; - width: 48px; + width: 44px; z-index: 1; } @@ -66,20 +66,20 @@ } html[dir=rtl] .new-note-action { - border-radius: 0 0 48px 0; + border-radius: 0 0 44px 0; } .new-note-action:hover, .new-note-action:focus { - border-radius: 0 0 0 56px; - height: 56px; + border-radius: 0 0 0 48px; + height: 48px; outline: none; - width: 56px; + width: 48px; } html[dir=rtl] .new-note-action:hover, html[dir=rtl] .new-note-action:focus { - border-radius: 0 0 56px 0; + border-radius: 0 0 48px 0; } .new-note-action-container-activated > .new-note-action { @@ -97,8 +97,9 @@ } .new-note-action-icon { + -webkit-padding-end: 11px; height: 16px; - padding: 16px; + padding-top: 12px; width: 16px; }
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.js b/chrome/browser/resources/chromeos/login/oobe_welcome.js index 7500d0c..1d8f5d52 100644 --- a/chrome/browser/resources/chromeos/login/oobe_welcome.js +++ b/chrome/browser/resources/chromeos/login/oobe_welcome.js
@@ -363,6 +363,7 @@ if (this.networkLastSelectedGuid_ == '' && state.ConnectionState == CrOnc.ConnectionState.CONNECTED) { this.onSelectedNetworkConnected_(); + return; } // If user has previously selected another network, there
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.html b/chrome/browser/resources/chromeos/login/screen_gaia_signin.html index de61c5ef..a2ca6d1 100644 --- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.html +++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.html
@@ -12,8 +12,6 @@ </oobe-back-button> <div class="flex"> </div> - <oobe-next-button inverse disabled> - </oobe-next-button> </div> </oobe-dialog> <div id="gaia-step-contents" class="step-contents">
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js index 9204c66..4040aca7 100644 --- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js +++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
@@ -1203,6 +1203,7 @@ var adAuthUI = this.getSigninFrame_(); adAuthUI.setUser(username); adAuthUI.setInvalid(errorState); + this.authCompleted_ = false; this.loading = false; Oobe.getInstance().headerHidden = false; }
diff --git a/chrome/browser/resources/local_ntp/local_ntp.css b/chrome/browser/resources/local_ntp/local_ntp.css index 10fbfa6..a88cf32d 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.css +++ b/chrome/browser/resources/local_ntp/local_ntp.css
@@ -2,6 +2,19 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +html { + /* document's column count is set dynamically from JS. */ + --column-count: 4; + --content-width: calc( + (var(--column-count) * (var(--tile-width) + var(--tile-margin))) + /* We add an extra pixel because rounding errors on different zooms can + * make the width shorter than it should be. */ + + 1px); + /* These values must match NTP_DESIGN constants in JS. */ + --tile-margin: 16px; + --tile-width: 154px; +} + /* TODO: Need to discuss with NTP folks before we remove font-family from the * body tag. */ body { @@ -14,13 +27,15 @@ } #ntp-contents { + margin: 0 auto; text-align: -webkit-center; + width: var(--content-width); } .non-google-page #ntp-contents { + left: calc(50% - var(--content-width)/2); position: absolute; top: calc(50% - 155px); - width: 100%; } body.hide-fakebox-logo #logo, @@ -28,20 +43,33 @@ visibility: hidden; } +#search { + margin: 0 calc(var(--tile-margin) / 2); + width: calc(100% - var(--tile-margin)); +} + #logo { - background-image: url(../../../../ui/webui/resources/images/google_logo.svg); - background-repeat: no-repeat; - height: 92px; + height: 249px; margin-bottom: 24px; - margin-top: 157px; - width: 272px; + position: relative; } .non-google-page #logo { display: none; } -body.alternate-logo #logo { +#logo-default { + background-image: url(../../../../ui/webui/resources/images/google_logo.svg); + background-repeat: no-repeat; + bottom: 0; + height: 92px; + left: calc(50% - 272px/2); + position: absolute; + transition: opacity 130ms; + width: 272px; +} + +body.alternate-logo #logo-default { -webkit-mask-image: url(../../../../ui/webui/resources/images/google_logo.svg); -webkit-mask-repeat: no-repeat; @@ -61,8 +89,6 @@ outline: none; position: relative; transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1); - /* #fakebox width is set dynamically from JS. */ - width: 300px; } .non-google-page #fakebox {
diff --git a/chrome/browser/resources/local_ntp/local_ntp.html b/chrome/browser/resources/local_ntp/local_ntp.html index 4f4f9f5..54c8107 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.html +++ b/chrome/browser/resources/local_ntp/local_ntp.html
@@ -18,13 +18,19 @@ <div id="one-google" class="hidden"></div> <div id="ntp-contents"> - <div id="logo" title="Google"></div> - <div id="fakebox"> - <div id="fakebox-text"></div> - <input id="fakebox-input" autocomplete="off" tabIndex="-1" type="url" - aria-hidden="true"> - <div id="fakebox-cursor"></div> - <div id="fakebox-speech" tabIndex="0" hidden></div> + <div id="search"> + <!-- Container for the logo, whether default or doodle. --> + <div id="logo"> + <!-- The logo that is displayed in the absence of a doodle. --> + <div id="logo-default" title="Google"></div> + </div> + <div id="fakebox"> + <div id="fakebox-text"></div> + <input id="fakebox-input" autocomplete="off" tabIndex="-1" type="url" + aria-hidden="true"> + <div id="fakebox-cursor"></div> + <div id="fakebox-speech" tabIndex="0" hidden></div> + </div> </div> <div id="most-visited"> <!-- The container for the tiles. The MV iframe goes in here. -->
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js index 1ac7234..9695eda 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.js +++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -411,13 +411,7 @@ return false; numColumnsShown = newNumColumns; - // We add an extra pixel because rounding errors on different zooms can - // make the width shorter than it should be. - var tilesContainerWidth = Math.ceil(numColumnsShown * tileRequiredWidth) + 1; - $(IDS.TILES).style.width = tilesContainerWidth + 'px'; - // -2 to account for border. - var fakeboxWidth = (tilesContainerWidth - NTP_DESIGN.tileMargin - 2); - $(IDS.FAKEBOX).style.width = fakeboxWidth + 'px'; + document.documentElement.style.setProperty('--column-count', numColumnsShown); return true; }
diff --git a/chrome/browser/resources/md_downloads/action_service.html b/chrome/browser/resources/md_downloads/action_service.html index 0dce3440..7d59ba9e 100644 --- a/chrome/browser/resources/md_downloads/action_service.html +++ b/chrome/browser/resources/md_downloads/action_service.html
@@ -1,4 +1,4 @@ -<link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://downloads/i18n_setup.html"> +<link rel="import" href="chrome://downloads/browser_proxy.html"> <script src="chrome://downloads/action_service.js"></script>
diff --git a/chrome/browser/resources/md_downloads/action_service.js b/chrome/browser/resources/md_downloads/action_service.js index 1aac588c..67e515c 100644 --- a/chrome/browser/resources/md_downloads/action_service.js +++ b/chrome/browser/resources/md_downloads/action_service.js
@@ -3,10 +3,14 @@ // found in the LICENSE file. cr.define('downloads', function() { + // TODO(dpapad): Rename to SearchService. class ActionService { constructor() { - /** @private {Array<string>} */ + /** @private {!Array<string>} */ this.searchTerms_ = []; + + /** @private {!downloads.BrowserProxy} */ + this.browserProxy_ = downloads.BrowserProxy.getInstance(); } /** @@ -18,40 +22,17 @@ return searchText.split(/"([^"]*)"/).map(s => s.trim()).filter(s => !!s); } - /** @param {string} id ID of the download to cancel. */ - cancel(id) { - chrome.send('cancel', [id]); - } - /** Instructs the browser to clear all finished downloads. */ clearAll() { if (loadTimeData.getBoolean('allowDeletingHistory')) { - chrome.send('clearAll'); + this.browserProxy_.clearAll(); this.search(''); } } - /** @param {string} id ID of the dangerous download to discard. */ - discardDangerous(id) { - chrome.send('discardDangerous', [id]); - } - - /** @param {string} url URL of a file to download. */ - download(url) { - const a = document.createElement('a'); - a.href = url; - a.setAttribute('download', ''); - a.click(); - } - - /** @param {string} id ID of the download that the user started dragging. */ - drag(id) { - chrome.send('drag', [id]); - } - /** Loads more downloads with the current search terms. */ loadMore() { - chrome.send('getDownloads', this.searchTerms_); + this.browserProxy_.getDownloads(this.searchTerms_); } /** @@ -62,41 +43,6 @@ return this.searchTerms_.length > 0; } - /** Opens the current local destination for downloads. */ - openDownloadsFolder() { - chrome.send('openDownloadsFolderRequiringGesture'); - } - - /** - * @param {string} id ID of the download to run locally on the user's box. - */ - openFile(id) { - chrome.send('openFileRequiringGesture', [id]); - } - - /** @param {string} id ID the of the progressing download to pause. */ - pause(id) { - chrome.send('pause', [id]); - } - - /** @param {string} id ID of the finished download to remove. */ - remove(id) { - chrome.send('remove', [id]); - } - - /** @param {string} id ID of the paused download to resume. */ - resume(id) { - chrome.send('resume', [id]); - } - - /** - * @param {string} id ID of the dangerous download to save despite - * warnings. - */ - saveDangerous(id) { - chrome.send('saveDangerousRequiringGesture', [id]); - } - /** * @param {string} searchText What to search for. * @return {boolean} Whether |searchText| resulted in new search terms. @@ -117,19 +63,6 @@ this.loadMore(); return true; } - - /** - * Shows the local folder a finished download resides in. - * @param {string} id ID of the download to show. - */ - show(id) { - chrome.send('show', [id]); - } - - /** Undo download removal. */ - undo() { - chrome.send('undo'); - } } cr.addSingletonGetter(ActionService);
diff --git a/chrome/browser/resources/md_downloads/action_service_unittest.gtestjs b/chrome/browser/resources/md_downloads/action_service_unittest.gtestjs index 2546172..bc3524b 100644 --- a/chrome/browser/resources/md_downloads/action_service_unittest.gtestjs +++ b/chrome/browser/resources/md_downloads/action_service_unittest.gtestjs
@@ -15,6 +15,7 @@ get extraLibraries() { return [ '../../../../ui/webui/resources/js/cr.js', + 'browser_proxy.js', 'action_service.js', ]; }
diff --git a/chrome/browser/resources/md_downloads/browser_proxy.html b/chrome/browser/resources/md_downloads/browser_proxy.html new file mode 100644 index 0000000..245093d --- /dev/null +++ b/chrome/browser/resources/md_downloads/browser_proxy.html
@@ -0,0 +1,2 @@ +<link rel="import" href="chrome://resources/html/cr.html"> +<script src="browser_proxy.js"></script>
diff --git a/chrome/browser/resources/md_downloads/browser_proxy.js b/chrome/browser/resources/md_downloads/browser_proxy.js new file mode 100644 index 0000000..e85d85dc7 --- /dev/null +++ b/chrome/browser/resources/md_downloads/browser_proxy.js
@@ -0,0 +1,95 @@ +// 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. + +cr.define('downloads', function() { + class BrowserProxy { + /** @param {string} id ID of the download to cancel. */ + cancel(id) { + chrome.send('cancel', [id]); + } + + /** @param {string} id ID of the dangerous download to discard. */ + discardDangerous(id) { + chrome.send('discardDangerous', [id]); + } + + /** @param {string} url URL of a file to download. */ + download(url) { + const a = document.createElement('a'); + a.href = url; + a.setAttribute('download', ''); + a.click(); + } + + /** @param {string} id ID of the download that the user started dragging. */ + drag(id) { + chrome.send('drag', [id]); + } + + /** + * Loads more downloads with the current search terms. + * @param {!Array<string>} searchTerms + */ + getDownloads(searchTerms) { + chrome.send('getDownloads', searchTerms); + } + + /** Opens the current local destination for downloads. */ + openDownloadsFolder() { + chrome.send('openDownloadsFolderRequiringGesture'); + } + + /** + * @param {string} id ID of the download to run locally on the user's box. + */ + openFile(id) { + chrome.send('openFileRequiringGesture', [id]); + } + + /** @param {string} id ID the of the progressing download to pause. */ + pause(id) { + chrome.send('pause', [id]); + } + + /** @param {string} id ID of the finished download to remove. */ + remove(id) { + chrome.send('remove', [id]); + } + + /** Instructs the browser to clear all finished downloads. */ + clearAll() { + chrome.send('clearAll'); + } + + /** @param {string} id ID of the paused download to resume. */ + resume(id) { + chrome.send('resume', [id]); + } + + /** + * @param {string} id ID of the dangerous download to save despite + * warnings. + */ + saveDangerous(id) { + chrome.send('saveDangerousRequiringGesture', [id]); + } + + /** + * Shows the local folder a finished download resides in. + * @param {string} id ID of the download to show. + */ + show(id) { + chrome.send('show', [id]); + } + + /** Undo download removal. */ + undo() { + chrome.send('undo'); + } + } + + cr.addSingletonGetter(BrowserProxy); + + return {BrowserProxy: BrowserProxy}; +});
diff --git a/chrome/browser/resources/md_downloads/compiled_resources2.gyp b/chrome/browser/resources/md_downloads/compiled_resources2.gyp index a435a08c..19accde0 100644 --- a/chrome/browser/resources/md_downloads/compiled_resources2.gyp +++ b/chrome/browser/resources/md_downloads/compiled_resources2.gyp
@@ -6,9 +6,16 @@ { 'target_name': 'action_service', 'dependencies': [ - '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data', + 'browser_proxy', + ], + 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { + 'target_name': 'browser_proxy', + 'dependencies': [ + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', ], 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], }, @@ -37,7 +44,7 @@ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util', '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-behaviors/compiled_resources2.gyp:paper-inky-focus-behavior-extracted', 'constants', - 'action_service', + 'browser_proxy', 'externs', ], 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], @@ -52,6 +59,7 @@ '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:command', '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-list/compiled_resources2.gyp:iron-list-extracted', 'action_service', + 'browser_proxy', 'item', 'toolbar', '<(EXTERNS_GYP):chrome_send', @@ -69,6 +77,7 @@ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-a11y-announcer/compiled_resources2.gyp:iron-a11y-announcer-extracted', '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-menu/compiled_resources2.gyp:paper-menu-extracted', 'action_service', + 'browser_proxy', ], 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], },
diff --git a/chrome/browser/resources/md_downloads/item.html b/chrome/browser/resources/md_downloads/item.html index 84f94d04..a230d16 100644 --- a/chrome/browser/resources/md_downloads/item.html +++ b/chrome/browser/resources/md_downloads/item.html
@@ -11,7 +11,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/paper-progress/paper-progress.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html"> -<link rel="import" href="chrome://downloads/action_service.html"> +<link rel="import" href="chrome://downloads/browser_proxy.html"> <link rel="import" href="chrome://downloads/constants.html"> <link rel="import" href="chrome://downloads/i18n_setup.html"> <link rel="import" href="chrome://downloads/icons.html">
diff --git a/chrome/browser/resources/md_downloads/item.js b/chrome/browser/resources/md_downloads/item.js index 42f0019..d589ab8 100644 --- a/chrome/browser/resources/md_downloads/item.js +++ b/chrome/browser/resources/md_downloads/item.js
@@ -74,7 +74,12 @@ 'observeIsDangerous_(isDangerous_, data)', ], + /** @private {?downloads.BrowserProxy} */ + browserProxy_: null, + + /** @override */ ready: function() { + this.browserProxy_ = downloads.BrowserProxy.getInstance(); this.content = this.$.content; }, @@ -262,12 +267,12 @@ /** @private */ onCancelTap_: function() { - downloads.ActionService.getInstance().cancel(this.data.id); + this.browserProxy_.cancel(this.data.id); }, /** @private */ onDiscardDangerousTap_: function() { - downloads.ActionService.getInstance().discardDangerous(this.data.id); + this.browserProxy_.discardDangerous(this.data.id); }, /** @@ -276,7 +281,7 @@ */ onDragStart_: function(e) { e.preventDefault(); - downloads.ActionService.getInstance().drag(this.data.id); + this.browserProxy_.drag(this.data.id); }, /** @@ -285,35 +290,35 @@ */ onFileLinkTap_: function(e) { e.preventDefault(); - downloads.ActionService.getInstance().openFile(this.data.id); + this.browserProxy_.openFile(this.data.id); }, /** @private */ onPauseOrResumeTap_: function() { if (this.isInProgress_) - downloads.ActionService.getInstance().pause(this.data.id); + this.browserProxy_.pause(this.data.id); else - downloads.ActionService.getInstance().resume(this.data.id); + this.browserProxy_.resume(this.data.id); }, /** @private */ onRemoveTap_: function() { - downloads.ActionService.getInstance().remove(this.data.id); + this.browserProxy_.remove(this.data.id); }, /** @private */ onRetryTap_: function() { - downloads.ActionService.getInstance().download(this.data.url); + this.browserProxy_.download(this.data.url); }, /** @private */ onSaveDangerousTap_: function() { - downloads.ActionService.getInstance().saveDangerous(this.data.id); + this.browserProxy_.saveDangerous(this.data.id); }, /** @private */ onShowTap_: function() { - downloads.ActionService.getInstance().show(this.data.id); + this.browserProxy_.show(this.data.id); }, });
diff --git a/chrome/browser/resources/md_downloads/manager.html b/chrome/browser/resources/md_downloads/manager.html index 4733d0ed..ef56219 100644 --- a/chrome/browser/resources/md_downloads/manager.html +++ b/chrome/browser/resources/md_downloads/manager.html
@@ -8,6 +8,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-announcer/iron-a11y-announcer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html"> <link rel="import" href="chrome://downloads/action_service.html"> +<link rel="import" href="chrome://downloads/browser_proxy.html"> <link rel="import" href="chrome://downloads/constants.html"> <link rel="import" href="chrome://downloads/i18n_setup.html"> <link rel="import" href="chrome://downloads/item.html">
diff --git a/chrome/browser/resources/md_downloads/manager.js b/chrome/browser/resources/md_downloads/manager.js index 5be3230..f6471eafb 100644 --- a/chrome/browser/resources/md_downloads/manager.js +++ b/chrome/browser/resources/md_downloads/manager.js
@@ -55,13 +55,26 @@ 'itemsChanged_(items_.*)', ], - attached: function() { - document.documentElement.classList.remove('loading'); - }, + /** @private {?downloads.BrowserProxy} */ + browserProxy_: null, + + /** @private {?downloads.ActionService} */ + actionService_: null, /** @private {!PromiseResolver} */ loaded_: new PromiseResolver, + /** @override */ + created: function() { + this.browserProxy_ = downloads.BrowserProxy.getInstance(); + this.actionService_ = downloads.ActionService.getInstance(); + }, + + /** @override */ + attached: function() { + document.documentElement.classList.remove('loading'); + }, + /** @private */ clearAll_: function() { this.set('items_', []); @@ -142,9 +155,9 @@ */ onCommand_: function(e) { if (e.command.id == 'clear-all-command') - downloads.ActionService.getInstance().clearAll(); + this.browserProxy_.clearAll(); else if (e.command.id == 'undo-command') - downloads.ActionService.getInstance().undo(); + this.browserProxy_.undo(); else if (e.command.id == 'find-command') this.$.toolbar.onFindCommand(); }, @@ -154,7 +167,7 @@ const list = this.$['downloads-list']; if (list.scrollHeight - list.scrollTop - list.offsetHeight <= 100) { // Approaching the end of the scrollback. Attempt to load more items. - downloads.ActionService.getInstance().loadMore(); + this.actionService_.loadMore(); } this.hasShadow_ = list.scrollTop > 0; }, @@ -168,13 +181,13 @@ document.addEventListener('canExecute', this.onCanExecute_.bind(this)); document.addEventListener('command', this.onCommand_.bind(this)); - downloads.ActionService.getInstance().loadMore(); + this.actionService_.loadMore(); return this.loaded_.promise; }, /** @private */ onSearchChanged_: function() { - this.inSearchMode_ = downloads.ActionService.getInstance().isSearching(); + this.inSearchMode_ = this.actionService_.isSearching(); }, /**
diff --git a/chrome/browser/resources/md_downloads/toolbar.html b/chrome/browser/resources/md_downloads/toolbar.html index 811c211..e53051b 100644 --- a/chrome/browser/resources/md_downloads/toolbar.html +++ b/chrome/browser/resources/md_downloads/toolbar.html
@@ -1,6 +1,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://downloads/action_service.html"> +<link rel="import" href="chrome://downloads/browser_proxy.html"> <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr.html">
diff --git a/chrome/browser/resources/md_downloads/toolbar.js b/chrome/browser/resources/md_downloads/toolbar.js index 5796d0c..a542050d 100644 --- a/chrome/browser/resources/md_downloads/toolbar.js +++ b/chrome/browser/resources/md_downloads/toolbar.js
@@ -20,6 +20,14 @@ }, }, + /** @private {?downloads.BrowserProxy} */ + browserProxy_: null, + + /** @override */ + ready: function() { + this.browserProxy_ = downloads.BrowserProxy.getInstance(); + }, + /** @return {boolean} Whether removal can be undone. */ canUndo: function() { return !this.$.toolbar.getSearchField().isSearchFocused(); @@ -47,7 +55,7 @@ /** @private */ onClearAllTap_: function() { assert(this.canClearAll()); - downloads.ActionService.getInstance().clearAll(); + this.browserProxy_.clearAll(); this.$.moreActionsMenu.close(); }, @@ -69,7 +77,7 @@ /** @private */ onOpenDownloadsFolderTap_: function() { - downloads.ActionService.getInstance().openDownloadsFolder(); + this.browserProxy_.openDownloadsFolder(); this.$.moreActionsMenu.close(); },
diff --git a/chrome/browser/resources/md_extensions/animation_helper.html b/chrome/browser/resources/md_extensions/animation_helper.html deleted file mode 100644 index f03c2229..0000000 --- a/chrome/browser/resources/md_extensions/animation_helper.html +++ /dev/null
@@ -1,9 +0,0 @@ -<link rel="import" href="chrome://resources/html/polymer.html"> - -<link rel="import" href="chrome://resources/html/assert.html"> -<link rel="import" href="chrome://resources/html/cr.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/hero-animation.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/fade-in-animation.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/fade-out-animation.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/scale-down-animation.html"> -<script src="chrome://extensions/animation_helper.js"></script>
diff --git a/chrome/browser/resources/md_extensions/animation_helper.js b/chrome/browser/resources/md_extensions/animation_helper.js deleted file mode 100644 index 1266b7c..0000000 --- a/chrome/browser/resources/md_extensions/animation_helper.js +++ /dev/null
@@ -1,96 +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. - -cr.exportPath('extensions'); - -/** - * The different types of animations this helper supports. - * @enum {number} - */ -extensions.Animation = { - HERO: 0, - FADE_IN: 1, - FADE_OUT: 2, - SCALE_DOWN: 3, -}; - -cr.define('extensions', function() { - 'use strict'; - - /** - * A helper object for setting entry/exit animations. Polymer's support of - * this is pretty limited, since it doesn't allow for things like specifying - * hero properties or nodes. - */ - class AnimationHelper { - /** - * @param {!HTMLElement} element The parent element to set the animations - * on. This will be used as the page in to/fromPage. - * @param {?HTMLElement} node The node to use for scaling and fading - * animations. - */ - constructor(element, node) { - this.element_ = element; - this.node_ = node; - element.animationConfig = {}; - } - - /** - * Set the entry animation for the element. - * @param {!Array<extensions.Animation>} animations - */ - setEntryAnimations(animations) { - const configs = []; - for (let animation of animations) { - switch (animation) { - case extensions.Animation.HERO: - configs.push( - {name: 'hero-animation', id: 'hero', toPage: this.element_}); - break; - case extensions.Animation.FADE_IN: - assert(this.node_); - configs.push({name: 'fade-in-animation', node: this.node_}); - break; - default: - assertNotReached(); - } - } - this.element_.animationConfig.entry = configs; - } - - /** - * Set the exit animation for the element. - * @param {!Array<extensions.Animation>} animations - */ - setExitAnimations(animations) { - const configs = []; - for (let animation of animations) { - switch (animation) { - case extensions.Animation.HERO: - configs.push( - {name: 'hero-animation', id: 'hero', fromPage: this.element_}); - break; - case extensions.Animation.FADE_OUT: - assert(this.node_); - configs.push({name: 'fade-out-animation', node: this.node_}); - break; - case extensions.Animation.SCALE_DOWN: - assert(this.node_); - configs.push({ - name: 'scale-down-animation', - node: this.node_, - transformOrigin: '50% 50%', - axis: 'y', - }); - break; - default: - assertNotReached(); - } - } - this.element_.animationConfig.exit = configs; - } - } - - return {AnimationHelper: AnimationHelper}; -});
diff --git a/chrome/browser/resources/md_extensions/compiled_resources2.gyp b/chrome/browser/resources/md_extensions/compiled_resources2.gyp index 00e8564..ab7b556 100644 --- a/chrome/browser/resources/md_extensions/compiled_resources2.gyp +++ b/chrome/browser/resources/md_extensions/compiled_resources2.gyp
@@ -4,14 +4,6 @@ { 'targets': [ { - 'target_name': 'animation_helper', - 'dependencies': [ - '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', - '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', - ], - 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], - }, - { 'target_name': 'code_section', 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', @@ -26,9 +18,7 @@ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data', - '<(DEPTH)/third_party/polymer/v1_0/components-chromium/neon-animation/compiled_resources2.gyp:neon-animatable-behavior-extracted', '<(EXTERNS_GYP):developer_private', - 'animation_helper', 'item', 'item_util', ], @@ -48,10 +38,8 @@ 'target_name': 'error_page', 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', - '<(DEPTH)/third_party/polymer/v1_0/components-chromium/neon-animation/compiled_resources2.gyp:neon-animatable-behavior-extracted', '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-menu/compiled_resources2.gyp:paper-menu-extracted', '<(EXTERNS_GYP):developer_private', - 'animation_helper', 'code_section', ], 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], @@ -83,10 +71,8 @@ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', - '<(DEPTH)/third_party/polymer/v1_0/components-chromium/neon-animation/compiled_resources2.gyp:neon-animatable-behavior-extracted', '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-resizable-behavior/compiled_resources2.gyp:iron-resizable-behavior-extracted', '<(EXTERNS_GYP):developer_private', - 'animation_helper', 'item', ], 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], @@ -106,9 +92,7 @@ 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', - '<(DEPTH)/third_party/polymer/v1_0/components-chromium/neon-animation/compiled_resources2.gyp:neon-animatable-behavior-extracted', '<(EXTERNS_GYP):developer_private', - 'animation_helper', ], 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], }, @@ -129,7 +113,6 @@ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', '<(EXTERNS_GYP):developer_private', - 'animation_helper', 'detail_view', 'item', 'item_list', @@ -138,6 +121,7 @@ 'navigation_helper', 'sidebar', 'toolbar', + 'view_manager', ], 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], }, @@ -213,5 +197,14 @@ ], 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], }, + { + 'target_name': 'view_manager', + 'dependencies': [ + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', + '<(EXTERNS_GYP):web_animations', + ], + 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], + }, ] }
diff --git a/chrome/browser/resources/md_extensions/detail_view.html b/chrome/browser/resources/md_extensions/detail_view.html index 79960dd47..bb228b8f 100644 --- a/chrome/browser/resources/md_extensions/detail_view.html +++ b/chrome/browser/resources/md_extensions/detail_view.html
@@ -11,8 +11,6 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable-behavior.html"> -<link rel="import" href="chrome://extensions/animation_helper.html"> <link rel="import" href="chrome://extensions/item_util.html"> <dom-module id="extensions-detail-view">
diff --git a/chrome/browser/resources/md_extensions/detail_view.js b/chrome/browser/resources/md_extensions/detail_view.js index d01d4e4..82057c7 100644 --- a/chrome/browser/resources/md_extensions/detail_view.js +++ b/chrome/browser/resources/md_extensions/detail_view.js
@@ -8,7 +8,7 @@ const DetailView = Polymer({ is: 'extensions-detail-view', - behaviors: [I18nBehavior, Polymer.NeonAnimatableBehavior], + behaviors: [I18nBehavior], properties: { /** @@ -24,12 +24,6 @@ inDevMode: Boolean, }, - ready: function() { - this.sharedElements = {hero: this.$.main}; - /** @type {!extensions.AnimationHelper} */ - this.animationHelper = new extensions.AnimationHelper(this, this.$.main); - }, - /** @private */ onCloseButtonTap_: function() { this.fire('close');
diff --git a/chrome/browser/resources/md_extensions/error_page.html b/chrome/browser/resources/md_extensions/error_page.html index 2f131eab..b4c2c1f 100644 --- a/chrome/browser/resources/md_extensions/error_page.html +++ b/chrome/browser/resources/md_extensions/error_page.html
@@ -5,10 +5,8 @@ <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable-behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> -<link rel="import" href="chrome://extensions/animation_helper.html"> <link rel="import" href="chrome://extensions/code_section.html"> <dom-module id="extensions-error-page">
diff --git a/chrome/browser/resources/md_extensions/error_page.js b/chrome/browser/resources/md_extensions/error_page.js index 4025e1b..e5fe405 100644 --- a/chrome/browser/resources/md_extensions/error_page.js +++ b/chrome/browser/resources/md_extensions/error_page.js
@@ -31,8 +31,6 @@ const ErrorPage = Polymer({ is: 'extensions-error-page', - behaviors: [Polymer.NeonAnimatableBehavior], - properties: { /** @type {!chrome.developerPrivate.ExtensionInfo|undefined} */ data: Object, @@ -49,14 +47,6 @@ 'onSelectedErrorChanged_(selectedError_)', ], - ready: function() { - /** @type {!extensions.AnimationHelper} */ - this.animationHelper = new extensions.AnimationHelper(this, this.$.main); - this.animationHelper.setEntryAnimations([extensions.Animation.FADE_IN]); - this.animationHelper.setExitAnimations([extensions.Animation.SCALE_DOWN]); - this.sharedElements = {hero: this.$.main}; - }, - /** * Watches for changes to |data| in order to fetch the corresponding * file source.
diff --git a/chrome/browser/resources/md_extensions/item_list.html b/chrome/browser/resources/md_extensions/item_list.html index b5f786f..3618597 100644 --- a/chrome/browser/resources/md_extensions/item_list.html +++ b/chrome/browser/resources/md_extensions/item_list.html
@@ -4,8 +4,6 @@ <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-resizable-behavior/iron-resizable-behavior.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable-behavior.html"> -<link rel="import" href="chrome://extensions/animation_helper.html"> <link rel="import" href="chrome://extensions/item.html"> <dom-module id="extensions-item-list">
diff --git a/chrome/browser/resources/md_extensions/item_list.js b/chrome/browser/resources/md_extensions/item_list.js index eaa07793..0784416 100644 --- a/chrome/browser/resources/md_extensions/item_list.js +++ b/chrome/browser/resources/md_extensions/item_list.js
@@ -6,7 +6,7 @@ const ItemList = Polymer({ is: 'extensions-item-list', - behaviors: [Polymer.NeonAnimatableBehavior, Polymer.IronResizableBehavior], + behaviors: [Polymer.IronResizableBehavior], properties: { /** @type {Array<!chrome.developerPrivate.ExtensionInfo>} */ @@ -31,21 +31,7 @@ listeners: { 'list.extension-item-size-changed': 'itemSizeChanged_', - }, - - ready: function() { - /** @type {extensions.AnimationHelper} */ - this.animationHelper = new extensions.AnimationHelper(this, this.$.list); - this.animationHelper.setEntryAnimations([extensions.Animation.FADE_IN]); - this.animationHelper.setExitAnimations([extensions.Animation.HERO]); - }, - - /** - * Called when a subpage for a given item is about to be shown. - * @param {string} id - */ - willShowItemSubpage: function(id) { - this.sharedElements = {hero: this.$$('#' + id)}; + 'view-enter-start': 'onViewEnterStart_', }, /** @@ -88,6 +74,11 @@ return !this.shouldShowEmptyItemsMessage_() && this.shownItems_.length === 0; }, + + /** @private */ + onViewEnterStart_: function() { + this.fire('resize'); // This is needed to correctly render iron-list. + }, }); return {
diff --git a/chrome/browser/resources/md_extensions/keyboard_shortcuts.html b/chrome/browser/resources/md_extensions/keyboard_shortcuts.html index bf779b8..1678a87 100644 --- a/chrome/browser/resources/md_extensions/keyboard_shortcuts.html +++ b/chrome/browser/resources/md_extensions/keyboard_shortcuts.html
@@ -3,10 +3,8 @@ <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/md_select_css.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable-behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html"> -<link rel="import" href="chrome://extensions/animation_helper.html"> <link rel="import" href="chrome://extensions/shortcut_input.html"> <dom-module id="extensions-keyboard-shortcuts">
diff --git a/chrome/browser/resources/md_extensions/keyboard_shortcuts.js b/chrome/browser/resources/md_extensions/keyboard_shortcuts.js index 850dfc3..160e3ce 100644 --- a/chrome/browser/resources/md_extensions/keyboard_shortcuts.js +++ b/chrome/browser/resources/md_extensions/keyboard_shortcuts.js
@@ -9,8 +9,6 @@ const KeyboardShortcuts = Polymer({ is: 'extensions-keyboard-shortcuts', - behaviors: [Polymer.NeonAnimatableBehavior], - properties: { /** @type {Array<!chrome.developerPrivate.ExtensionInfo>} */ items: Array, @@ -25,14 +23,6 @@ }, }, - ready: function() { - /** @type {!extensions.AnimationHelper} */ - this.animationHelper = new extensions.AnimationHelper(this, this.$.main); - this.animationHelper.setEntryAnimations([extensions.Animation.FADE_IN]); - this.animationHelper.setExitAnimations([extensions.Animation.SCALE_DOWN]); - this.sharedElements = {hero: this.$.main}; - }, - /** * @return {!Array<!chrome.developerPrivate.ExtensionInfo>} * @private
diff --git a/chrome/browser/resources/md_extensions/manager.html b/chrome/browser/resources/md_extensions/manager.html index 2603abc..355a84ea 100644 --- a/chrome/browser/resources/md_extensions/manager.html +++ b/chrome/browser/resources/md_extensions/manager.html
@@ -3,13 +3,12 @@ <link rel="import" href="chrome://resources/cr_elements/cr_drawer/cr_drawer.html"> <link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html"> <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> +<link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/html/promise_resolver.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-header-panel/paper-header-panel.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animated-pages.html"> <link rel="import" href="chrome://extensions/detail_view.html"> <link rel="import" href="chrome://extensions/drop_overlay.html"> <link rel="import" href="chrome://extensions/error_page.html"> @@ -22,6 +21,7 @@ <link rel="import" href="chrome://extensions/service.html"> <link rel="import" href="chrome://extensions/sidebar.html"> <link rel="import" href="chrome://extensions/toolbar.html"> +<link rel="import" href="chrome://extensions/view_manager.html"> <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> <dom-module id="extensions-manager"> @@ -41,27 +41,11 @@ flex-basis: 256px; } - #pages { + #viewManager { flex-grow: 1; overflow-y: auto; } - /* Neon-animated pages set the position of the content to be absolute, - * which is necessary for animations, but breaks sub-page layout. Apply a - * static position to the selected page. See - * https://github.com/PolymerElements/neon-animation/issues/101 for - * conversations. - * Note: Another proposed solution was - * neon-animated-pages .iron-selected:not(.neon-animating) { - * position: relative; - * } - * but the below appears to work fine, and is in line with what settings - * does. - */ - neon-animated-pages ::content > .iron-selected { - position: static; - } - extensions-item { display: inline-block; } @@ -82,23 +66,22 @@ <extensions-sidebar></extensions-sidebar> </div> </dialog> - <neon-animated-pages id="pages" attr-for-selected="id" - selected="items-list"> + <extensions-view-manager id="viewManager"> <extensions-item-list id="items-list" items="[[extensions]]" delegate="[[delegate]]" in-dev-mode="[[inDevMode]]" - filter="[[filter]]" hidden$="[[!didInitPage_]]"> + filter="[[filter]]" hidden$="[[!didInitPage_]]" slot="view"> </extensions-item-list> <extensions-detail-view id="details-view" delegate="[[delegate]]" in-dev-mode="[[inDevMode]]" data="[[detailViewItem_]]" - on-close="onDetailsViewClose_"> + on-close="onDetailsViewClose_" slot="view"> </extensions-detail-view> <extensions-keyboard-shortcuts id="keyboard-shortcuts" - items="[[extensions]]"> + items="[[extensions]]" slot="view"> </extensions-keyboard-shortcuts> <extensions-error-page id="error-page" on-close="onErrorPageClose_" - data="[[errorPageItem_]]" delegate="[[delegate]]"> + data="[[errorPageItem_]]" delegate="[[delegate]]" slot="view"> </extensions-error-page> - </neon-animated-pages> + </extensions-view-manager> <extensions-options-dialog id="options-dialog"> </extensions-options-dialog> <extensions-pack-dialog id="pack-dialog" delegate="[[delegate]]"> @@ -108,4 +91,4 @@ </paper-header-panel> </template> <script src="chrome://extensions/manager.js"></script> -</dom-module> +</dom-module> \ No newline at end of file
diff --git a/chrome/browser/resources/md_extensions/manager.js b/chrome/browser/resources/md_extensions/manager.js index 0f515ce..6f64abe 100644 --- a/chrome/browser/resources/md_extensions/manager.js +++ b/chrome/browser/resources/md_extensions/manager.js
@@ -78,12 +78,6 @@ */ navigationHelper_: Object, - /** - * The current page being shown. - * @private {!PageState} - */ - currentPage_: Object, - /** @type {!Array<!chrome.developerPrivate.ExtensionInfo>} */ extensions: { type: Array, @@ -115,6 +109,13 @@ 'items-list.extension-item-show-errors': 'onShouldShowItemErrors_', }, + /** + * The current page being shown. Default to null, and initPage will figure + * out the initial page based on url. + * @private {?PageState} + */ + currentPage_: null, + created: function() { this.readyPromiseResolver = new PromiseResolver(); }, @@ -128,7 +129,6 @@ this.listHelper_ = new ListHelper(this); this.sidebar.setListDelegate(this.listHelper_); this.readyPromiseResolver.resolve(); - this.currentPage_ = {page: Page.LIST}; this.navigationHelper_ = new extensions.NavigationHelper(newPage => { this.changePage(newPage, true); }); @@ -137,7 +137,7 @@ // still on the details page. We could be on a different page if the // user hit back while the options dialog was visible; in that case, the // new page is already correct. - if (this.currentPage_.page == Page.DETAILS) { + if (this.currentPage_ && this.currentPage_.page == Page.DETAILS) { // This will update the currentPage_ and the NavigationHelper; since // the active page is already the details page, no main page // transition occurs. @@ -280,11 +280,11 @@ // that the DOM will have stale data, but there's no point in causing the // extra work. if (this.detailViewItem_ && this.detailViewItem_.id == item.id && - this.$.pages.selected == Page.DETAILS) { + this.currentPage_.page == Page.DETAILS) { this.detailViewItem_ = item; } else if ( this.errorPageItem_ && this.errorPageItem_.id == item.id && - this.$.pages.selected == Page.ERRORS) { + this.currentPage_.page == Page.ERRORS) { this.errorPageItem_ = item; } }, @@ -329,7 +329,7 @@ * of the change. */ changePage: function(newPage, isSilent) { - if (this.currentPage_.page == newPage.page && + if (this.currentPage_ && this.currentPage_.page == newPage.page && this.currentPage_.subpage == newPage.subpage && this.currentPage_.extensionId == newPage.extensionId) { return; @@ -339,7 +339,7 @@ if (this.optionsDialog.open) this.optionsDialog.close(); - const fromPage = this.$.pages.selected; + const fromPage = this.currentPage_ ? this.currentPage_.page : null; const toPage = newPage.page; let data; if (newPage.extensionId) @@ -351,27 +351,8 @@ this.errorPageItem_ = assert(data); if (fromPage != toPage) { - let entry; - let exit; - if (fromPage == Page.LIST && - (toPage == Page.DETAILS || toPage == Page.ERRORS)) { - this.$['items-list'].willShowItemSubpage(data.id); - entry = [extensions.Animation.HERO]; - // The item grid can be larger than the detail view that we're - // hero'ing into, so we want to also fade out to avoid any jarring. - exit = [extensions.Animation.HERO, extensions.Animation.FADE_OUT]; - } else if (toPage == Page.LIST) { - entry = [extensions.Animation.FADE_IN]; - exit = [extensions.Animation.SCALE_DOWN]; - } else { - assert(toPage == Page.DETAILS || toPage == Page.SHORTCUTS); - entry = [extensions.Animation.FADE_IN]; - exit = [extensions.Animation.FADE_OUT]; - } - - this.getPage_(fromPage).animationHelper.setExitAnimations(exit); - this.getPage_(toPage).animationHelper.setEntryAnimations(entry); - this.$.pages.selected = toPage; + /** @type {extensions.ViewManager} */ (this.$.viewManager) + .switchView(toPage); } if (newPage.subpage) {
diff --git a/chrome/browser/resources/md_extensions/toolbar.html b/chrome/browser/resources/md_extensions/toolbar.html index 72d0443..20d8d952 100644 --- a/chrome/browser/resources/md_extensions/toolbar.html +++ b/chrome/browser/resources/md_extensions/toolbar.html
@@ -4,6 +4,7 @@ <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/paper_toggle_style_css.html"> +<link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
diff --git a/chrome/browser/resources/md_extensions/view_manager.html b/chrome/browser/resources/md_extensions/view_manager.html new file mode 100644 index 0000000..75a6207 --- /dev/null +++ b/chrome/browser/resources/md_extensions/view_manager.html
@@ -0,0 +1,26 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="chrome://resources/html/assert.html"> +<link rel="import" href="chrome://resources/html/cr.html"> + +<dom-module id="extensions-view-manager"> + <template> + <style> + :host ::slotted([slot=view]) { + bottom: 0; + display: none; + left: 0; + position: absolute; + right: 0; + top: 0; + } + + :host ::slotted(.active), + :host ::slotted(.closing) { + display: block; + } + </style> + <slot name="view"></slot> + </template> + <script src="chrome://extensions/view_manager.js"></script> +</dom-module> \ No newline at end of file
diff --git a/chrome/browser/resources/md_extensions/view_manager.js b/chrome/browser/resources/md_extensions/view_manager.js new file mode 100644 index 0000000..28ee965d --- /dev/null +++ b/chrome/browser/resources/md_extensions/view_manager.js
@@ -0,0 +1,113 @@ +// 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. + +cr.define('extensions', function() { + 'use strict'; + + /** + * TODO(scottchen): shim for not having Animation.finished implemented. Can + * replace with Animation.finished if Chrome implements it (see: + * crbug.com/257235). + * @param {!Animation} animation + * @return {!Promise} + */ + function whenFinished(animation) { + return new Promise(function(resolve, reject) { + animation.addEventListener('finish', resolve); + }); + } + + /** @type {!Map<string, function(!Element): !Promise>} */ + const viewAnimations = new Map(); + viewAnimations.set('no-animation', () => Promise.resolve()); + viewAnimations.set('fade-in', element => { + const animation = element.animate( + { + opacity: [0, 1], + }, + /** @type {!KeyframeEffectOptions} */ ({ + duration: 180, + easing: 'ease-in-out', + iterations: 1, + })); + + return whenFinished(animation); + }); + viewAnimations.set('fade-out', element => { + const animation = element.animate( + { + opacity: [1, 0], + }, + /** @type {!KeyframeEffectOptions} */ ({ + duration: 180, + easing: 'ease-in-out', + iterations: 1, + })); + + return whenFinished(animation); + }); + + const ViewManager = Polymer({ + is: 'extensions-view-manager', + + /** + * @param {!Element} element + * @param {string} animation + * @return {!Promise} + * @private + */ + exit_: function(element, animation) { + const animationFunction = extensions.viewAnimations.get(animation); + assert(animationFunction); + + element.classList.remove('active'); + element.classList.add('closing'); + element.dispatchEvent(new CustomEvent('view-exit-start')); + return animationFunction(element).then(function() { + element.classList.remove('closing'); + element.dispatchEvent(new CustomEvent('view-exit-finish')); + }); + }, + + /** + * @param {!Element} element + * @param {!string} animation + * @return {!Promise} + * @private + */ + enter_: function(element, animation) { + const animationFunction = extensions.viewAnimations.get(animation); + assert(animationFunction); + + element.classList.add('active'); + element.dispatchEvent(new CustomEvent('view-enter-start')); + return animationFunction(element).then(function() { + element.dispatchEvent(new CustomEvent('view-enter-finish')); + }); + }, + + /** + * @param {string} newViewId + * @param {string=} enterAnimation + * @param {string=} exitAnimation + * @return {!Promise} + */ + switchView: function(newViewId, enterAnimation, exitAnimation) { + const previousView = this.querySelector('.active'); + const newView = assert(this.querySelector('#' + newViewId)); + + const promises = []; + if (previousView) { + promises.push(this.exit_(previousView, exitAnimation || 'fade-out')); + promises.push(this.enter_(newView, enterAnimation || 'fade-in')); + } else { + promises.push(this.enter_(newView, 'no-animation')); + } + + return Promise.all(promises); + }, + }); + + return {viewAnimations: viewAnimations, ViewManager: ViewManager}; +}); \ No newline at end of file
diff --git a/chrome/browser/resources/md_user_manager/user_manager_pages.html b/chrome/browser/resources/md_user_manager/user_manager_pages.html index 5ac8b03..f438e76 100644 --- a/chrome/browser/resources/md_user_manager/user_manager_pages.html +++ b/chrome/browser/resources/md_user_manager/user_manager_pages.html
@@ -20,7 +20,7 @@ } /* neon-animated-pages does not automatically hide what's under content */ - neon-animatable:not(.iron-selected) > ::content > * { + neon-animatable:not(.iron-selected) ::slotted(*) { display: none !important; } </style> @@ -37,7 +37,7 @@ </template> </neon-animatable> <neon-animatable id="user-pods-page"> - <content></content> + <slot></slot> </neon-animatable> <neon-animatable id="supervised-learn-more-page"> <template is="dom-if"
diff --git a/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html b/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html index f36fcc9..83947a3e 100644 --- a/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html +++ b/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html
@@ -75,7 +75,7 @@ <div id="dropdown" style="display: none"> <h1>{{header}}</h1> <div id="scroll-container"> - <content></content> + <slot></slot> </div> </div> </div>
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.js b/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.js index b50fe91..99d2c1e 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.js +++ b/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.js
@@ -118,9 +118,8 @@ */ setFontsData_: function(response) { var fontMenuOptions = []; - for (var i = 0; i < response.fontList.length; ++i) { - fontMenuOptions.push( - {value: response.fontList[i][0], name: response.fontList[i][1]}); + for (var fontData of response.fontList) { + fontMenuOptions.push({value: fontData[0], name: fontData[1]}); } this.fontOptions_ = fontMenuOptions; this.advancedExtensionUrl_ = response.extensionUrl;
diff --git a/chrome/browser/resources/settings/appearance_page/fonts_browser_proxy.js b/chrome/browser/resources/settings/appearance_page/fonts_browser_proxy.js index d513b3ad..306c3839b0 100644 --- a/chrome/browser/resources/settings/appearance_page/fonts_browser_proxy.js +++ b/chrome/browser/resources/settings/appearance_page/fonts_browser_proxy.js
@@ -4,7 +4,10 @@ /** * @typedef {{ - * fontList: Array<{0: string, 1: (string|undefined), 2: (string|undefined)}>, + * fontList: !Array<{ + * 0: string, + * 1: (string|undefined), + * 2: (string|undefined)}>, * extensionUrl: string * }} */
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html index c2058b6..7c592698f 100644 --- a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html +++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
@@ -68,6 +68,10 @@ width: 16px; } + [slot=footer] iron-icon { + margin: auto; + } + .clear-browsing-data-footer { -webkit-padding-start: 4px; align-items: flex-start;
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_tabs.html b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_tabs.html index 71637dff..b991c99 100644 --- a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_tabs.html +++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_tabs.html
@@ -68,6 +68,10 @@ width: 16px; } + [slot=footer] iron-icon { + margin: auto; + } + .clear-browsing-data-footer { -webkit-padding-start: 4px; align-items: flex-start;
diff --git a/chrome/browser/resources/settings/site_settings/site_details_permission.html b/chrome/browser/resources/settings/site_settings/site_details_permission.html index 11cbf80..b356f18 100644 --- a/chrome/browser/resources/settings/site_settings/site_details_permission.html +++ b/chrome/browser/resources/settings/site_settings/site_details_permission.html
@@ -52,6 +52,10 @@ <option id="block" value$="[[ContentSetting.BLOCK]]"> $i18n{siteSettingsActionBlock} </option> + <option id="ask" value$="[[ContentSetting.ASK]]" + hidden$="[[!isNonDefaultAsk_(site.setting, site.source)]]"> + $i18n{siteSettingsActionAsk} + </option> </select> <span class="md-select-underline"></span> </div>
diff --git a/chrome/browser/resources/settings/site_settings/site_details_permission.js b/chrome/browser/resources/settings/site_settings/site_details_permission.js index 0b6a61d6..26d8fd7 100644 --- a/chrome/browser/resources/settings/site_settings/site_details_permission.js +++ b/chrome/browser/resources/settings/site_settings/site_details_permission.js
@@ -62,6 +62,16 @@ this.$.permission.disabled = site.source != settings.SiteSettingSource.EMBARGO; } + + if (this.isNonDefaultAsk_(site.setting, site.source)) { + assert( + this.$.permission.disabled, + 'The \'Ask\' entry is for display-only and cannot be set by the ' + + 'user.'); + assert( + this.$.permission.value == settings.ContentSetting.ASK, + '\'Ask\' should only show up when it\'s currently selected.'); + } }, /** @@ -121,9 +131,8 @@ /** * Returns true if there's a string to display that describes the source of - * this permission's setting. - * Note |source| is a subproperty of |this.site|, so this will only be called - * when |this.site| is updated. + * this permission's setting. Currently, this only gets called when + * |this.site| is updated. * @param {!settings.SiteSettingSource} source The source of the permission. * @private */ @@ -134,9 +143,28 @@ }, /** + * Returns true if the permission is set to a non-default 'ask'. Currently, + * this only gets called when |this.site| is updated. + * @param {!settings.ContentSetting} setting The setting of the permission. + * @param {!settings.SiteSettingSource} source The source of the permission. + * @private + */ + isNonDefaultAsk_: function(setting, source) { + if (setting != settings.ContentSetting.ASK || + source == settings.SiteSettingSource.DEFAULT) { + return false; + } + + assert( + source == settings.SiteSettingSource.EXTENSION || + source == settings.SiteSettingSource.POLICY, + 'Only extensions or enterprise policy can change the setting to ASK.'); + return true; + }, + + /** * Updates the string used to describe the source of this permission setting. - * Note |source| is a subproperty of |this.site|, so this will only be called - * when |this.site| is updated. + * Currently, this only gets called when |this.site| is updated. * @param {!settings.SiteSettingSource} source The source of the permission. * @param {!string} embargoString * @param {!string} insecureOriginString
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_browsertest_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_browsertest_win.cc index 4ba4c5a..66e682b5 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_browsertest_win.cc +++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_browsertest_win.cc
@@ -78,8 +78,9 @@ dialog_controller_->OnInfected(std::set<base::FilePath>()); } +// Disabled due to flaky failures: https://crbug.com/753632 IN_PROC_BROWSER_TEST_F(ChromeCleanerPromptUserTest, - OnInfectedBrowserNotAvailable) { + DISABLED_OnInfectedBrowserNotAvailable) { browser()->window()->Minimize(); base::RunLoop().RunUntilIdle(); dialog_controller_->OnInfected(std::set<base::FilePath>());
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.cc b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.cc index ccf4f66..2773e5e 100644 --- a/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.cc +++ b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.cc
@@ -239,19 +239,15 @@ void OneGoogleBarFetcherImpl::Fetch(OneGoogleCallback callback) { callbacks_.push_back(std::move(callback)); - IssueRequestIfNoneOngoing(); -} - -void OneGoogleBarFetcherImpl::IssueRequestIfNoneOngoing() { - // If there is an ongoing request, let it complete. - if (pending_request_.get()) { - return; - } GURL google_base_url = google_util::CommandLineGoogleBaseURL(); if (!google_base_url.is_valid()) { google_base_url = google_url_tracker_->google_url(); } + + // Note: If there is an ongoing request, abandon it. It's possible that + // something has changed in the meantime (e.g. signin state) that would make + // the result obsolete. pending_request_ = base::MakeUnique<AuthenticatedURLFetcher>( request_context_, google_base_url, base::BindOnce(&OneGoogleBarFetcherImpl::FetchDone,
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.h b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.h index f59029e..f79a6e9 100644 --- a/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.h +++ b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.h
@@ -41,8 +41,6 @@ private: class AuthenticatedURLFetcher; - void IssueRequestIfNoneOngoing(); - void FetchDone(const net::URLFetcher* source); void JsonParsed(std::unique_ptr<base::Value> value);
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl_unittest.cc b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl_unittest.cc index 5594cafd..339e4a6 100644 --- a/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl_unittest.cc +++ b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl_unittest.cc
@@ -183,19 +183,36 @@ EXPECT_THAT(data->end_of_body_script, Eq("end_of_body_script_value")); } +class MockURLFetcherDelegateForTests + : public net::TestURLFetcher::DelegateForTests { + public: + MOCK_METHOD1(OnRequestStart, void(int fetcher_id)); + MOCK_METHOD1(OnChunkUpload, void(int fetcher_id)); + MOCK_METHOD1(OnRequestEnd, void(int fetcher_id)); +}; + +TEST_F(OneGoogleBarFetcherImplTest, SecondRequestOverridesFirst) { + // Trigger the first request. + base::MockCallback<OneGoogleBarFetcher::OneGoogleCallback> first_callback; + one_google_bar_fetcher()->Fetch(first_callback.Get()); + net::TestURLFetcher* first_fetcher = GetRunningURLFetcher(); + testing::StrictMock<MockURLFetcherDelegateForTests> first_mock_delegate; + first_fetcher->SetDelegateForTests(&first_mock_delegate); + + // Trigger a second request. That should cancel the first one. + EXPECT_CALL(first_mock_delegate, OnRequestEnd(0)); + base::MockCallback<OneGoogleBarFetcher::OneGoogleCallback> second_callback; + one_google_bar_fetcher()->Fetch(second_callback.Get()); +} + TEST_F(OneGoogleBarFetcherImplTest, CoalescesMultipleRequests) { // Trigger two requests. base::MockCallback<OneGoogleBarFetcher::OneGoogleCallback> first_callback; one_google_bar_fetcher()->Fetch(first_callback.Get()); - net::URLFetcher* first_fetcher = GetRunningURLFetcher(); base::MockCallback<OneGoogleBarFetcher::OneGoogleCallback> second_callback; one_google_bar_fetcher()->Fetch(second_callback.Get()); - net::URLFetcher* second_fetcher = GetRunningURLFetcher(); - // Expect that only one fetcher handles both requests. - EXPECT_THAT(first_fetcher, Eq(second_fetcher)); - - // But both callbacks should get called. + // Make sure that a single response causes both callbacks to be called. base::Optional<OneGoogleBarData> first_data; base::Optional<OneGoogleBarData> second_data;
diff --git a/chrome/browser/signin/easy_unlock_service.cc b/chrome/browser/signin/easy_unlock_service.cc index e5eefbb..5200585 100644 --- a/chrome/browser/signin/easy_unlock_service.cc +++ b/chrome/browser/signin/easy_unlock_service.cc
@@ -329,9 +329,7 @@ } bool EasyUnlockService::IsEnabled() const { - // The feature is enabled iff there are any paired devices. - const base::ListValue* devices = GetRemoteDevices(); - return devices && !devices->empty(); + return false; } void EasyUnlockService::OpenSetupApp() {
diff --git a/chrome/browser/signin/easy_unlock_service_regular.cc b/chrome/browser/signin/easy_unlock_service_regular.cc index 537c227c..b46615b 100644 --- a/chrome/browser/signin/easy_unlock_service_regular.cc +++ b/chrome/browser/signin/easy_unlock_service_regular.cc
@@ -104,7 +104,9 @@ } void EasyUnlockServiceRegular::LoadRemoteDevices() { - if (GetCryptAuthDeviceManager()->GetUnlockKeys().empty()) { + bool has_unlock_keys = !GetCryptAuthDeviceManager()->GetUnlockKeys().empty(); + pref_manager_->SetIsEasyUnlockEnabled(has_unlock_keys); + if (!has_unlock_keys) { SetProximityAuthDevices(GetAccountId(), cryptauth::RemoteDeviceList()); return; } @@ -565,6 +567,22 @@ #endif } +bool EasyUnlockServiceRegular::IsEnabled() const { +#if defined(OS_CHROMEOS) + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + proximity_auth::switches::kDisableBluetoothLowEnergyDiscovery)) { + // The feature is enabled iff there are any paired devices set by the + // component app. + const base::ListValue* devices = GetRemoteDevices(); + return devices && !devices->empty(); + } + + return pref_manager_ && pref_manager_->IsEasyUnlockEnabled(); +#else + return false; +#endif +} + void EasyUnlockServiceRegular::OnWillFinalizeUnlock(bool success) { will_unlock_using_easy_unlock_ = success; } @@ -600,10 +618,17 @@ if (public_keys_before_sync == public_keys_after_sync) return; - // Show the appropriate notification if an unlock key is first synced or if it - // changes an existing key. - // Note: We do not show a notification when EasyUnlock is disabled by sync. - if (public_keys_after_sync.size() > 0) { +// Show the appropriate notification if an unlock key is first synced or if it +// changes an existing key. +// Note: We do not show a notification when EasyUnlock is disabled by sync nor +// if EasyUnlock was enabled through the setup app. +#if defined(OS_CHROMEOS) + bool is_setup_fresh = + short_lived_user_context_ && short_lived_user_context_->user_context(); +#else + bool is_setup_fresh = true; +#endif + if (public_keys_after_sync.size() > 0 && !is_setup_fresh) { if (public_keys_before_sync.size() == 0) { notification_controller_->ShowChromebookAddedNotification(); } else { @@ -697,8 +722,10 @@ cryptauth::InvocationReason::INVOCATION_REASON_FEATURE_TOGGLED); EasyUnlockService::ResetLocalStateForUser(GetAccountId()); SetRemoteDevices(base::ListValue()); + SetProximityAuthDevices(GetAccountId(), cryptauth::RemoteDeviceList()); SetTurnOffFlowStatus(IDLE); ReloadAppAndLockScreen(); + pref_manager_->SetIsEasyUnlockEnabled(false); } void EasyUnlockServiceRegular::OnToggleEasyUnlockApiFailed(
diff --git a/chrome/browser/signin/easy_unlock_service_regular.h b/chrome/browser/signin/easy_unlock_service_regular.h index 09b82e4a..cb023eba 100644 --- a/chrome/browser/signin/easy_unlock_service_regular.h +++ b/chrome/browser/signin/easy_unlock_service_regular.h
@@ -99,6 +99,7 @@ void InitializeInternal() override; void ShutdownInternal() override; bool IsAllowedInternal() const override; + bool IsEnabled() const override; void OnWillFinalizeUnlock(bool success) override; void OnSuspendDoneInternal() override; #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc b/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc index ab4c9ab..21913bd 100644 --- a/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc +++ b/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc
@@ -354,7 +354,20 @@ bool EasyUnlockServiceSignin::IsAllowedInternal() const { return service_active_ && account_id_.is_valid() && - !chromeos::LoginState::Get()->IsUserLoggedIn(); + !chromeos::LoginState::Get()->IsUserLoggedIn() && + (pref_manager_ && pref_manager_->IsEasyUnlockAllowed()); +} + +bool EasyUnlockServiceSignin::IsEnabled() const { + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + proximity_auth::switches::kDisableBluetoothLowEnergyDiscovery)) { + // In EasyUnlock v1, we used the presence of the hardlock state as an + // indicator of whether EasyUnlock is enabled. + EasyUnlockScreenlockStateHandler::HardlockState hardlock_state; + return GetPersistedHardlockState(&hardlock_state); + } + + return pref_manager_->IsEasyUnlockEnabled(); } void EasyUnlockServiceSignin::OnWillFinalizeUnlock(bool success) { @@ -407,6 +420,11 @@ user_pod_last_focused_timestamp_ = base::TimeTicks::Now(); ResetScreenlockState(); + + pref_manager_->SetActiveUser(account_id); + if (!IsAllowed() || !IsEnabled()) + return; + ShowInitialUserState(); // ShowInitialUserState() will display a tooltip explaining that the user must @@ -419,8 +437,6 @@ return; } - pref_manager_->SetActiveUser(account_id); - if (should_update_app_state) { UpdateAppState(); } else {
diff --git a/chrome/browser/signin/easy_unlock_service_signin_chromeos.h b/chrome/browser/signin/easy_unlock_service_signin_chromeos.h index 12cc074..09bdd79 100644 --- a/chrome/browser/signin/easy_unlock_service_signin_chromeos.h +++ b/chrome/browser/signin/easy_unlock_service_signin_chromeos.h
@@ -106,6 +106,7 @@ void InitializeInternal() override; void ShutdownInternal() override; bool IsAllowedInternal() const override; + bool IsEnabled() const override; void OnWillFinalizeUnlock(bool success) override; void OnSuspendDoneInternal() override;
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.cc b/chrome/browser/ui/app_list/app_list_view_delegate.cc index d6c3ae2..228b73c 100644 --- a/chrome/browser/ui/app_list/app_list_view_delegate.cc +++ b/chrome/browser/ui/app_list/app_list_view_delegate.cc
@@ -47,6 +47,7 @@ #include "extensions/common/manifest_handlers/launcher_page_info.h" #include "services/service_manager/public/cpp/connector.h" #include "ui/app_list/app_list_switches.h" +#include "ui/app_list/app_list_view_delegate_observer.h" #include "ui/app_list/search_box_model.h" #include "ui/app_list/search_controller.h" #include "ui/app_list/speech_ui_model.h" @@ -266,10 +267,12 @@ void AppListViewDelegate::OnWallpaperColorsChanged( const std::vector<SkColor>& prominent_colors) { - if (!model_) + if (wallpaper_prominent_colors_ == prominent_colors) return; - model_->search_box()->SetWallpaperProminentColors(prominent_colors); + wallpaper_prominent_colors_ = prominent_colors; + for (auto& observer : observers_) + observer.OnWallpaperColorsChanged(); } void AppListViewDelegate::OnHotwordStateChanged(bool started) { @@ -529,6 +532,21 @@ return service && service->GetSpeechRecognitionContents(); } +void AppListViewDelegate::GetWallpaperProminentColors( + std::vector<SkColor>* colors) { + *colors = wallpaper_prominent_colors_; +} + +void AppListViewDelegate::AddObserver( + app_list::AppListViewDelegateObserver* observer) { + observers_.AddObserver(observer); +} + +void AppListViewDelegate::RemoveObserver( + app_list::AppListViewDelegateObserver* observer) { + observers_.RemoveObserver(observer); +} + void AppListViewDelegate::OnTemplateURLServiceChanged() { TemplateURLService* template_url_service = TemplateURLServiceFactory::GetForProfile(profile_);
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.h b/chrome/browser/ui/app_list/app_list_view_delegate.h index 18c7819..3dd489b1 100644 --- a/chrome/browser/ui/app_list/app_list_view_delegate.h +++ b/chrome/browser/ui/app_list/app_list_view_delegate.h
@@ -26,6 +26,8 @@ #include "mojo/public/cpp/bindings/associated_binding.h" #include "mojo/public/cpp/bindings/binding.h" #include "ui/app_list/app_list_view_delegate.h" +#include "ui/app_list/app_list_view_delegate_observer.h" +#include "ui/app_list/views/app_list_view.h" namespace app_list { class CustomLauncherPageContents; @@ -86,6 +88,9 @@ void CustomLauncherPageAnimationChanged(double progress) override; void CustomLauncherPagePopSubpage() override; bool IsSpeechRecognitionEnabled() override; + void GetWallpaperProminentColors(std::vector<SkColor>* colors) override; + void AddObserver(app_list::AppListViewDelegateObserver* observer) override; + void RemoveObserver(app_list::AppListViewDelegateObserver* observer) override; // Overridden from TemplateURLServiceObserver: void OnTemplateURLServiceChanged() override; @@ -159,6 +164,10 @@ // Ash's mojom::WallpaperController. ash::mojom::WallpaperControllerPtr wallpaper_controller_ptr_; + std::vector<SkColor> wallpaper_prominent_colors_; + + base::ObserverList<app_list::AppListViewDelegateObserver> observers_; + base::WeakPtrFactory<AppListViewDelegate> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(AppListViewDelegate);
diff --git a/chrome/browser/ui/ash/chrome_launcher_prefs.cc b/chrome/browser/ui/ash/chrome_launcher_prefs.cc index 85d1600..21a7c26 100644 --- a/chrome/browser/ui/ash/chrome_launcher_prefs.cc +++ b/chrome/browser/ui/ash/chrome_launcher_prefs.cc
@@ -13,7 +13,6 @@ #include "ash/public/cpp/ash_pref_names.h" #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "base/strings/string_number_conversions.h" #include "base/values.h" #include "chrome/browser/app_mode/app_mode_utils.h" #include "chrome/browser/prefs/pref_service_syncable_util.h" @@ -29,9 +28,6 @@ #include "components/prefs/scoped_user_pref_update.h" #include "components/sync/model/string_ordinal.h" #include "components/sync_preferences/pref_service_syncable.h" -#include "ui/display/display.h" -#include "ui/display/screen.h" -#include "ui/display/types/display_constants.h" namespace { @@ -55,148 +51,6 @@ return apps; } -// Returns the preference value for the display with the given |display_id|. -// The pref value is stored in |local_path| and |path|, but the pref service may -// have per-display preferences and the value can be specified by policy. -// Here is the priority: -// * A value managed by policy. This is a single value that applies to all -// displays. -// * A user-set value for the specified display. -// * A user-set value in |local_path| or |path|, if no per-display settings are -// ever specified (see http://crbug.com/173719 for why). |local_path| is -// preferred. See comment in |kShelfAlignment| as to why we consider two -// prefs and why |local_path| is preferred. -// * A value recommended by policy. This is a single value that applies to all -// root windows. -// * The default value for |local_path| if the value is not recommended by -// policy. -std::string GetPerDisplayPref(PrefService* prefs, - int64_t display_id, - const char* local_path, - const char* path) { - const PrefService::Preference* local_pref = prefs->FindPreference(local_path); - const std::string value(prefs->GetString(local_path)); - if (local_pref->IsManaged()) - return value; - - std::string pref_key = base::Int64ToString(display_id); - bool has_per_display_prefs = false; - if (!pref_key.empty()) { - const base::DictionaryValue* shelf_prefs = - prefs->GetDictionary(prefs::kShelfPreferences); - const base::DictionaryValue* display_pref = nullptr; - std::string per_display_value; - if (shelf_prefs->GetDictionary(pref_key, &display_pref) && - display_pref->GetString(path, &per_display_value)) - return per_display_value; - - // If the pref for the specified display is not found, scan the whole prefs - // and check if the prefs for other display is already specified. - std::string unused_value; - for (base::DictionaryValue::Iterator iter(*shelf_prefs); !iter.IsAtEnd(); - iter.Advance()) { - const base::DictionaryValue* display_pref = nullptr; - if (iter.value().GetAsDictionary(&display_pref) && - display_pref->GetString(path, &unused_value)) { - has_per_display_prefs = true; - break; - } - } - } - - if (local_pref->IsRecommended() || !has_per_display_prefs) - return value; - - const base::Value* default_value = prefs->GetDefaultPrefValue(local_path); - std::string default_string; - default_value->GetAsString(&default_string); - return default_string; -} - -// Sets the preference value for the display with the given |display_id|. -void SetPerDisplayPref(PrefService* prefs, - int64_t display_id, - const char* pref_key, - const std::string& value) { - if (display_id < 0) - return; - - // Avoid DictionaryPrefUpdate's notifications for read but unmodified prefs. - const base::DictionaryValue* current_shelf_prefs = - prefs->GetDictionary(prefs::kShelfPreferences); - DCHECK(current_shelf_prefs); - std::string display_key = base::Int64ToString(display_id); - const base::DictionaryValue* current_display_prefs = nullptr; - std::string current_value; - if (current_shelf_prefs->GetDictionary(display_key, ¤t_display_prefs) && - current_display_prefs->GetString(pref_key, ¤t_value) && - current_value == value) { - return; - } - - DictionaryPrefUpdate update(prefs, prefs::kShelfPreferences); - base::DictionaryValue* shelf_prefs = update.Get(); - base::DictionaryValue* display_prefs_weak = nullptr; - if (!shelf_prefs->GetDictionary(display_key, &display_prefs_weak)) { - auto display_prefs = base::MakeUnique<base::DictionaryValue>(); - display_prefs_weak = display_prefs.get(); - shelf_prefs->Set(display_key, std::move(display_prefs)); - } - display_prefs_weak->SetStringWithoutPathExpansion(pref_key, value); -} - -ash::ShelfAlignment AlignmentFromPref(const std::string& value) { - if (value == kShelfAlignmentLeft) - return ash::SHELF_ALIGNMENT_LEFT; - else if (value == kShelfAlignmentRight) - return ash::SHELF_ALIGNMENT_RIGHT; - // Default to bottom. - return ash::SHELF_ALIGNMENT_BOTTOM; -} - -const char* AlignmentToPref(ash::ShelfAlignment alignment) { - switch (alignment) { - case ash::SHELF_ALIGNMENT_BOTTOM: - return kShelfAlignmentBottom; - case ash::SHELF_ALIGNMENT_LEFT: - return kShelfAlignmentLeft; - case ash::SHELF_ALIGNMENT_RIGHT: - return kShelfAlignmentRight; - case ash::SHELF_ALIGNMENT_BOTTOM_LOCKED: - // This should not be a valid preference option for now. We only want to - // lock the shelf during login or when adding a user. - return nullptr; - } - NOTREACHED(); - return nullptr; -} - -ash::ShelfAutoHideBehavior AutoHideBehaviorFromPref(const std::string& value) { - // Note: To maintain sync compatibility with old images of chrome/chromeos - // the set of values that may be encountered includes the now-extinct - // "Default" as well as "Never" and "Always", "Default" should now - // be treated as "Never" (http://crbug.com/146773). - if (value == kShelfAutoHideBehaviorAlways) - return ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS; - return ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER; -} - -const char* AutoHideBehaviorToPref(ash::ShelfAutoHideBehavior behavior) { - switch (behavior) { - case ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS: - return kShelfAutoHideBehaviorAlways; - case ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER: - return kShelfAutoHideBehaviorNever; - case ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN: - // This should not be a valid preference option for now. We only want to - // completely hide it when we run in app mode - or while we temporarily - // hide the shelf as part of an animation (e.g. the multi user change). - return nullptr; - } - NOTREACHED(); - return nullptr; -} - bool IsAppIdArcPackage(const std::string& app_id) { return app_id.find('.') != app_id.npos; } @@ -308,13 +162,6 @@ const char kPinnedAppsPrefPinnedByPolicy[] = "pinned_by_policy"; const char kPinnedAppsPlaceholder[] = "AppShelfIDPlaceholder--------"; -const char kShelfAutoHideBehaviorAlways[] = "Always"; -const char kShelfAutoHideBehaviorNever[] = "Never"; - -const char kShelfAlignmentBottom[] = "Bottom"; -const char kShelfAlignmentLeft[] = "Left"; -const char kShelfAlignmentRight[] = "Right"; - void RegisterChromeLauncherUserPrefs( user_prefs::PrefRegistrySyncable* registry) { // TODO: If we want to support multiple profiles this will likely need to be @@ -327,73 +174,6 @@ CreateDefaultPinnedAppsList(), user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterListPref(prefs::kPolicyPinnedLauncherApps); - registry->RegisterStringPref(prefs::kShelfAutoHideBehavior, - kShelfAutoHideBehaviorNever, - user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterStringPref(prefs::kShelfAutoHideBehaviorLocal, - std::string()); - registry->RegisterStringPref(prefs::kShelfAlignment, - kShelfAlignmentBottom, - user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterStringPref(prefs::kShelfAlignmentLocal, std::string()); - registry->RegisterDictionaryPref(prefs::kShelfPreferences); -} - -ash::ShelfAutoHideBehavior GetShelfAutoHideBehaviorPref(PrefService* prefs, - int64_t display_id) { - DCHECK_NE(display_id, display::kInvalidDisplayId); - - // Don't show the shelf in app mode. - if (chrome::IsRunningInAppMode()) - return ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN; - - // See comment in |kShelfAlignment| as to why we consider two prefs. - return AutoHideBehaviorFromPref( - GetPerDisplayPref(prefs, display_id, prefs::kShelfAutoHideBehaviorLocal, - prefs::kShelfAutoHideBehavior)); -} - -void SetShelfAutoHideBehaviorPref(PrefService* prefs, - int64_t display_id, - ash::ShelfAutoHideBehavior behavior) { - DCHECK_NE(display_id, display::kInvalidDisplayId); - - const char* value = AutoHideBehaviorToPref(behavior); - if (!value) - return; - - SetPerDisplayPref(prefs, display_id, prefs::kShelfAutoHideBehavior, value); - if (display_id == display::Screen::GetScreen()->GetPrimaryDisplay().id()) { - // See comment in |kShelfAlignment| about why we have two prefs here. - prefs->SetString(prefs::kShelfAutoHideBehaviorLocal, value); - prefs->SetString(prefs::kShelfAutoHideBehavior, value); - } -} - -ash::ShelfAlignment GetShelfAlignmentPref(PrefService* prefs, - int64_t display_id) { - DCHECK_NE(display_id, display::kInvalidDisplayId); - - // See comment in |kShelfAlignment| as to why we consider two prefs. - return AlignmentFromPref(GetPerDisplayPref( - prefs, display_id, prefs::kShelfAlignmentLocal, prefs::kShelfAlignment)); -} - -void SetShelfAlignmentPref(PrefService* prefs, - int64_t display_id, - ash::ShelfAlignment alignment) { - DCHECK_NE(display_id, display::kInvalidDisplayId); - - const char* value = AlignmentToPref(alignment); - if (!value) - return; - - SetPerDisplayPref(prefs, display_id, prefs::kShelfAlignment, value); - if (display_id == display::Screen::GetScreen()->GetPrimaryDisplay().id()) { - // See comment in |kShelfAlignment| as to why we consider two prefs. - prefs->SetString(prefs::kShelfAlignmentLocal, value); - prefs->SetString(prefs::kShelfAlignment, value); - } } // Helper that extracts app list from policy preferences. @@ -489,8 +269,9 @@ ChromeLauncherPrefsObserver::CreateIfNecessary(Profile* profile) { sync_preferences::PrefServiceSyncable* prefs = PrefServiceSyncableFromProfile(profile); - if (!prefs->FindPreference(prefs::kShelfAlignmentLocal)->HasUserSetting() || - !prefs->FindPreference(prefs::kShelfAutoHideBehaviorLocal) + if (!prefs->FindPreference(ash::prefs::kShelfAlignmentLocal) + ->HasUserSetting() || + !prefs->FindPreference(ash::prefs::kShelfAutoHideBehaviorLocal) ->HasUserSetting()) { return base::WrapUnique(new ChromeLauncherPrefsObserver(prefs)); } @@ -514,10 +295,10 @@ // if the local values haven't already been set. if (!prefs_->IsSyncing()) return; - PropagatePrefToLocalIfNotSet(prefs_, prefs::kShelfAlignmentLocal, - prefs::kShelfAlignment); - PropagatePrefToLocalIfNotSet(prefs_, prefs::kShelfAutoHideBehaviorLocal, - prefs::kShelfAutoHideBehavior); + PropagatePrefToLocalIfNotSet(prefs_, ash::prefs::kShelfAlignmentLocal, + ash::prefs::kShelfAlignment); + PropagatePrefToLocalIfNotSet(prefs_, ash::prefs::kShelfAutoHideBehaviorLocal, + ash::prefs::kShelfAutoHideBehavior); prefs_->RemoveObserver(this); }
diff --git a/chrome/browser/ui/ash/chrome_launcher_prefs.h b/chrome/browser/ui/ash/chrome_launcher_prefs.h index 713fb59..5ffb2f2 100644 --- a/chrome/browser/ui/ash/chrome_launcher_prefs.h +++ b/chrome/browser/ui/ash/chrome_launcher_prefs.h
@@ -35,32 +35,9 @@ // This is NOT a valid extension identifier so pre-M31 versions ignore it. extern const char kPinnedAppsPlaceholder[]; -// Values used for prefs::kShelfAutoHideBehavior. -extern const char kShelfAutoHideBehaviorAlways[]; -extern const char kShelfAutoHideBehaviorNever[]; - -// Values used for prefs::kShelfAlignment. -extern const char kShelfAlignmentBottom[]; -extern const char kShelfAlignmentLeft[]; -extern const char kShelfAlignmentRight[]; - void RegisterChromeLauncherUserPrefs( user_prefs::PrefRegistrySyncable* registry); -// Get or set the shelf auto hide behavior preference for a particular display. -ash::ShelfAutoHideBehavior GetShelfAutoHideBehaviorPref(PrefService* prefs, - int64_t display_id); -void SetShelfAutoHideBehaviorPref(PrefService* prefs, - int64_t display_id, - ash::ShelfAutoHideBehavior behavior); - -// Get or set the shelf alignment preference for a particular display. -ash::ShelfAlignment GetShelfAlignmentPref(PrefService* prefs, - int64_t display_id); -void SetShelfAlignmentPref(PrefService* prefs, - int64_t display_id, - ash::ShelfAlignment alignment); - // Get the list of pinned apps from preferences. std::vector<ash::ShelfID> GetPinnedAppsFromPrefs( const PrefService* prefs,
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc index ff1470e5..d0c5e31 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
@@ -8,6 +8,7 @@ #include "ash/public/cpp/remote_shelf_item_delegate.h" #include "ash/public/cpp/shelf_item.h" #include "ash/public/cpp/shelf_model.h" +#include "ash/public/cpp/shelf_prefs.h" #include "ash/public/interfaces/constants.mojom.h" #include "ash/resources/grit/ash_resources.h" #include "ash/shelf/shelf.h" @@ -246,11 +247,6 @@ app_window_controllers_.push_back(std::move(extension_app_window_controller)); app_window_controllers_.push_back( base::MakeUnique<ArcAppWindowLauncherController>(this)); - - // Right now ash::Shell isn't created for tests. - // TODO(mukai): Allows it to observe display change and write tests. - if (ash::Shell::HasInstance()) - ash::Shell::Get()->window_tree_host_manager()->AddObserver(this); } ChromeLauncherController::~ChromeLauncherController() { @@ -261,8 +257,6 @@ app_window_controllers_.clear(); model_->RemoveObserver(this); - if (ash::Shell::HasInstance()) - ash::Shell::Get()->window_tree_host_manager()->RemoveObserver(this); // Release all profile dependent resources. ReleaseProfile(); @@ -686,14 +680,16 @@ PrefService* prefs = profile()->GetPrefs(); PrefService* other_prefs = other_profile->GetPrefs(); const int64_t display = GetDisplayIDForShelf(shelf); - const bool currently_shown = ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER == - GetShelfAutoHideBehaviorPref(prefs, display); - const bool other_shown = ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER == - GetShelfAutoHideBehaviorPref(other_prefs, display); + const bool currently_shown = + ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER == + ash::GetShelfAutoHideBehaviorPref(prefs, display); + const bool other_shown = + ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER == + ash::GetShelfAutoHideBehaviorPref(other_prefs, display); return currently_shown != other_shown || - GetShelfAlignmentPref(prefs, display) != - GetShelfAlignmentPref(other_prefs, display); + ash::GetShelfAlignmentPref(prefs, display) != + ash::GetShelfAlignmentPref(other_prefs, display); } void ChromeLauncherController::OnUserProfileReadyToSwitch(Profile* profile) { @@ -706,35 +702,6 @@ return arc_deferred_launcher_.get(); } -void ChromeLauncherController::SetShelfAutoHideBehaviorFromPrefs() { - if (!ConnectToShelfController() || updating_shelf_pref_from_observer_) - return; - - // The pref helper functions return default values for invalid display ids. - PrefService* prefs = profile_->GetPrefs(); - for (const auto& display : display::Screen::GetScreen()->GetAllDisplays()) { - shelf_controller_->SetAutoHideBehavior( - GetShelfAutoHideBehaviorPref(prefs, display.id()), display.id()); - } -} - -void ChromeLauncherController::SetShelfAlignmentFromPrefs() { - if (!ConnectToShelfController() || updating_shelf_pref_from_observer_) - return; - - // The pref helper functions return default values for invalid display ids. - PrefService* prefs = profile_->GetPrefs(); - for (const auto& display : display::Screen::GetScreen()->GetAllDisplays()) { - shelf_controller_->SetAlignment(GetShelfAlignmentPref(prefs, display.id()), - display.id()); - } -} - -void ChromeLauncherController::SetShelfBehaviorsFromPrefs() { - SetShelfAutoHideBehaviorFromPrefs(); - SetShelfAlignmentFromPrefs(); -} - ChromeLauncherController::ScopedPinSyncDisabler ChromeLauncherController::GetScopedPinSyncDisabler() { // Only one temporary disabler should not exist at a time. @@ -1190,8 +1157,6 @@ app_icon_loaders_.push_back(std::move(arc_app_icon_loader)); } - SetShelfBehaviorsFromPrefs(); - pref_change_registrar_.Init(profile()->GetPrefs()); pref_change_registrar_.Add( prefs::kPolicyPinnedLauncherApps, @@ -1205,18 +1170,6 @@ base::Bind(&ChromeLauncherController::ScheduleUpdateAppLaunchersFromPref, base::Unretained(this))); pref_change_registrar_.Add( - prefs::kShelfAlignmentLocal, - base::Bind(&ChromeLauncherController::SetShelfAlignmentFromPrefs, - base::Unretained(this))); - pref_change_registrar_.Add( - prefs::kShelfAutoHideBehaviorLocal, - base::Bind(&ChromeLauncherController::SetShelfAutoHideBehaviorFromPrefs, - base::Unretained(this))); - pref_change_registrar_.Add( - prefs::kShelfPreferences, - base::Bind(&ChromeLauncherController::SetShelfBehaviorsFromPrefs, - base::Unretained(this))); - pref_change_registrar_.Add( prefs::kTouchVirtualKeyboardEnabled, base::Bind(&ChromeLauncherController::SetVirtualKeyboardBehaviorFromPrefs, base::Unretained(this))); @@ -1245,8 +1198,6 @@ app_updaters_.clear(); - prefs_observer_.reset(); - pref_change_registrar_.RemoveAll(); app_list::AppListSyncableService* app_service = @@ -1260,38 +1211,6 @@ /////////////////////////////////////////////////////////////////////////////// // ash::mojom::ShelfObserver: -void ChromeLauncherController::OnShelfInitialized(int64_t display_id) { - if (!ConnectToShelfController()) - return; - - // The pref helper functions return default values for invalid display ids. - PrefService* prefs = profile_->GetPrefs(); - shelf_controller_->SetAlignment(GetShelfAlignmentPref(prefs, display_id), - display_id); - shelf_controller_->SetAutoHideBehavior( - GetShelfAutoHideBehaviorPref(prefs, display_id), display_id); -} - -void ChromeLauncherController::OnAlignmentChanged(ash::ShelfAlignment alignment, - int64_t display_id) { - // The locked alignment is set temporarily and not saved to preferences. - if (alignment == ash::SHELF_ALIGNMENT_BOTTOM_LOCKED) - return; - DCHECK(!updating_shelf_pref_from_observer_); - base::AutoReset<bool> updating(&updating_shelf_pref_from_observer_, true); - // This will uselessly store a preference value for invalid display ids. - SetShelfAlignmentPref(profile_->GetPrefs(), display_id, alignment); -} - -void ChromeLauncherController::OnAutoHideBehaviorChanged( - ash::ShelfAutoHideBehavior auto_hide, - int64_t display_id) { - DCHECK(!updating_shelf_pref_from_observer_); - base::AutoReset<bool> updating(&updating_shelf_pref_from_observer_, true); - // This will uselessly store a preference value for invalid display ids. - SetShelfAutoHideBehaviorPref(profile_->GetPrefs(), display_id, auto_hide); -} - void ChromeLauncherController::OnShelfItemAdded(int32_t index, const ash::ShelfItem& item) { DCHECK(ash_util::IsRunningInMash()) << " Unexpected model synchronization"; @@ -1483,18 +1402,6 @@ } /////////////////////////////////////////////////////////////////////////////// -// ash::WindowTreeHostManager::Observer: - -void ChromeLauncherController::OnDisplayConfigurationChanged() { - // In BOTTOM_LOCKED state, ignore the call of SetShelfBehaviorsFromPrefs. - // Because it might be called by some operations, like crbug.com/627040 - // rotating screen. - ash::Shelf* shelf = ash::Shelf::ForWindow(ash::Shell::GetPrimaryRootWindow()); - if (shelf->alignment() != ash::SHELF_ALIGNMENT_BOTTOM_LOCKED) - SetShelfBehaviorsFromPrefs(); -} - -/////////////////////////////////////////////////////////////////////////////// // AppSyncUIStateObserver: void ChromeLauncherController::OnAppSyncUIStatusChanged() {
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h index d6a6e88..d9425d57 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
@@ -9,7 +9,6 @@ #include <string> #include <vector> -#include "ash/display/window_tree_host_manager.h" #include "ash/public/cpp/shelf_item_delegate.h" #include "ash/public/cpp/shelf_model_observer.h" #include "ash/public/cpp/shelf_types.h" @@ -20,7 +19,6 @@ #include "chrome/browser/ui/app_icon_loader_delegate.h" #include "chrome/browser/ui/app_list/app_list_syncable_service.h" #include "chrome/browser/ui/ash/app_sync_ui_state_observer.h" -#include "chrome/browser/ui/ash/chrome_launcher_prefs.h" #include "chrome/browser/ui/ash/launcher/launcher_app_updater.h" #include "chrome/browser/ui/ash/launcher/settings_window_observer.h" #include "components/prefs/pref_change_registrar.h" @@ -67,7 +65,6 @@ public AppIconLoaderDelegate, private ash::mojom::ShelfObserver, private ash::ShelfModelObserver, - private ash::WindowTreeHostManager::Observer, private AppSyncUIStateObserver, private app_list::AppListSyncableService::Observer, private sync_preferences::PrefServiceSyncableObserver { @@ -224,11 +221,6 @@ // Controller to launch ARC apps in deferred mode. ArcAppDeferredLauncherController* GetArcDeferredLauncher(); - // Sets the shelf auto-hide and/or alignment behavior from prefs. - void SetShelfAutoHideBehaviorFromPrefs(); - void SetShelfAlignmentFromPrefs(); - void SetShelfBehaviorsFromPrefs(); - // Temporarily prevent pinned shelf item changes from updating the sync model. using ScopedPinSyncDisabler = std::unique_ptr<base::AutoReset<bool>>; ScopedPinSyncDisabler GetScopedPinSyncDisabler(); @@ -356,11 +348,6 @@ void ReleaseProfile(); // ash::mojom::ShelfObserver: - void OnShelfInitialized(int64_t display_id) override; - void OnAlignmentChanged(ash::ShelfAlignment alignment, - int64_t display_id) override; - void OnAutoHideBehaviorChanged(ash::ShelfAutoHideBehavior auto_hide, - int64_t display_id) override; void OnShelfItemAdded(int32_t index, const ash::ShelfItem& item) override; void OnShelfItemRemoved(const ash::ShelfID& id) override; void OnShelfItemMoved(const ash::ShelfID& id, int32_t index) override; @@ -377,9 +364,6 @@ void ShelfItemDelegateChanged(const ash::ShelfID& id, ash::ShelfItemDelegate* delegate) override; - // ash::WindowTreeHostManager::Observer: - void OnDisplayConfigurationChanged() override; - // AppSyncUIStateObserver: void OnAppSyncUIStatusChanged() override; @@ -413,9 +397,6 @@ // The binding this instance uses to implment mojom::ShelfObserver mojo::AssociatedBinding<ash::mojom::ShelfObserver> observer_binding_; - // True when setting a shelf pref in response to an observer notification. - bool updating_shelf_pref_from_observer_ = false; - // True when applying changes from the remote ShelfModel owned by Ash. // Changes to the local ShelfModel should not be reported during this time. bool applying_remote_shelf_model_changes_ = false;
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc index 0cb5062..2bcc91c 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
@@ -76,6 +76,7 @@ #include "ui/aura/client/aura_constants.h" #include "ui/aura/window.h" #include "ui/base/window_open_disposition.h" +#include "ui/display/manager/display_manager.h" #include "ui/display/test/display_manager_test_api.h" #include "ui/events/base_event_utils.h" #include "ui/events/event.h"
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc index 9353cb1..f38b5f2 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
@@ -283,12 +283,6 @@ TestShelfController() : binding_(this) {} ~TestShelfController() override {} - ash::ShelfAlignment alignment() const { return alignment_; } - ash::ShelfAutoHideBehavior auto_hide() const { return auto_hide_; } - - size_t alignment_change_count() const { return alignment_change_count_; } - size_t auto_hide_change_count() const { return auto_hide_change_count_; } - size_t added_count() const { return added_count_; } size_t removed_count() const { return removed_count_; } size_t updated_count() const { return updated_count_; } @@ -305,18 +299,6 @@ ash::mojom::ShelfObserverAssociatedPtrInfo observer) override { observer_.Bind(std::move(observer)); } - void SetAlignment(ash::ShelfAlignment alignment, - int64_t display_id) override { - alignment_change_count_++; - alignment_ = alignment; - observer_->OnAlignmentChanged(alignment_, display_id); - } - void SetAutoHideBehavior(ash::ShelfAutoHideBehavior auto_hide, - int64_t display_id) override { - auto_hide_change_count_++; - auto_hide_ = auto_hide; - observer_->OnAutoHideBehaviorChanged(auto_hide_, display_id); - } void AddShelfItem(int32_t, const ash::ShelfItem&) override { added_count_++; } void RemoveShelfItem(const ash::ShelfID&) override { removed_count_++; } void MoveShelfItem(const ash::ShelfID&, int32_t) override {} @@ -327,12 +309,6 @@ } private: - ash::ShelfAlignment alignment_ = ash::SHELF_ALIGNMENT_BOTTOM_LOCKED; - ash::ShelfAutoHideBehavior auto_hide_ = ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN; - - size_t alignment_change_count_ = 0; - size_t auto_hide_change_count_ = 0; - size_t added_count_ = 0; size_t removed_count_ = 0; size_t updated_count_ = 0; @@ -4259,76 +4235,6 @@ EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus()); } -// Tests that shelf profile preferences are loaded on login. -TEST_F(ChromeLauncherControllerTest, PrefsLoadedOnLogin) { - PrefService* prefs = profile()->GetTestingPrefService(); - prefs->SetString(prefs::kShelfAlignmentLocal, "Left"); - prefs->SetString(prefs::kShelfAlignment, "Left"); - prefs->SetString(prefs::kShelfAutoHideBehaviorLocal, "Always"); - prefs->SetString(prefs::kShelfAutoHideBehavior, "Always"); - - TestChromeLauncherController* test_launcher_controller = - shell_delegate_->CreateLauncherController(profile(), model_.get()); - test_launcher_controller->Init(); - - // Simulate login for the test controller. - test_launcher_controller->ReleaseProfile(); - test_launcher_controller->AttachProfile(profile()); - base::RunLoop().RunUntilIdle(); - - TestShelfController* shelf_controller = - test_launcher_controller->test_shelf_controller(); - ASSERT_TRUE(shelf_controller); - EXPECT_EQ(ash::SHELF_ALIGNMENT_LEFT, shelf_controller->alignment()); - EXPECT_EQ(1u, shelf_controller->alignment_change_count()); - EXPECT_EQ(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, - shelf_controller->auto_hide()); - EXPECT_EQ(1u, shelf_controller->auto_hide_change_count()); -} - -// Tests that the shelf controller's changes are not wastefully echoed back. -TEST_F(ChromeLauncherControllerTest, DoNotEchoShelfControllerChanges) { - TestChromeLauncherController* test_launcher_controller = - shell_delegate_->CreateLauncherController(profile(), model_.get()); - test_launcher_controller->Init(); - - // Simulate login for the test controller. - test_launcher_controller->ReleaseProfile(); - test_launcher_controller->AttachProfile(profile()); - base::RunLoop().RunUntilIdle(); - - TestShelfController* shelf_controller = - test_launcher_controller->test_shelf_controller(); - ASSERT_TRUE(shelf_controller); - EXPECT_EQ(ash::SHELF_ALIGNMENT_BOTTOM, shelf_controller->alignment()); - EXPECT_EQ(1u, shelf_controller->alignment_change_count()); - EXPECT_EQ(ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf_controller->auto_hide()); - EXPECT_EQ(1u, shelf_controller->auto_hide_change_count()); - - // Changing settings via the shelf controller causes the launcher controller - // to update profile prefs. The launcher controller's prefs observation should - // not cause those same changes to be echoed back to the shelf controller. - int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); - shelf_controller->SetAlignment(ash::SHELF_ALIGNMENT_LEFT, display_id); - EXPECT_EQ(2u, shelf_controller->alignment_change_count()); - shelf_controller->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, - display_id); - EXPECT_EQ(2u, shelf_controller->auto_hide_change_count()); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(ash::SHELF_ALIGNMENT_LEFT, shelf_controller->alignment()); - EXPECT_EQ(2u, shelf_controller->alignment_change_count()); - EXPECT_EQ(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, - shelf_controller->auto_hide()); - EXPECT_EQ(2u, shelf_controller->auto_hide_change_count()); - - PrefService* prefs = profile()->GetTestingPrefService(); - EXPECT_EQ("Left", prefs->GetString(prefs::kShelfAlignmentLocal)); - EXPECT_EQ("Left", prefs->GetString(prefs::kShelfAlignment)); - EXPECT_EQ("Always", prefs->GetString(prefs::kShelfAutoHideBehaviorLocal)); - EXPECT_EQ("Always", prefs->GetString(prefs::kShelfAutoHideBehavior)); -} - // Ensure Ash and Chrome ShelfModel changes are synchronized correctly in Mash. TEST_F(ChromeLauncherControllerTest, ShelfModelSyncMash) { if (chromeos::GetAshConfig() != ash::Config::MASH)
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc index 6bc765b..31e1624 100644 --- a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc +++ b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
@@ -7,6 +7,7 @@ #include <string> #include "ash/public/cpp/shelf_model.h" +#include "ash/public/cpp/shelf_prefs.h" #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" @@ -24,22 +25,10 @@ #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_util.h" #include "chrome/browser/ui/ash/launcher/desktop_shell_launcher_context_menu.h" #include "chrome/browser/ui/ash/launcher/extension_launcher_context_menu.h" -#include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" -#include "components/prefs/pref_service.h" #include "components/session_manager/core/session_manager.h" #include "content/public/common/context_menu_params.h" -namespace { - -// Returns true if the user can modify the |shelf|'s auto-hide behavior. -bool CanUserModifyShelfAutoHideBehavior(const Profile* profile) { - const std::string& pref = prefs::kShelfAutoHideBehaviorLocal; - return profile->GetPrefs()->FindPreference(pref)->IsUserModifiable(); -} - -} // namespace - // static LauncherContextMenu* LauncherContextMenu::Create( ChromeLauncherController* controller, @@ -98,7 +87,8 @@ case MENU_CHANGE_WALLPAPER: return ash::Shell::Get()->wallpaper_delegate()->CanOpenSetWallpaperPage(); case MENU_AUTO_HIDE: - return CanUserModifyShelfAutoHideBehavior(controller_->profile()); + return ash::CanUserModifyShelfAutoHideBehavior( + controller_->profile()->GetPrefs()); default: DCHECK(command_id < MENU_ITEM_COUNT); return true; @@ -106,13 +96,14 @@ } void LauncherContextMenu::ExecuteCommand(int command_id, int event_flags) { + int64_t display_id = + display::Screen::GetScreen() + ->GetDisplayNearestWindow(shelf_->shelf_widget()->GetNativeWindow()) + .id(); switch (static_cast<MenuItem>(command_id)) { case MENU_OPEN_NEW: controller_->LaunchApp(item_.id, ash::LAUNCH_FROM_UNKNOWN, ui::EF_NONE, - display::Screen::GetScreen() - ->GetDisplayNearestWindow( - shelf_->shelf_widget()->GetNativeWindow()) - .id()); + display_id); break; case MENU_CLOSE: if (item_.type == ash::TYPE_DIALOG) { @@ -139,10 +130,11 @@ controller_->PinAppWithID(item_.id.app_id); break; case MENU_AUTO_HIDE: - shelf_->SetAutoHideBehavior(shelf_->auto_hide_behavior() == - ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS - ? ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER - : ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); + ash::SetShelfAutoHideBehaviorPref( + controller_->profile()->GetPrefs(), display_id, + shelf_->auto_hide_behavior() == ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS + ? ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER + : ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); break; case MENU_ALIGNMENT_MENU: break; @@ -185,7 +177,8 @@ display::Screen::GetScreen()->GetDisplayNearestWindow( shelf_->GetWindow()->GetRootWindow()); if (!IsFullScreenMode(display.id()) && - CanUserModifyShelfAutoHideBehavior(controller_->profile())) { + ash::CanUserModifyShelfAutoHideBehavior( + controller_->profile()->GetPrefs())) { AddCheckItemWithStringId(MENU_AUTO_HIDE, IDS_ASH_SHELF_CONTEXT_MENU_AUTO_HIDE); }
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc b/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc index f89f3788..8f274e1 100644 --- a/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc +++ b/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc
@@ -32,7 +32,6 @@ #include "components/session_manager/core/session_manager.h" #include "ui/aura/window_event_dispatcher.h" #include "ui/display/display.h" -#include "ui/display/screen.h" #include "ui/views/widget/widget.h" namespace { @@ -132,7 +131,7 @@ // menu is disabled when Incognito mode is switched off (by a policy). TEST_F(LauncherContextMenuTest, NewIncognitoWindowMenuIsDisabledWhenIncognitoModeOff) { - int64_t primary_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); + int64_t primary_id = GetPrimaryDisplay().id(); // Initially, "New Incognito window" should be enabled. std::unique_ptr<LauncherContextMenu> menu(CreateLauncherContextMenu( ash::TYPE_BROWSER_SHORTCUT, GetShelf(primary_id))); @@ -157,7 +156,7 @@ // menu is disabled when Incognito mode is forced (by a policy). TEST_F(LauncherContextMenuTest, NewWindowMenuIsDisabledWhenIncognitoModeForced) { - int64_t primary_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); + int64_t primary_id = GetPrimaryDisplay().id(); // Initially, "New window" should be enabled. std::unique_ptr<LauncherContextMenu> menu(CreateLauncherContextMenu( ash::TYPE_BROWSER_SHORTCUT, GetShelf(primary_id))); @@ -177,7 +176,7 @@ // Verifies status of contextmenu items for desktop shell. TEST_F(LauncherContextMenuTest, DesktopShellLauncherContextMenuItemCheck) { - int64_t primary_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); + int64_t primary_id = GetPrimaryDisplay().id(); std::unique_ptr<LauncherContextMenu> menu( CreateLauncherContextMenuForDesktopShell(GetShelf(primary_id))); EXPECT_FALSE( @@ -202,7 +201,7 @@ // opened. TEST_F(LauncherContextMenuTest, DesktopShellLauncherContextMenuVerifyCloseItem) { - int64_t primary_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); + int64_t primary_id = GetPrimaryDisplay().id(); std::unique_ptr<LauncherContextMenu> menu(CreateLauncherContextMenu( ash::TYPE_BROWSER_SHORTCUT, GetShelf(primary_id))); ASSERT_FALSE( @@ -221,7 +220,7 @@ const ash::ShelfItem* item = controller()->GetItem(ash::ShelfID(app_id)); ASSERT_TRUE(item); - int64_t primary_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); + int64_t primary_id = GetPrimaryDisplay().id(); ash::Shelf* shelf = GetShelf(primary_id); std::unique_ptr<LauncherContextMenu> menu( @@ -308,8 +307,8 @@ // shelf is a per-display setting (crbug.com/496681). TEST_F(LauncherContextMenuTest, AutohideShelfOptionOnExternalDisplay) { UpdateDisplay("940x550,940x550"); - int64_t primary_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); - int64_t secondary_id = display_manager()->GetSecondaryDisplay().id(); + int64_t primary_id = GetPrimaryDisplay().id(); + int64_t secondary_id = GetSecondaryDisplay().id(); // Create a normal window on primary display. views::Widget* widget = new views::Widget;
diff --git a/chrome/browser/ui/ash/session_controller_client.cc b/chrome/browser/ui/ash/session_controller_client.cc index 35998e6..0520778dc 100644 --- a/chrome/browser/ui/ash/session_controller_client.cc +++ b/chrome/browser/ui/ash/session_controller_client.cc
@@ -14,6 +14,7 @@ #include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" +#include "chrome/browser/app_mode/app_mode_utils.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/login/ui/user_adding_screen.h" @@ -524,6 +525,7 @@ ash::mojom::SessionInfoPtr info = ash::mojom::SessionInfo::New(); info->can_lock_screen = CanLockScreen(); info->should_lock_screen_automatically = ShouldLockScreenAutomatically(); + info->is_running_in_app_mode = chrome::IsRunningInAppMode(); info->add_user_session_policy = GetAddUserSessionPolicy(); info->state = session_manager->session_state();
diff --git a/chrome/browser/ui/autofill/autofill_popup_layout_model.cc b/chrome/browser/ui/autofill/autofill_popup_layout_model.cc index 5259c4a7..e9bf170 100644 --- a/chrome/browser/ui/autofill/autofill_popup_layout_model.cc +++ b/chrome/browser/ui/autofill/autofill_popup_layout_model.cc
@@ -121,12 +121,9 @@ int AutofillPopupLayoutModel::RowWidthWithoutText(int row, bool has_subtext) const { std::vector<autofill::Suggestion> suggestions = delegate_->GetSuggestions(); - bool is_warning_message = (suggestions[row].frontend_id == - POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE); - const bool is_row_with_ = - (is_warning_message || (suggestions[row].frontend_id == - POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY)); - + const bool is_warning_message = + (suggestions[row].frontend_id == + POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE); int row_size = 2 * (kEndPadding + kPopupBorderThickness); if (has_subtext) row_size += is_warning_message ? kHttpWarningNamePadding : kNamePadding; @@ -135,7 +132,7 @@ const base::string16& icon = suggestions[row].icon; if (!icon.empty()) { row_size += GetIconImage(row).width() + - (is_row_with_ ? kPaddingAfterLeadingIcon : kIconPadding); + (is_warning_message ? kPaddingAfterLeadingIcon : kIconPadding); } return row_size; } @@ -225,11 +222,6 @@ gfx::kGoogleRed700); } - if (icon_str == base::ASCIIToUTF16("showAllSavedPasswords")) { - return gfx::CreateVectorIcon(kOpenInNewIcon, kIconSize, - gfx::kChromeIconGrey); - } - // For other suggestion entries, get icon from PNG files. int icon_id = GetIconResourceID(icon_str); DCHECK_NE(-1, icon_id);
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc index 0610283d..568e9fb 100644 --- a/chrome/browser/ui/browser_browsertest.cc +++ b/chrome/browser/ui/browser_browsertest.cc
@@ -2035,7 +2035,14 @@ } #endif -IN_PROC_BROWSER_TEST_F(BrowserTest, WindowOpenClose) { +// Disabled due to flaky timeout on Win7 Tests (dbg): https://crbug.com/753691. +#if defined(OS_WIN) && !defined(NDEBUG) +#define MAYBE_WindowOpenClose DISABLED_WindowOpenClose +#else +#define MAYBE_WindowOpenClose WindowOpenClose +#endif + +IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_WindowOpenClose) { base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kDisablePopupBlocking); GURL url = ui_test_utils::GetTestUrl(
diff --git a/chrome/browser/ui/cocoa/bubble_anchor_helper_views.h b/chrome/browser/ui/cocoa/bubble_anchor_helper_views.h index 41f73bc..fec4f20a 100644 --- a/chrome/browser/ui/cocoa/bubble_anchor_helper_views.h +++ b/chrome/browser/ui/cocoa/bubble_anchor_helper_views.h
@@ -26,4 +26,9 @@ void KeepBubbleAnchored(views::BubbleDialogDelegateView* bubble, LocationBarDecoration* decoration = nullptr); +// Simplified version of KeepBubbleAnchored() for bubbles that manage their own +// anchoring. Causes |decoration| to be set active until |bubble| is closed. +void TrackBubbleState(views::BubbleDialogDelegateView* bubble, + LocationBarDecoration* decoration); + #endif // CHROME_BROWSER_UI_COCOA_BUBBLE_ANCHOR_HELPER_VIEWS_H_
diff --git a/chrome/browser/ui/cocoa/bubble_anchor_helper_views.mm b/chrome/browser/ui/cocoa/bubble_anchor_helper_views.mm index b666e65b..b071a9f 100644 --- a/chrome/browser/ui/cocoa/bubble_anchor_helper_views.mm +++ b/chrome/browser/ui/cocoa/bubble_anchor_helper_views.mm
@@ -16,13 +16,17 @@ namespace { +// Whether frame changes on the parent window are observed or ignored. +enum AnchorType { OBSERVE_PARENT, IGNORE_PARENT }; + // Self-deleting object that hosts Objective-C observers watching for parent // window resizes to reposition a bubble Widget. Deletes itself when the bubble // Widget closes. class BubbleAnchorHelper : public views::WidgetObserver { public: BubbleAnchorHelper(views::BubbleDialogDelegateView* bubble, - LocationBarDecoration* decoration); + LocationBarDecoration* decoration, + AnchorType type); private: // Observe |name| on the bubble parent window with a block to call ReAnchor(). @@ -71,11 +75,17 @@ void KeepBubbleAnchored(views::BubbleDialogDelegateView* bubble, LocationBarDecoration* decoration) { - new BubbleAnchorHelper(bubble, decoration); + new BubbleAnchorHelper(bubble, decoration, OBSERVE_PARENT); +} + +void TrackBubbleState(views::BubbleDialogDelegateView* bubble, + LocationBarDecoration* decoration) { + new BubbleAnchorHelper(bubble, decoration, IGNORE_PARENT); } BubbleAnchorHelper::BubbleAnchorHelper(views::BubbleDialogDelegateView* bubble, - LocationBarDecoration* decoration) + LocationBarDecoration* decoration, + AnchorType type) : observer_tokens_([[NSMutableArray alloc] init]), bubble_(bubble), decoration_(decoration) { @@ -86,6 +96,9 @@ if (decoration_) decoration_->SetActive(true); + if (type == IGNORE_PARENT) + return; + NSRect parent_frame = [[bubble->parent_window() window] frame]; NSRect bubble_frame = [bubble->GetWidget()->GetNativeWindow() frame];
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h b/chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h index 56a202d..0f7610f 100644 --- a/chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h +++ b/chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h
@@ -18,6 +18,10 @@ struct VectorIcon; } +namespace test { +class LocationBarDecorationTestApi; +} + // Base class for decorations at the left and right of the location // bar. For instance, the location icon. @@ -190,6 +194,8 @@ CGFloat alpha) const; private: + friend class test::LocationBarDecorationTestApi; + // Called when the state of the decoration is updated. void UpdateDecorationState();
diff --git a/chrome/browser/ui/cocoa/permission_bubble/permission_bubble_cocoa_interactive_uitest.mm b/chrome/browser/ui/cocoa/permission_bubble/permission_bubble_cocoa_interactive_uitest.mm index 856036f..489fdd63 100644 --- a/chrome/browser/ui/cocoa/permission_bubble/permission_bubble_cocoa_interactive_uitest.mm +++ b/chrome/browser/ui/cocoa/permission_bubble/permission_bubble_cocoa_interactive_uitest.mm
@@ -11,6 +11,8 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/cocoa/bubble_anchor_helper_views.h" +#import "chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/interactive_test_utils.h" @@ -32,6 +34,25 @@ } // namespace +namespace test { + +// Test API for LocationBarDecoration. This can be moved to its own file if +// another test needs it. +class LocationBarDecorationTestApi { + public: + explicit LocationBarDecorationTestApi(LocationBarDecoration* decoration) + : decoration_(decoration) {} + + bool active() const { return decoration_->active_; } + + private: + LocationBarDecoration* decoration_; + + DISALLOW_COPY_AND_ASSIGN(LocationBarDecorationTestApi); +}; + +} // namespace test + class PermissionBubbleInteractiveUITest : public InProcessBrowserTest, public ::testing::WithParamInterface<UiMode> { @@ -52,6 +73,10 @@ [waiter wait]; } EXPECT_TRUE([window isKeyWindow]); + + // Whether or not we had to wait, flush the run loop. This ensures any + // asynchronous close operations have completed. + base::RunLoop().RunUntilIdle(); } // Send Cmd+keycode in the key window to NSApp. @@ -78,10 +103,14 @@ base::MakeUnique<test::PermissionRequestManagerTestApi>(browser()); EXPECT_TRUE(test_api_->manager()); + decoration_test_api_ = base::MakeUnique<test::LocationBarDecorationTestApi>( + GetPageInfoDecoration(browser()->window()->GetNativeWindow())); + test_api_->AddSimpleRequest(browser()->profile(), CONTENT_SETTINGS_TYPE_GEOLOCATION); EXPECT_TRUE([browser()->window()->GetNativeWindow() isKeyWindow]); + EXPECT_FALSE(decoration_test_api_->active()); test_api_->manager()->DisplayPendingRequests(); // The bubble should steal key focus when shown. @@ -90,6 +119,7 @@ protected: std::unique_ptr<test::PermissionRequestManagerTestApi> test_api_; + std::unique_ptr<test::LocationBarDecorationTestApi> decoration_test_api_; private: DISALLOW_COPY_AND_ASSIGN(PermissionBubbleInteractiveUITest); @@ -119,6 +149,7 @@ EXPECT_EQ(0, browser()->tab_strip_model()->active_index()); EXPECT_TRUE(test_api_->GetPromptWindow()); + EXPECT_TRUE(decoration_test_api_->active()); // Add a blank tab in the foreground. AddBlankTabAndShow(browser()); @@ -133,6 +164,7 @@ // Prompt is hidden while its tab is not active. EXPECT_FALSE(test_api_->GetPromptWindow()); + EXPECT_FALSE(decoration_test_api_->active()); // Now a webcontents is active, it gets a first shot at processing the // accelerator before sending it back unhandled to the browser via IPC. That's @@ -146,6 +178,7 @@ EnsureWindowActive(test_api_->GetPromptWindow(), "switched to permission tab with arrow"); EXPECT_TRUE(test_api_->GetPromptWindow()); + EXPECT_TRUE(decoration_test_api_->active()); // Ensure we can switch away with the bubble active. SendAccelerator(ui::VKEY_RIGHT, false, true); @@ -154,6 +187,7 @@ [browser_window makeKeyAndOrderFront:nil]; EnsureWindowActive(browser_window, "switch away with arrow"); EXPECT_FALSE(test_api_->GetPromptWindow()); + EXPECT_FALSE(decoration_test_api_->active()); // Also test switching tabs with curly braces. "VKEY_OEM_4" is // LeftBracket/Brace on a US keyboard, which ui::MacKeyCodeForWindowsKeyCode @@ -165,12 +199,14 @@ EnsureWindowActive(test_api_->GetPromptWindow(), "switch to permission tab with curly brace"); EXPECT_TRUE(test_api_->GetPromptWindow()); + EXPECT_TRUE(decoration_test_api_->active()); SendAccelerator(ui::VKEY_OEM_4, true, false); EXPECT_EQ(1, browser()->tab_strip_model()->active_index()); [browser_window makeKeyAndOrderFront:nil]; EnsureWindowActive(browser_window, "switch away with curly brace"); EXPECT_FALSE(test_api_->GetPromptWindow()); + EXPECT_FALSE(decoration_test_api_->active()); } INSTANTIATE_TEST_CASE_P(,
diff --git a/chrome/browser/ui/cocoa/permission_bubble/permission_prompt_impl_views_mac.mm b/chrome/browser/ui/cocoa/permission_bubble/permission_prompt_impl_views_mac.mm index 3c4f250..211bf9fa 100644 --- a/chrome/browser/ui/cocoa/permission_bubble/permission_prompt_impl_views_mac.mm +++ b/chrome/browser/ui/cocoa/permission_bubble/permission_prompt_impl_views_mac.mm
@@ -5,9 +5,12 @@ #include "base/feature_list.h" #include "base/memory/ptr_util.h" #include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/cocoa/bubble_anchor_helper_views.h" #import "chrome/browser/ui/cocoa/permission_bubble/permission_bubble_cocoa.h" #include "chrome/browser/ui/views/permission_bubble/permission_prompt_impl.h" #include "ui/base/material_design/material_design_controller.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_delegate.h" namespace { @@ -19,6 +22,12 @@ !base::FeatureList::IsEnabled(kCocoaPermissionBubbles); } +views::BubbleDialogDelegateView* BubbleForWindow(gfx::NativeWindow window) { + views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window); + DCHECK(widget); + return widget->widget_delegate()->AsBubbleDialogDelegate(); +} + } // namespace // static @@ -26,7 +35,14 @@ content::WebContents* web_contents, Delegate* delegate) { Browser* browser = chrome::FindBrowserWithWebContents(web_contents); - if (UseViewsBubbles()) - return base::MakeUnique<PermissionPromptImpl>(browser, delegate); + if (UseViewsBubbles()) { + auto prompt = base::MakeUnique<PermissionPromptImpl>(browser, delegate); + // Note the PermissionPromptImpl constructor always shows the bubble, which + // is necessary to call TrackBubbleState(). + TrackBubbleState( + BubbleForWindow(prompt->GetNativeWindow()), + GetPageInfoDecoration(web_contents->GetTopLevelNativeWindow())); + return prompt; + } return base::MakeUnique<PermissionBubbleCocoa>(browser, delegate); }
diff --git a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm index bbda2a6..e66020a 100644 --- a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm +++ b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm
@@ -339,7 +339,9 @@ } void RenderViewContextMenuMac::InitToolkitMenu() { - if (params_.selection_text.empty()) + if (params_.selection_text.empty() || + params_.input_field_type == + blink::WebContextMenuData::kInputFieldTypePassword) return; if (params_.link_url.is_empty()) {
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc index 48fcac1c..f5547de 100644 --- a/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc +++ b/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc
@@ -151,11 +151,8 @@ controller_->GetBackgroundColorIDForRow(index))); const int frontend_id = controller_->GetSuggestionAt(index).frontend_id; - const bool is_http_warning = - (frontend_id == POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE); const bool icon_in_front_of_text = - (is_http_warning || - frontend_id == POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY); + (frontend_id == POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE); const bool is_rtl = controller_->IsRTL(); const int text_align = is_rtl ? gfx::Canvas::TEXT_ALIGN_RIGHT : gfx::Canvas::TEXT_ALIGN_LEFT; @@ -222,7 +219,7 @@ controller_->layout_model().GetLabelFontListForRow(index)); int label_x_align_left = x_align_left; - if (is_http_warning) { + if (icon_in_front_of_text) { label_x_align_left = is_rtl ? value_rect.x() : value_rect.right() - label_width; } else {
diff --git a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc index 3390057..88ea614d 100644 --- a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc +++ b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc
@@ -18,6 +18,7 @@ #include "components/ui_devtools/devtools_server.h" #include "components/ui_devtools/views/ui_devtools_css_agent.h" #include "components/ui_devtools/views/ui_devtools_dom_agent.h" +#include "components/ui_devtools/views/ui_devtools_overlay_agent.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/service_manager_connection.h" #include "services/service_manager/public/cpp/connector.h" @@ -111,12 +112,16 @@ devtools_server_ = ui_devtools::UiDevToolsServer::Create(nullptr); if (devtools_server_) { auto dom_backend = base::MakeUnique<ui_devtools::UIDevToolsDOMAgent>(); + auto overlay_backend = + base::MakeUnique<ui_devtools::UIDevToolsOverlayAgent>( + dom_backend.get()); auto css_backend = base::MakeUnique<ui_devtools::UIDevToolsCSSAgent>(dom_backend.get()); auto devtools_client = base::MakeUnique<ui_devtools::UiDevToolsClient>( "UiDevToolsClient", devtools_server_.get()); devtools_client->AddAgent(std::move(dom_backend)); devtools_client->AddAgent(std::move(css_backend)); + devtools_client->AddAgent(std::move(overlay_backend)); devtools_server_->AttachClient(std::move(devtools_client)); } #endif
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index a872796..4f3b730 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1141,6 +1141,8 @@ return false; if (!bookmark_bar_view_.get()) return false; + if (!bookmark_bar_view_->parent()) + return false; if (bookmark_bar_view_->GetPreferredSize().height() == 0) return false; // New tab page needs visible bookmarks even when top-views are hidden. @@ -2197,9 +2199,9 @@ } bool BrowserView::MaybeShowBookmarkBar(WebContents* contents) { - bool show_bookmark_bar = - browser_->SupportsWindowFeature(Browser::FEATURE_BOOKMARKBAR); - if ((!show_bookmark_bar || !contents) && !bookmark_bar_view_.get()) + const bool show_bookmark_bar = + contents && browser_->SupportsWindowFeature(Browser::FEATURE_BOOKMARKBAR); + if (!show_bookmark_bar && !bookmark_bar_view_.get()) return false; if (!bookmark_bar_view_.get()) { bookmark_bar_view_.reset(new BookmarkBarView(browser_.get(), this));
diff --git a/chrome/browser/ui/views/frame/browser_view_unittest.cc b/chrome/browser/ui/views/frame/browser_view_unittest.cc index 7ca7b09d..10918a9 100644 --- a/chrome/browser/ui/views/frame/browser_view_unittest.cc +++ b/chrome/browser/ui/views/frame/browser_view_unittest.cc
@@ -183,10 +183,8 @@ EXPECT_TRUE(browser_view()->AcceleratorPressed(kNextTabRepeatAccel)); } -// Test that the bookmark bar view's parent is not set to nullptr when closing -// the browser. If the parent is set to nullptr, then the bookmark bar -// disappears before the browser is closed, which looks weird. -TEST_F(BrowserViewTest, BookmarkBarParentIsNotNullOnShutdown) { +// Test that bookmark bar view becomes invisible when closing the browser. +TEST_F(BrowserViewTest, BookmarkBarInvisibleOnShutdown) { BookmarkBarView::DisableAnimationsForTesting(true); Browser* browser = browser_view()->browser(); @@ -198,11 +196,11 @@ BookmarkBarView* bookmark_bar = browser_view()->GetBookmarkBarView(); chrome::ExecuteCommand(browser, IDC_SHOW_BOOKMARK_BAR); - EXPECT_NE(nullptr, bookmark_bar->parent()); + EXPECT_TRUE(bookmark_bar->visible()); tab_strip_model->CloseWebContentsAt(tab_strip_model->active_index(), 0); EXPECT_EQ(0, tab_strip_model->count()); - EXPECT_NE(nullptr, bookmark_bar->parent()); + EXPECT_FALSE(bookmark_bar->visible()); BookmarkBarView::DisableAnimationsForTesting(false); }
diff --git a/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc b/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc index d3a753b8..130d388 100644 --- a/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc +++ b/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc
@@ -73,6 +73,7 @@ // BubbleDialogDelegateView: ui::AXRole GetAccessibleWindowRole() const override; + base::string16 GetAccessibleWindowTitle() const override; bool ShouldShowCloseButton() const override; base::string16 GetWindowTitle() const override; void AddedToWidget() override; @@ -173,6 +174,12 @@ return ui::AX_ROLE_ALERT_DIALOG; } +base::string16 PermissionsBubbleDialogDelegateView::GetAccessibleWindowTitle() + const { + return l10n_util::GetStringFUTF16(IDS_PERMISSIONS_BUBBLE_ACCESSIBLE_TITLE, + display_origin_); +} + bool PermissionsBubbleDialogDelegateView::ShouldShowCloseButton() const { return true; }
diff --git a/chrome/browser/ui/views/tabs/new_tab_button.cc b/chrome/browser/ui/views/tabs/new_tab_button.cc index 2ab290e..2b8de108 100644 --- a/chrome/browser/ui/views/tabs/new_tab_button.cc +++ b/chrome/browser/ui/views/tabs/new_tab_button.cc
@@ -6,9 +6,11 @@ #include "build/build_config.h" #include "chrome/browser/themes/theme_properties.h" +#include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/views/feature_promos/new_tab_promo_bubble_view.h" #include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h" +#include "chrome/browser/ui/views/tabs/tab_strip.h" #include "third_party/skia/include/core/SkColorFilter.h" #include "third_party/skia/include/effects/SkBlurMaskFilter.h" #include "third_party/skia/include/effects/SkLayerDrawLooper.h" @@ -77,11 +79,18 @@ GetLayoutSize(NEW_TAB_BUTTON).height(); } +// static +void NewTabButton::ShowPromoForLastActiveBrowser() { + BrowserView* browser = static_cast<BrowserView*>( + BrowserList::GetInstance()->GetLastActive()->window()); + browser->tabstrip()->new_tab_button()->ShowPromo(); +} + void NewTabButton::ShowPromo() { // Owned by its native widget. Will be destroyed as its widget is destroyed. new_tab_promo_ = NewTabPromoBubbleView::CreateOwned(GetVisibleBounds()); new_tab_promo_observer_.Add(new_tab_promo_->GetWidget()); - NewTabButton::SchedulePaint(); + SchedulePaint(); } #if defined(OS_WIN) @@ -188,7 +197,7 @@ #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && !defined(OS_MACOSX) feature_engagement::NewTabTrackerFactory::GetInstance() ->GetForProfile(tab_strip_->controller()->GetProfile()) - ->DismissNewTabTracker(); + ->OnPromoClosed(); #endif new_tab_promo_observer_.Remove(widget); // When the promo widget is destroyed, the NewTabButton needs to be
diff --git a/chrome/browser/ui/views/tabs/new_tab_button.h b/chrome/browser/ui/views/tabs/new_tab_button.h index 2c41031..a88275f 100644 --- a/chrome/browser/ui/views/tabs/new_tab_button.h +++ b/chrome/browser/ui/views/tabs/new_tab_button.h
@@ -38,6 +38,9 @@ // button's visible region begins. static int GetTopOffset(); + // Retrieves the last active BrowserView instance to display the NewTabPromo. + static void ShowPromoForLastActiveBrowser(); + // Shows the NewTabPromo when the NewTabFeatureEngagementTracker calls for it. void ShowPromo();
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc index e6153b96..810cc0b 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -53,6 +53,7 @@ #include "google_apis/gaia/gaia_urls.h" #include "ui/base/ime/chromeos/input_method_manager.h" #include "ui/base/ime/chromeos/input_method_util.h" +#include "ui/base/l10n/l10n_util.h" using content::BrowserThread; namespace em = enterprise_management; @@ -572,6 +573,9 @@ const Key& key, authpolicy::ErrorType error, const authpolicy::ActiveDirectoryAccountInfo& account_info) { + if (error != authpolicy::ERROR_NONE) + authpolicy_login_helper_->CancelRequestsAndRestart(); + switch (error) { case authpolicy::ERROR_NONE: { DCHECK(account_info.has_account_id() && @@ -596,29 +600,17 @@ case authpolicy::ERROR_BAD_USER_NAME: CallJS("invalidateAd", username, static_cast<int>(ActiveDirectoryErrorState::BAD_USERNAME)); - return; + break; case authpolicy::ERROR_BAD_PASSWORD: CallJS("invalidateAd", username, static_cast<int>(ActiveDirectoryErrorState::BAD_PASSWORD)); - case authpolicy::ERROR_UNKNOWN: - case authpolicy::ERROR_DBUS_FAILURE: - case authpolicy::ERROR_CANNOT_RESOLVE_KDC: - case authpolicy::ERROR_KINIT_FAILED: - case authpolicy::ERROR_NET_FAILED: - case authpolicy::ERROR_SMBCLIENT_FAILED: - case authpolicy::ERROR_PARSE_FAILED: - case authpolicy::ERROR_PARSE_PREG_FAILED: - case authpolicy::ERROR_BAD_GPOS: - case authpolicy::ERROR_LOCAL_IO: - case authpolicy::ERROR_NOT_JOINED: - case authpolicy::ERROR_NOT_LOGGED_IN: - case authpolicy::ERROR_STORE_POLICY_FAILED: - LoadAuthExtension(true, false /* offline */); break; default: - // TODO(rsorokin): Proper error handling. DLOG(WARNING) << "Unhandled error code: " << error; LoadAuthExtension(true, false /* offline */); + core_oobe_view_->ShowSignInError( + 0, l10n_util::GetStringUTF8(IDS_AD_AUTH_UNKNOWN_ERROR), std::string(), + HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT); } }
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc index 54067f9..009d70ab 100644 --- a/chrome/browser/ui/webui/extensions/extensions_ui.cc +++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -260,10 +260,6 @@ GURL(extension_urls::GetWebstoreExtensionsCategoryURL()), g_browser_process->GetApplicationLocale()).spec())); - source->AddResourcePath("animation_helper.html", - IDR_MD_EXTENSIONS_ANIMATION_HELPER_HTML); - source->AddResourcePath("animation_helper.js", - IDR_MD_EXTENSIONS_ANIMATION_HELPER_JS); source->AddResourcePath("code_section.html", IDR_MD_EXTENSIONS_CODE_SECTION_HTML); source->AddResourcePath("code_section.js", IDR_MD_EXTENSIONS_CODE_SECTION_JS); @@ -324,6 +320,9 @@ source->AddResourcePath("strings.html", IDR_MD_EXTENSIONS_STRINGS_HTML); source->AddResourcePath("toolbar.html", IDR_MD_EXTENSIONS_TOOLBAR_HTML); source->AddResourcePath("toolbar.js", IDR_MD_EXTENSIONS_TOOLBAR_JS); + source->AddResourcePath("view_manager.html", + IDR_MD_EXTENSIONS_VIEW_MANAGER_HTML); + source->AddResourcePath("view_manager.js", IDR_MD_EXTENSIONS_VIEW_MANAGER_JS); source->SetDefaultResource(IDR_MD_EXTENSIONS_EXTENSIONS_HTML); return source;
diff --git a/chrome/browser/ui/webui/md_downloads/md_downloads_ui.cc b/chrome/browser/ui/webui/md_downloads/md_downloads_ui.cc index f2da6b7..702887c 100644 --- a/chrome/browser/ui/webui/md_downloads/md_downloads_ui.cc +++ b/chrome/browser/ui/webui/md_downloads/md_downloads_ui.cc
@@ -118,6 +118,10 @@ IDR_MD_DOWNLOADS_ACTION_SERVICE_HTML); source->AddResourcePath("action_service.js", IDR_MD_DOWNLOADS_ACTION_SERVICE_JS); + source->AddResourcePath("browser_proxy.html", + IDR_MD_DOWNLOADS_BROWSER_PROXY_HTML); + source->AddResourcePath("browser_proxy.js", + IDR_MD_DOWNLOADS_BROWSER_PROXY_JS); source->AddResourcePath("constants.html", IDR_MD_DOWNLOADS_CONSTANTS_HTML); source->AddResourcePath("constants.js", IDR_MD_DOWNLOADS_CONSTANTS_JS); source->AddResourcePath("downloads.js", IDR_MD_DOWNLOADS_DOWNLOADS_JS);
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc index 075351a..2dd152a5 100644 --- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -336,6 +336,8 @@ const std::string& model, const std::string& make_and_model, bool ipp_everywhere) { + UMA_HISTOGRAM_BOOLEAN("Printing.CUPS.IppAttributesSuccess", success); + if (!success) { base::DictionaryValue reject; reject.SetString("message", "Querying printer failed");
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index fa93e71..792243a4 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -1909,6 +1909,7 @@ IDS_SETTINGS_SITE_SETTINGS_BLOCK_DEFAULT_MENU}, {"siteSettingsActionAllow", IDS_SETTINGS_SITE_SETTINGS_ALLOW_MENU}, {"siteSettingsActionBlock", IDS_SETTINGS_SITE_SETTINGS_BLOCK_MENU}, + {"siteSettingsActionAsk", IDS_SETTINGS_SITE_SETTINGS_ASK_MENU}, {"siteSettingsActionReset", IDS_SETTINGS_SITE_SETTINGS_RESET_MENU}, {"siteSettingsActionSessionOnly", IDS_SETTINGS_SITE_SETTINGS_SESSION_ONLY_MENU},
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.cc b/chrome/browser/ui/webui/settings/site_settings_handler.cc index d66cebd..338a20e 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler.cc +++ b/chrome/browser/ui/webui/settings/site_settings_handler.cc
@@ -19,6 +19,7 @@ #include "chrome/browser/content_settings/web_site_settings_uma_util.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/permissions/chooser_context_base.h" +#include "chrome/browser/permissions/permission_decision_auto_blocker.h" #include "chrome/browser/permissions/permission_uma_util.h" #include "chrome/browser/permissions/permission_util.h" #include "chrome/browser/profiles/profile.h" @@ -536,6 +537,12 @@ PermissionUtil::ScopedRevocationReporter scoped_revocation_reporter( profile_, origin, origin, content_type, PermissionSourceUI::SITE_SETTINGS); + + // Clear any existing embargo status if the new setting isn't block. + if (setting != CONTENT_SETTING_BLOCK) { + PermissionDecisionAutoBlocker::GetForProfile(profile_) + ->RemoveEmbargoByUrl(origin, content_type); + } map->SetContentSettingDefaultScope(origin, origin, content_type, std::string(), setting); WebSiteSettingsUmaUtil::LogPermissionChange(content_type, setting);
diff --git a/chrome/browser/vr/color_scheme.cc b/chrome/browser/vr/color_scheme.cc index 577a688..a1372e4 100644 --- a/chrome/browser/vr/color_scheme.cc +++ b/chrome/browser/vr/color_scheme.cc
@@ -59,9 +59,9 @@ normal_scheme.prompt_button_background_down = 0xE6FFFFFF; normal_scheme.secure = gfx::kGoogleGreen700; normal_scheme.insecure = gfx::kGoogleRed700; - normal_scheme.warning = 0xFF5A5A5A; normal_scheme.url_emphasized = SK_ColorBLACK; - normal_scheme.url_deemphasized = normal_scheme.warning; + normal_scheme.url_deemphasized = 0xFF5A5A5A; + normal_scheme.offline_page_warning = 0xFF242424; normal_scheme.disabled = 0x33333333; normal_scheme.dimmer_inner = 0xCC0D0D0D; normal_scheme.dimmer_outer = 0xE6000000; @@ -87,6 +87,8 @@ fullscreen_scheme.close_button_background_down = fullscreen_scheme.element_background_down; + kColorSchemes[ColorScheme::kModeIncognito] = + kColorSchemes[ColorScheme::kModeNormal]; ColorScheme& incognito_scheme = kColorSchemes[ColorScheme::kModeIncognito]; incognito_scheme.world_background = 0xFF2E2E2E; incognito_scheme.floor = 0xFF282828; @@ -107,9 +109,9 @@ incognito_scheme.separator = 0xFF474747; incognito_scheme.secure = 0xFFEDEDED; incognito_scheme.insecure = incognito_scheme.secure; - incognito_scheme.warning = incognito_scheme.secure; incognito_scheme.url_emphasized = incognito_scheme.secure; incognito_scheme.url_deemphasized = 0xFF878787; + incognito_scheme.offline_page_warning = incognito_scheme.secure; incognito_scheme.prompt_foreground = 0xCCFFFFFF; incognito_scheme.prompt_primary_button_forground = 0xD9000000; incognito_scheme.prompt_secondary_button_foreground = 0xD9000000;
diff --git a/chrome/browser/vr/color_scheme.h b/chrome/browser/vr/color_scheme.h index afafcba..3d1dc84 100644 --- a/chrome/browser/vr/color_scheme.h +++ b/chrome/browser/vr/color_scheme.h
@@ -68,9 +68,9 @@ // should respect these colors. SkColor secure; SkColor insecure; - SkColor warning; SkColor url_emphasized; SkColor url_deemphasized; + SkColor offline_page_warning; // The color used for disabled icons. SkColor disabled;
diff --git a/chrome/browser/vr/elements/url_bar_texture.cc b/chrome/browser/vr/elements/url_bar_texture.cc index bbe11d6..949e4e1 100644 --- a/chrome/browser/vr/elements/url_bar_texture.cc +++ b/chrome/browser/vr/elements/url_bar_texture.cc
@@ -61,7 +61,7 @@ SkColor GetSecurityChipColor(SecurityLevel level, bool offline_page, const ColorScheme& color_scheme) { - return offline_page ? color_scheme.url_emphasized + return offline_page ? color_scheme.offline_page_warning : GetSchemeColor(level, color_scheme); }
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 727a7488..c9c3d0c 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -371,7 +371,7 @@ // Enables or disables UI in MD Settings to view content settings grouped by // origin. const base::Feature kSiteDetails{"SiteDetails", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; #if !defined(OS_ANDROID) // Enables delaying the navigation of background tabs in order to improve
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index ac982b62..7427f13c 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -2159,30 +2159,12 @@ #endif // !defined(OS_ANDROID) #if defined(OS_CHROMEOS) -// |kShelfAlignment| and |kShelfAutoHideBehavior| have a local variant. The -// local variant is not synced and is used if set. If the local variant is not -// set its value is set from the synced value (once prefs have been -// synced). This gives a per-machine setting that is initialized from the last -// set value. -// These values are default on the machine but can be overridden by per-display -// values in kShelfPreferences (unless overridden by managed policy). -// String value corresponding to ash::Shell::ShelfAlignment. -const char kShelfAlignment[] = "shelf_alignment"; -const char kShelfAlignmentLocal[] = "shelf_alignment_local"; -// String value corresponding to ash::Shell::ShelfAutoHideBehavior. -const char kShelfAutoHideBehavior[] = "auto_hide_behavior"; -const char kShelfAutoHideBehaviorLocal[] = "auto_hide_behavior_local"; // This value stores chrome icon's index in the launcher. This should be handled // separately with app shortcut's index because of ShelfModel's backward // compatibility. If we add chrome icon index to |kPinnedLauncherApps|, its // index is also stored in the |kPinnedLauncherApp| pref. It may causes // creating two chrome icons. const char kShelfChromeIconIndex[] = "shelf_chrome_icon_index"; -// Dictionary value that holds per-display preference of shelf alignment and -// auto-hide behavior. Key of the dictionary is the id of the display, and -// its value is a dictionary whose keys are kShelfAlignment and -// kShelfAutoHideBehavior. -const char kShelfPreferences[] = "shelf_preferences"; const char kPinnedLauncherApps[] = "pinned_launcher_apps"; const char kPolicyPinnedLauncherApps[] = "policy_pinned_launcher_apps";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 949e686..2e5464a7 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -773,13 +773,7 @@ #endif // !defined(OS_ANDROID) #if defined(OS_CHROMEOS) -extern const char kShelfAlignment[]; -extern const char kShelfAlignmentLocal[]; -extern const char kShelfAutoHideBehavior[]; -extern const char kShelfAutoHideBehaviorLocal[]; extern const char kShelfChromeIconIndex[]; -extern const char kShelfPreferences[]; - extern const char kPinnedLauncherApps[]; extern const char kPolicyPinnedLauncherApps[]; #endif // defined(OS_CHROMEOS)
diff --git a/chrome/installer/linux/debian/build.sh b/chrome/installer/linux/debian/build.sh index 4c4979f..28bf2d8 100755 --- a/chrome/installer/linux/debian/build.sh +++ b/chrome/installer/linux/debian/build.sh
@@ -88,6 +88,22 @@ chmod 755 "${STAGEDIR}/DEBIAN/postrm" } +verify_package() { + local DEPENDS="$1" + echo ${DEPENDS} | sed 's/, /\n/g' | LANG=C sort > expected_deb_depends + dpkg -I "${PACKAGE}-${CHANNEL}_${VERSIONFULL}_${ARCHITECTURE}.deb" | \ + grep '^ Depends: ' | sed 's/^ Depends: //' | sed 's/, /\n/g' | \ + LANG=C sort > actual_deb_depends + BAD_DIFF=0 + diff -u expected_deb_depends actual_deb_depends || BAD_DIFF=1 + if [ $BAD_DIFF -ne 0 ] && [ -z "${IGNORE_DEPS_CHANGES:-}" ]; then + echo + echo "ERROR: bad dpkg dependencies!" + echo + exit $BAD_DIFF + fi +} + # Actually generate the package file. do_package() { echo "Packaging ${ARCHITECTURE}..." @@ -103,22 +119,7 @@ gen_control fi fakeroot dpkg-deb -Zxz -z9 -b "${STAGEDIR}" . -} - -verify_package() { - DEPENDS="${COMMON_DEPS}" # This needs to match do_package() above. - echo ${DEPENDS} | sed 's/, /\n/g' | LANG=C sort > expected_deb_depends - dpkg -I "${PACKAGE}-${CHANNEL}_${VERSIONFULL}_${ARCHITECTURE}.deb" | \ - grep '^ Depends: ' | sed 's/^ Depends: //' | sed 's/, /\n/g' | \ - LANG=C sort > actual_deb_depends - BAD_DIFF=0 - diff -u expected_deb_depends actual_deb_depends || BAD_DIFF=1 - if [ $BAD_DIFF -ne 0 ] && [ -z "${IGNORE_DEPS_CHANGES:-}" ]; then - echo - echo "ERROR: bad dpkg dependencies!" - echo - exit $BAD_DIFF - fi + verify_package "$DEPENDS" } # Remove temporary files and unwanted packaging output. @@ -356,4 +357,3 @@ stage_install_debian do_package -verify_package
diff --git a/chrome/installer/linux/rpm/build.sh b/chrome/installer/linux/rpm/build.sh index 1f1b645..59875c1 100755 --- a/chrome/installer/linux/rpm/build.sh +++ b/chrome/installer/linux/rpm/build.sh
@@ -54,6 +54,27 @@ chmod 755 "${STAGEDIR}/etc/cron.daily/${PACKAGE}" } +verify_package() { + local DEPENDS="$1" + local ADDITIONAL_RPM_DEPENDS="/bin/sh, \ + rpmlib(CompressedFileNames) <= 3.0.4-1, \ + rpmlib(PayloadFilesHavePrefix) <= 4.0-1, \ + rpmlib(PayloadIsXz) <= 5.2-1, \ + /usr/sbin/update-alternatives" + echo "${DEPENDS}" "${ADDITIONAL_RPM_DEPENDS}" | sed 's/,/\n/g' | \ + sed 's/^ *//' | LANG=C sort > expected_rpm_depends + rpm -qpR "${OUTPUTDIR}/${PKGNAME}.${ARCHITECTURE}.rpm" | LANG=C sort | uniq \ + > actual_rpm_depends + BAD_DIFF=0 + diff -u expected_rpm_depends actual_rpm_depends || BAD_DIFF=1 + if [ $BAD_DIFF -ne 0 ] && [ -z "${IGNORE_DEPS_CHANGES:-}" ]; then + echo + echo "ERROR: bad rpm dependencies!" + echo + exit $BAD_DIFF + fi +} + # Actually generate the package file. do_package() { echo "Packaging ${ARCHITECTURE}..." @@ -176,8 +197,10 @@ "${OUTPUTDIR}" # Make sure the package is world-readable, otherwise it causes problems when # copied to share drive. - chmod a+r "${OUTPUTDIR}/${PKGNAME}.$ARCHITECTURE.rpm" + chmod a+r "${OUTPUTDIR}/${PKGNAME}.${ARCHITECTURE}.rpm" rm -rf "$RPMBUILD_DIR" + + verify_package "$DEPENDS" } # Remove temporary files and unwanted packaging output.
diff --git a/chrome/installer/zucchini/BUILD.gn b/chrome/installer/zucchini/BUILD.gn index 7b669a0..008406c3 100644 --- a/chrome/installer/zucchini/BUILD.gn +++ b/chrome/installer/zucchini/BUILD.gn
@@ -38,6 +38,7 @@ "rel32_utils.cc", "rel32_utils.h", "suffix_array.h", + "type_win_pe.h", "typed_value.h", "zucchini.h", ]
diff --git a/chrome/installer/zucchini/type_win_pe.h b/chrome/installer/zucchini/type_win_pe.h new file mode 100644 index 0000000..c6875075 --- /dev/null +++ b/chrome/installer/zucchini/type_win_pe.h
@@ -0,0 +1,170 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_INSTALLER_ZUCCHINI_TYPE_WIN_PE_H_ +#define CHROME_INSTALLER_ZUCCHINI_TYPE_WIN_PE_H_ + +#include <stddef.h> +#include <stdint.h> + +namespace zucchini { + +// Structures and constants taken from WINNT.h and following identical layout. +// This is used for parsing of Portable Executable (PE) file format. +namespace pe { +// Supported by MSVC, g++, and clang++. Ensures no gaps in packing. +#pragma pack(push, 1) + +// IMAGE_NUMBEROF_DIRECTORY_ENTRIES +constexpr size_t kImageNumberOfDirectoryEntries = 16; + +// IMAGE_FILE_BASE_RELOCATION_TABLE +constexpr size_t kIndexOfBaseRelocationTable = 5; + +constexpr uint32_t kImageScnMemExecute = 0x20000000; // IMAGE_SCN_MEM_EXECUTE +constexpr uint32_t kImageScnMemRead = 0x40000000; // IMAGE_SCN_MEM_READ + +// IMAGE_DOS_HEADER +struct ImageDOSHeader { + uint16_t e_magic; // 0x00 + uint16_t e_cblp; + uint16_t e_cp; + uint16_t e_crlc; + uint16_t e_cparhdr; + uint16_t e_minalloc; + uint16_t e_maxalloc; + uint16_t e_ss; + uint16_t e_sp; // 0x10 + uint16_t e_csum; + uint16_t e_ip; + uint16_t e_cs; + uint16_t e_lfarlc; + uint16_t e_ovno; + uint16_t e_res[4]; + uint16_t e_oemid; // 0x24 + uint16_t e_oeminfo; + uint16_t e_res2[10]; + uint32_t e_lfanew; // 0x3c +}; + +// IMAGE_SECTION_HEADER +struct ImageSectionHeader { + char name[8]; + uint32_t virtual_size; + uint32_t virtual_address; + uint32_t size_of_raw_data; + uint32_t file_offset_of_raw_data; + uint32_t pointer_to_relocations; // Always zero in an image. + uint32_t pointer_to_line_numbers; // Always zero in an image. + uint16_t number_of_relocations; // Always zero in an image. + uint16_t number_of_line_numbers; // Always zero in an image. + uint32_t characteristics; +}; + +// IMAGE_DATA_DIRECTORY +struct ImageDataDirectory { + uint32_t virtual_address; + uint32_t size; +}; + +// IMAGE_FILE_HEADER +struct ImageFileHeader { + uint16_t machine; + uint16_t number_of_sections; + uint32_t time_date_stamp; + uint32_t pointer_to_symbol_table; + uint32_t number_of_symbols; + uint16_t size_of_optional_header; + uint16_t characteristics; +}; + +// IMAGE_OPTIONAL_HEADER +struct ImageOptionalHeader { + uint16_t magic; // 0x00: 0x10b or 0x107 + uint8_t major_linker_version; + uint8_t minor_linker_version; + uint32_t size_of_code; + uint32_t size_of_initialized_data; + uint32_t size_of_uninitialized_data; + uint32_t address_of_entry_point; // 0x10 + uint32_t base_of_code; + uint32_t base_of_data; + + uint32_t image_base; + uint32_t section_alignment; // 0x20 + uint32_t file_alignment; + uint16_t major_operating_system_version; + uint16_t minor_operating_system_version; + uint16_t major_image_version; + uint16_t minor_image_version; + uint16_t major_subsystem_version; // 0x30 + uint16_t minor_subsystem_version; + uint32_t win32_version_value; + uint32_t size_of_image; + uint32_t size_of_headers; + uint32_t check_sum; // 0x40 + uint16_t subsystem; + uint16_t dll_characteristics; + uint32_t size_of_stack_reserve; + uint32_t size_of_stack_commit; + uint32_t size_of_heap_reserve; // 0x50 + uint32_t size_of_heap_commit; + uint32_t loader_flags; + uint32_t number_of_rva_and_sizes; + ImageDataDirectory data_directory[kImageNumberOfDirectoryEntries]; // 0x60 + /* 0xE0 */ +}; + +// IMAGE_OPTIONAL_HEADER64 +struct ImageOptionalHeader64 { + uint16_t magic; // 0x00: 0x10b or 0x107 + uint8_t major_linker_version; + uint8_t minor_linker_version; + uint32_t size_of_code; + uint32_t size_of_initialized_data; + uint32_t size_of_uninitialized_data; + uint32_t address_of_entry_point; // 0x10 + uint32_t base_of_code; + + uint64_t image_base; + uint32_t section_alignment; // 0x20 + uint32_t file_alignment; + uint16_t major_operating_system_version; + uint16_t minor_operating_system_version; + uint16_t major_image_version; + uint16_t minor_image_version; + uint16_t major_subsystem_version; // 0x30 + uint16_t minor_subsystem_version; + uint32_t win32_version_value; + uint32_t size_of_image; + uint32_t size_of_headers; + uint32_t check_sum; // 0x40 + uint16_t subsystem; + uint16_t dll_characteristics; + uint64_t size_of_stack_reserve; + uint64_t size_of_stack_commit; // 0x50 + uint64_t size_of_heap_reserve; + uint64_t size_of_heap_commit; // 0x60 + uint32_t loader_flags; + uint32_t number_of_rva_and_sizes; + ImageDataDirectory data_directory[kImageNumberOfDirectoryEntries]; // 0x70 + /* 0xF0 */ +}; + +#pragma pack(pop) + +} // namespace pe + +// Constants and offsets gleaned from WINNT.h and various articles on the +// format of Windows PE executables. + +constexpr char const* kTextSectionName = ".text"; + +// Bitfield with characteristics usually associated with code sections. +const uint32_t kCodeCharacteristics = + pe::kImageScnMemExecute | pe::kImageScnMemRead; + +} // namespace zucchini + +#endif // CHROME_INSTALLER_ZUCCHINI_TYPE_WIN_PE_H_
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index a28f42b9..3f389ce 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1629,6 +1629,7 @@ "//components/dom_distiller/content/browser", "//components/dom_distiller/content/renderer", "//components/dom_distiller/core:test_support", + "//components/feature_engagement/test:test_support", "//components/policy:chrome_settings_proto_generated_compile", "//components/resources", "//components/safe_browsing_db:test_database_manager", @@ -2107,6 +2108,7 @@ ] if (!is_chromeos && (!is_mac || mac_views_browser)) { sources += [ + "../browser/feature_engagement/new_tab/new_tab_tracker_browsertest.cc", "../browser/ui/views/profiles/forced_reauthentication_dialog_view_browsertest.cc", "../browser/ui/views/profiles/profile_chooser_view_browsertest.cc", ]
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py index 2249fbd..f807582 100755 --- a/chrome/test/chromedriver/test/run_py_tests.py +++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -1281,8 +1281,13 @@ def testTouchScrollElement(self): self._driver.Load(self.GetHttpUrlForFile( '/chromedriver/touch_action_tests.html')) - scroll_left = 'return document.documentElement.scrollLeft;' - scroll_top = 'return document.documentElement.scrollTop;' + major_version = int(self._driver.capabilities['version'].split('.')[0]) + if major_version >= 61: + scroll_left = 'return document.documentElement.scrollLeft;' + scroll_top = 'return document.documentElement.scrollTop;' + else: + scroll_left = 'return document.body.scrollLeft;' + scroll_top = 'return document.body.scrollTop;' self.assertEquals(0, self._driver.ExecuteScript(scroll_left)) self.assertEquals(0, self._driver.ExecuteScript(scroll_top)) target = self._driver.FindElement('id', 'target')
diff --git a/chrome/test/chromedriver/test/test_expectations b/chrome/test/chromedriver/test/test_expectations index 676754f..f95497b 100644 --- a/chrome/test/chromedriver/test/test_expectations +++ b/chrome/test/chromedriver/test/test_expectations
@@ -274,6 +274,8 @@ _OS_NEGATIVE_FILTER['android:chrome'] + [ # https://bugs.chromium.org/p/chromedriver/issues/detail?id=998 'ImplicitWaitTest.testShouldImplicitlyWaitForASingleElement', + # https://bugs.chromium.org/p/chromedriver/issues/detail?id=1852 + 'CorrectEventFiringTest.testShouldFireMouseDownEventWhenClicking', ] )
diff --git a/chrome/test/data/extensions/api_test/feedback_private/basic/test.js b/chrome/test/data/extensions/api_test/feedback_private/basic/test.js index 5512b7eb..53996918 100644 --- a/chrome/test/data/extensions/api_test/feedback_private/basic/test.js +++ b/chrome/test/data/extensions/api_test/feedback_private/basic/test.js
@@ -27,7 +27,8 @@ }; chrome.feedbackPrivate.sendFeedback( feedbackInfo, chrome.test.callbackPass(function(response) { - chrome.test.assertEq(response, 'success'); + chrome.test.assertEq( + response, chrome.feedbackPrivate.Status.SUCCESS); })); } ]);
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index 38e030fb..4cbf80f 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -79,6 +79,7 @@ "sandboxstatus_browsertest.js", "settings/accessibility_audit_rules.js", "settings/accessibility_browsertest.js", + "settings/accessibility_test.js", "settings/advanced_page_browsertest.js", "settings/animation_browsertest.js", "settings/basic_page_browsertest.js", @@ -138,6 +139,7 @@ ] extra_js_files = [ "../../../browser/resources/md_downloads/action_service.js", + "../../../browser/resources/md_downloads/browser_proxy.js", "../../../browser/resources/print_preview/data/measurement_system.js", "../../../browser/resources/print_preview/print_preview_utils.js", "../../../renderer/resources/extensions/notifications_custom_bindings.js",
diff --git a/chrome/test/data/webui/extensions/cr_extensions_browsertest.js b/chrome/test/data/webui/extensions/cr_extensions_browsertest.js index 2fdd0337..7f5b1ea 100644 --- a/chrome/test/data/webui/extensions/cr_extensions_browsertest.js +++ b/chrome/test/data/webui/extensions/cr_extensions_browsertest.js
@@ -464,3 +464,28 @@ extension_navigation_helper_tests.TestNames.PushAndReplaceState)) .run(); }); + +//////////////////////////////////////////////////////////////////////////////// +// Extension View Manager Tests + +var CrExtensionsViewManagerTest = class extends CrExtensionsBrowserTest { + /** @override */ + get browsePreload() { + return 'chrome://extensions/view_manager.html'; + } + + /** @override */ + get extraLibraries() { + return super.extraLibraries.concat([ + 'extension_view_manager_test.js', + ]); + } +} + +TEST_F('CrExtensionsViewManagerTest', 'VisibilityTest', function() { + mocha.grep(assert(extension_view_manager_tests.TestNames.Visibility)).run(); +}); + +TEST_F('CrExtensionsViewManagerTest', 'EventFiringTest', function() { + mocha.grep(assert(extension_view_manager_tests.TestNames.EventFiring)).run(); +});
diff --git a/chrome/test/data/webui/extensions/extension_manager_test.js b/chrome/test/data/webui/extensions/extension_manager_test.js index 24fb38a..f3479c2 100644 --- a/chrome/test/data/webui/extensions/extension_manager_test.js +++ b/chrome/test/data/webui/extensions/extension_manager_test.js
@@ -22,6 +22,10 @@ /** @type {extensions.Manager} */ var manager; + function isActiveView(viewId) { + expectEquals(viewId, manager.$.viewManager.querySelector('.active').id); + } + setup(function() { manager = document.querySelector('extensions-manager'); }); @@ -124,34 +128,35 @@ test(assert(TestNames.ChangePages), function() { // We start on the item list. - var pages = manager.$.pages; - expectEquals(Page.LIST, pages.selected); + MockInteractions.tap(manager.sidebar.$['sections-extensions']); + Polymer.dom.flush(); + isActiveView(Page.LIST); // Switch: item list -> keyboard shortcuts. MockInteractions.tap(manager.sidebar.$['sections-shortcuts']); Polymer.dom.flush(); - expectEquals(Page.SHORTCUTS, pages.selected); + isActiveView(Page.SHORTCUTS); // Switch: keyboard shortcuts -> item list. MockInteractions.tap(manager.sidebar.$['sections-apps']); Polymer.dom.flush(); - expectEquals(Page.LIST, pages.selected); + isActiveView(Page.LIST); // Switch: item list -> detail view. var item = manager.$['items-list'].$$('extensions-item'); assert(item); item.onDetailsTap_(); Polymer.dom.flush(); - expectEquals(Page.DETAILS, pages.selected); + isActiveView(Page.DETAILS); // Switch: detail view -> keyboard shortcuts. MockInteractions.tap(manager.sidebar.$['sections-shortcuts']); Polymer.dom.flush(); - expectEquals(Page.SHORTCUTS, pages.selected); + isActiveView(Page.SHORTCUTS); }); test(assert(TestNames.UrlNavigationToDetails), function() { - expectEquals(Page.DETAILS, manager.$.pages.selected); + isActiveView(Page.DETAILS); var detailsView = manager.$['details-view']; expectEquals('ldnnhddmnhbkjipkidpdiheffobcpfmf', detailsView.data.id); });
diff --git a/chrome/test/data/webui/extensions/extension_view_manager_test.js b/chrome/test/data/webui/extensions/extension_view_manager_test.js new file mode 100644 index 0000000..1f8c8ea --- /dev/null +++ b/chrome/test/data/webui/extensions/extension_view_manager_test.js
@@ -0,0 +1,107 @@ +// 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. + +/** @fileoverview Suite of tests for extensions-detail-view. */ +cr.define('extension_view_manager_tests', function() { + /** @enum {string} */ + var TestNames = { + Visibility: 'visibility', + EventFiring: 'event firing', + }; + + var viewManager; + var views; + + suite('ExtensionViewManagerTest', function() { + + // Initialize an extension item before each test. + setup(function() { + PolymerTest.clearBody(); + + document.body.innerHTML = ` + <extensions-view-manager id="viewManager"> + <div slot="view" id="viewOne">view 1</div> + <div slot="view" id="viewTwo">view 2</div> + <div slot="view" id="viewThree">view 3</div> + </extensions-view-manager>`; + + viewManager = document.body.querySelector('#viewManager'); + }); + + test(assert(TestNames.Visibility), function() { + function assertViewVisible(id, isVisible) { + const expectFunc = isVisible ? expectTrue : expectFalse; + expectFunc(extension_test_util.isVisible(viewManager, '#' + id, true)); + } + + assertViewVisible('viewOne', false); + assertViewVisible('viewTwo', false); + assertViewVisible('viewThree', false); + + return viewManager.switchView('viewOne') + .then(() => { + assertViewVisible('viewOne', true); + assertViewVisible('viewTwo', false); + assertViewVisible('viewThree', false); + + return viewManager.switchView('viewThree') + }) + .then(() => { + assertViewVisible('viewOne', false); + assertViewVisible('viewTwo', false); + assertViewVisible('viewThree', true); + }); + }); + + test(assert(TestNames.EventFiring), function() { + var viewOne = viewManager.querySelector('#viewOne'); + var enterStart = false; + var enterFinish = false; + var exitStart = false; + var exitFinish = false; + + var fired = {}; + + [ + 'view-enter-start', + 'view-enter-finish', + 'view-exit-start', + 'view-exit-finish', + ].forEach(type => { + viewOne.addEventListener(type, () => { + fired[type] = true; + }) + }); + + // Setup the switch promise first. + var enterPromise = viewManager.switchView('viewOne'); + // view-enter-start should fire synchronously. + expectTrue(!!fired['view-enter-start']); + // view-enter-finish should not fire yet. + expectFalse(!!fired['view-enter-finish']); + + return enterPromise + .then(() => { + // view-enter-finish should fire after animation. + expectTrue(!!fired['view-enter-finish']); + + enterPromise = viewManager.switchView('viewTwo'); + // view-exit-start should fire synchronously. + expectTrue(!!fired['view-exit-start']); + // view-exit-finish should not fire yet. + expectFalse(!!fired['view-exit-finish']); + + return enterPromise; + }) + .then(() => { + // view-exit-finish should fire after animation. + expectTrue(!!fired['view-exit-finish']); + }); + }); + }); + + return { + TestNames: TestNames, + }; +});
diff --git a/chrome/test/data/webui/settings/accessibility_audit_rules.js b/chrome/test/data/webui/settings/accessibility_audit_rules.js index 80e597a..5079576 100644 --- a/chrome/test/data/webui/settings/accessibility_audit_rules.js +++ b/chrome/test/data/webui/settings/accessibility_audit_rules.js
@@ -2,19 +2,31 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -/** @fileoverview Lists the rules tested by the accessibility audit. +/** + * @fileoverview List the the audit rules tested by the aXe-audit. * * This list is generated by pasting the third_party/axe-core/axe.js code into * the browser console and running: * axe.getRules().map(function(ruleObj) { * return ruleObj.ruleId * }); + * + * Aforementioned code cannot be run in the file because during build time, + * js2gtest.js evals the file without any dependencies. At + * this point, not even a browser window exists. Thus, axe can only be + * referenced during runtime within the TEST_F call. */ -// Namespace for the accessibility audit. -function AccessibilityAudit() {} +/** + * Accessibility Test + * @namespace + */ +var AccessibilityTest = AccessibilityTest || {}; -AccessibilityAudit.ruleIds = [ +/** + * Hard-coded list of audit rule ids from the aXe-core audit. + */ +AccessibilityTest.ruleIds = [ 'accesskeys', 'area-alt', 'aria-allowed-attr',
diff --git a/chrome/test/data/webui/settings/accessibility_browsertest.js b/chrome/test/data/webui/settings/accessibility_browsertest.js index 30c1aec..512e1ba 100644 --- a/chrome/test/data/webui/settings/accessibility_browsertest.js +++ b/chrome/test/data/webui/settings/accessibility_browsertest.js
@@ -14,58 +14,17 @@ GEN_INCLUDE([ ROOT_PATH + 'chrome/test/data/webui/polymer_browser_test_base.js', ROOT_PATH + 'chrome/test/data/webui/settings/accessibility_audit_rules.js', + ROOT_PATH + 'chrome/test/data/webui/settings/accessibility_test.js', ROOT_PATH + 'third_party/axe-core/axe.js', ]); /** - * @typedef {{ - * rules: { - * 'color_contrast': ({ enabled: boolean} | undefined), - * 'aria_valid_attr': ({ enabled: boolean} | undefined), - * } - * }} - * @see https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#options-parameter - */ -function AccessibilityAuditConfig() {} - -/** * Test fixture for Accessibility of Chrome Settings. * @constructor * @extends {PolymerTest} */ function SettingsAccessibilityTest() {} -/** - * Run aXe-core accessibility audit, print console-friendly representation - * of violations to console, and fail the test if there are audit failures. - * @param {AccessibilityAuditConfig} options Dictionary disabling specific - * audit rules. - * @return {Promise} A promise resolved when the accessibility audit completes - * with no issues, or rejected if the audit finds any accessibility issues. - */ -SettingsAccessibilityTest.runAudit = function(options) { - // Ignore iron-iconset-svg elements that have duplicate ids and result in - // false postives from the audit. - var context = {exclude: ['iron-iconset-svg']}; - options = options || {}; - - return new Promise(function(resolve, reject) { - axe.run(context, options, function(err, results) { - if (err) - reject(err); - - var violationCount = results.violations.length; - if (violationCount) { - // Pretty print out the violations detected by the audit. - console.log(JSON.stringify(results.violations, null, 4)); - reject('Found ' + violationCount + ' accessibility violations.'); - } else { - resolve(); - } - }); - }); -}; - SettingsAccessibilityTest.prototype = { __proto__: PolymerTest.prototype, @@ -74,8 +33,9 @@ // Include files that define the mocha tests. extraLibraries: PolymerTest.getLibraries(ROOT_PATH).concat([ - 'ensure_lazy_loaded.js', 'passwords_and_autofill_fake_data.js', - 'passwords_a11y_test.js' + 'ensure_lazy_loaded.js', + 'passwords_and_autofill_fake_data.js', + 'passwords_a11y_test.js', ]), // TODO(hcarmona): Remove once ADT is not longer in the testing infrastructure @@ -87,23 +47,30 @@ }, }; -// TODO(quacht): Enable the audit rules failed in a separate CL after -// resolving the violation or after adding the violation exception framework. -// http://crbug.com/748608 -// http://crbug.com/748632 -var rulesToSkip = ['aria-valid-attr', 'color-contrast', 'region', 'skip-link']; +var rulesToSkip = [ + // Skip rules typically not run by the aXe audit by default. + 'region', + 'skip-link', + // Disable rules flaky for CFI build. + 'meta-viewpoint', + 'list', + 'frame-title', + 'label', + 'hidden_content', + 'aria-valid-attr-value', + 'button-name' +]; // Define a unit test for every audit rule. -AccessibilityAudit.ruleIds.forEach(function(ruleId) { +AccessibilityTest.ruleIds.forEach((ruleId) => { if (rulesToSkip.indexOf(ruleId) == -1) { // Replace hyphens, which break the build. var ruleName = ruleId.replace(new RegExp('-', 'g'), '_'); - TEST_F( - 'SettingsAccessibilityTest', 'MANAGE_PASSWORDS_' + ruleName, - function() { + TEST_F('SettingsAccessibilityTest', 'MANAGE_PASSWORDS_' + ruleName, + () => { mocha.grep('MANAGE_PASSWORDS_' + ruleId).run(); }); } -}) +}); GEN('#endif // defined(NDEBUG)'); \ No newline at end of file
diff --git a/chrome/test/data/webui/settings/accessibility_test.js b/chrome/test/data/webui/settings/accessibility_test.js new file mode 100644 index 0000000..12bd349 --- /dev/null +++ b/chrome/test/data/webui/settings/accessibility_test.js
@@ -0,0 +1,192 @@ +// 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. + +/** + * @fileoverview Accessibility Test API + */ + +/** + * Accessibility Test + * @namespace + */ +var AccessibilityTest = AccessibilityTest || {}; + +/** + * @typedef {{ + * runOnly: { + * type: string, + * values: Array<string> + * } + * }} + * @see https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#options-parameter + */ +AccessibilityTest.AxeOptions; + +/** + * The violation filter object maps individual audit rule IDs to functions that + * return true for elements to filter from that rule's violations. + * @typedef {Object<string, function(!axe.NodeResult): boolean>} + */ +AccessibilityTest.ViolationFilter; + +/** + * @typedef {{ + * name: string, + * axeOptions: ?AccessibilityTest.AxeOptions, + * setup: ?function, + * tests: Object<string, function(): ?Promise>, + * violationFilter: ?AccessibilityTest.ViolationFilter + * }} + */ +AccessibilityTest.Definition; + +/** + * Run aXe-core accessibility audit, print console-friendly representation + * of violations to console, and fail the test. + * @param {!AccessibilityTest.Definition} testDef Object configuring the audit. + * @return {Promise} A promise that will be resolved with the accessibility + * audit is complete. + */ +AccessibilityTest.runAudit_ = function(testDef) { + // Ignore iron-iconset-svg elements that have duplicate ids and result in + // false postives from the audit. + var context = {exclude: ['iron-iconset-svg']}; + options = testDef.axeOptions || {}; + // Element references needed for filtering audit results. + options.elementRef = true; + + return new Promise((resolve, reject) => { + axe.run(context, options, (err, results) => { + if (err) + reject(err); + + var filteredViolations = AccessibilityTest.filterViolations_( + results.violations, testDef.violationFilter || {}); + + var violationCount = filteredViolations.length; + if (violationCount) { + AccessibilityTest.print_(filteredViolations); + reject('Found ' + violationCount + ' accessibility violations.'); + } else { + resolve(); + } + }); + }); +}; + +/* + * Get list of filtered audit violations. + * @param {!Array<axe.Result>} violations List of accessibility violations. + * @param {!AccessibilityTest.ViolationFilter} filter Object specifying set of + * violations to filter from the results. + * @return {!Array<axe.Result>} List of filtered violations. + */ +AccessibilityTest.filterViolations_ = function(violations, filter) { + if (Object.keys(filter).length == 0) { + return violations; + } + + var filteredViolations = []; + // Check for and remove any nodes specified by filter. + for (let violation of violations) { + if (violation.id in filter) { + var exclusionRule = filter[violation.id]; + violation.nodes = violation.nodes.filter( + (node) => !exclusionRule(node)); + } + + if (violation.nodes.length > 0) { + filteredViolations.push(violation); + } + } + return filteredViolations; +}; + +/** + * Define a different test for each audit rule, unless overridden by + * |test.options.runOnly|. + * @param {AccessibilityTestDefinition} test Object configuring the test. + * @constructor + */ +AccessibilityTest.define = function(test) { + var axeOptions = test.axeOptions || {}; + // Maintain a list of tests to define. + var tests = [test]; + + // This option override should go first b/c it creates multiple test targets. + if (!axeOptions.runOnly) { + tests = []; + // Define a test for each audit rule separately. + for (let ruleId of AccessibilityTest.ruleIds) { + var newTestDefinition = Object.assign({}, test); + newTestDefinition.name += '_' + ruleId; + newTestDefinition.axeOptions = Object.assign({}, axeOptions); + newTestDefinition.axeOptions.runOnly = {type: 'rule', values: [ruleId]}; + + tests.push(newTestDefinition) + } + } + + // Define the mocha tests. + AccessibilityTest.defineAccessibilityTestSuite_(tests); +} + +/** + * Define mocha suite(s) testing accessibility for each test definition in + * given list. + * @param {Array<AccessibilityTestDefinition>} List of test definitions. + */ +AccessibilityTest.defineAccessibilityTestSuite_ = function(tests) { + for (let testDef of tests) { + suite(testDef.name, () => { + setup(testDef.setup.bind(testDef)); + for (var testMember in testDef.tests) { + test(testMember, AccessibilityTest.getMochaTest_(testMember, testDef)); + } + }); + } +} + +/** + * + * Return a function that runs the accessibility audit after executing + * the function corresponding to the |testDef.tests.testMember|. + * @param {string} testMember The name of the mocha test + * @param {AccessibilityTestDefinition} testDef Object configuring the test + * suite to which this test belongs. + */ +AccessibilityTest.getMochaTest_ = function(testMember, testDef) { + return () => { + // Run commands specified by the test definition followed by the + // accessibility audit. + var promise = testDef.tests[testMember].call(testDef); + if (promise) { + return promise.then(() => AccessibilityTest.runAudit_(testDef)); + } else { + return AccessibilityTest.runAudit_(testDef); + } + }; +}; + +/** + * Remove circular references in |violations| and print violations to the + * console. + * @param {!Array<axe.Result>} List of violations to display + */ +AccessibilityTest.print_ = function(violations) { + // Elements have circular references and must be removed before printing. + for (let violation of violations) { + for (let node of violation.nodes) { + delete node['element']; + ['all', 'any', 'none'].forEach((attribute) => { + for (let checkResult of node[attribute]) { + for (let relatedNode of checkResult.relatedNodes) { + delete relatedNode['element']; + } + } + }); + } + } + console.log(JSON.stringify(violations, null, 4)); +}; \ No newline at end of file
diff --git a/chrome/test/data/webui/settings/passwords_a11y_test.js b/chrome/test/data/webui/settings/passwords_a11y_test.js index af463ad..dd888058 100644 --- a/chrome/test/data/webui/settings/passwords_a11y_test.js +++ b/chrome/test/data/webui/settings/passwords_a11y_test.js
@@ -2,72 +2,80 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -/** @fileoverview Suite of accessibility tests for the passwords page. */ +/** @fileoverview Define accessibility tests for the MANAGE_PASSWORDS route. */ -// Define a mocha suite for every route-rule combination. -for (let ruleId of AccessibilityAudit.ruleIds) { - suite('MANAGE_PASSWORDS_' + ruleId, function() { - var passwordsSection = null; - var passwordManager = null; +AccessibilityTest.define({ + /** @override */ + name: 'MANAGE_PASSWORDS', + /** @type {PasswordManager} */ + passwordManager: null, + /** @type {PasswordsSectionElement}*/ + passwordsSection: null, + /** @override */ + setup: function() { + return new Promise((resolve) => { + // Reset to a blank page. + PolymerTest.clearBody(); - /** @type {AccessibilityAuditConfig} **/ - var auditOptions = {runOnly: {type: 'rule', values: [ruleId]}}; + // Set the URL to be that of specific route to load upon injecting + // settings-ui. Simply calling settings.navigateTo(route) prevents + // use of mock APIs for fake data. + window.history.pushState( + 'object or string', 'Test', settings.routes.MANAGE_PASSWORDS.path); - setup(function() { - return new Promise(function(resolve) { - // Reset to a blank page. - PolymerTest.clearBody(); + PasswordManagerImpl.instance_ = new TestPasswordManager(); + this.passwordManager = PasswordManagerImpl.instance_; - // Set the URL to be that of specific route to load upon injecting - // settings-ui. Simply calling settings.navigateTo(route) prevents - // use of mock APIs for fake data. - window.history.pushState( - 'object or string', 'Test', settings.routes.MANAGE_PASSWORDS.path); + var settingsUi = document.createElement('settings-ui'); - PasswordManagerImpl.instance_ = new TestPasswordManager(); - passwordManager = PasswordManagerImpl.instance_; + // The settings section will expand to load the MANAGE_PASSWORDS route + // (based on the URL set above) once the settings-ui element is attached + settingsUi.addEventListener('settings-section-expanded', () => { + // Passwords section should be loaded before setup is complete. + this.passwordsSection = settingsUi.$$('settings-main') + .$$('settings-basic-page') + .$$('settings-passwords-and-forms-page') + .$$('passwords-section'); + assertTrue(!!this.passwordsSection); - var settingsUi = document.createElement('settings-ui'); + assertEquals( + this.passwordManager, this.passwordsSection.passwordManager_); - // The settings section will expand to load the MANAGE_PASSWORDS route - // (based on the URL set above) once the settings-ui element is attached - settingsUi.addEventListener('settings-section-expanded', function() { - // Passwords section should be loaded before setup is complete. - passwordsSection = settingsUi.$$('settings-main') - .$$('settings-basic-page') - .$$('settings-passwords-and-forms-page') - .$$('passwords-section'); - - assertTrue(!!passwordsSection); - - assertEquals(passwordManager, passwordsSection.passwordManager_); - - resolve(); - }); - - document.body.appendChild(settingsUi); + resolve(); }); - }); - test('Accessible with 0 passwords', function() { - assertEquals(0, passwordsSection.savedPasswords.length); - return SettingsAccessibilityTest.runAudit(auditOptions); + document.body.appendChild(settingsUi); }); + }, - test('Accessible with 10 passwords', function() { + /** @override */ + tests: { + 'Accessible with 0 passwords': function() { + assertEquals(0, this.passwordsSection.savedPasswords.length); + }, + 'Accessible with 10 passwords': function() { var fakePasswords = []; for (var i = 0; i < 10; i++) { fakePasswords.push(FakeDataMaker.passwordEntry()); } - // Set list of passwords. - passwordManager.lastCallback.addSavedPasswordListChangedListener( + this.passwordManager.lastCallback.addSavedPasswordListChangedListener( fakePasswords); Polymer.dom.flush(); - assertEquals(10, passwordsSection.savedPasswords.length); - - return SettingsAccessibilityTest.runAudit(auditOptions); - }); - }); -}; \ No newline at end of file + assertEquals(10, this.passwordsSection.savedPasswords.length); + }, + }, + violationFilter: { + // TODO(quacht): remove this exception once the color contrast issue is + // solved. + // http://crbug.com/748608 + 'color-contrast': function(nodeResult) { + return nodeResult.element.id == 'prompt'; + }, + // Ignore errors caused by polymer aria-* attributes. + 'aria-valid-attr': function(nodeResult) { + return nodeResult.element.hasAttribute('aria-active-attribute'); + }, + } +});
diff --git a/chrome/test/data/webui/settings/site_details_permission_tests.js b/chrome/test/data/webui/settings/site_details_permission_tests.js index d7f8da7a..ce10dd2 100644 --- a/chrome/test/data/webui/settings/site_details_permission_tests.js +++ b/chrome/test/data/webui/settings/site_details_permission_tests.js
@@ -48,16 +48,6 @@ document.body.appendChild(testElement); }); - // Tests that the given value is converted to the expected value, for a - // given prefType. - function isAllowed(origin, exceptionList) { - for (var i = 0; i < exceptionList.length; ++i) { - if (exceptionList[i].origin == origin) - return exceptionList[i].setting == settings.ContentSetting.ALLOW; - } - return false; - }; - function validatePermissionFlipWorks(origin, expectedContentSetting) { browserProxy.resetResolver('setOriginPermissions'); @@ -218,6 +208,7 @@ testElement.$.permissionItem.innerText.trim()); assertTrue(testElement.$.permissionItem.classList.contains('two-line')); assertTrue(testElement.$.permission.disabled); + assertEquals(testSetting, testElement.$.permission.value); }; // Permissions that have been set by enterprise policy. @@ -241,6 +232,7 @@ testElement.$.permissionItem.innerText.trim()); assertTrue(testElement.$.permissionItem.classList.contains('two-line')); assertTrue(testElement.$.permission.disabled); + assertEquals(testSetting, testElement.$.permission.value); }; // Finally, check if changing the source from a non-user-controlled setting
diff --git a/chrome/test/data/webui/settings/site_details_tests.js b/chrome/test/data/webui/settings/site_details_tests.js index c2808fa6..05ebd72 100644 --- a/chrome/test/data/webui/settings/site_details_tests.js +++ b/chrome/test/data/webui/settings/site_details_tests.js
@@ -126,7 +126,7 @@ { embeddingOrigin: 'https://foo.com:443', origin: 'https://foo.com:443', - setting: settings.ContentSetting.BLOCK, + setting: settings.ContentSetting.ASK, source: settings.SiteSettingSource.POLICY, }, ], @@ -272,20 +272,19 @@ .then(() => { // Make sure initial state is as expected. assertEquals( - settings.ContentSetting.BLOCK, - siteDetailsPermission.site.setting); + settings.ContentSetting.ASK, siteDetailsPermission.site.setting); assertEquals( settings.SiteSettingSource.POLICY, siteDetailsPermission.site.source); assertEquals( - settings.ContentSetting.BLOCK, + settings.ContentSetting.ASK, siteDetailsPermission.$.permission.value); // Set new prefs and make sure only that permission is updated. var newException = { embeddingOrigin: testElement.origin, origin: testElement.origin, - setting: settings.ContentSetting.ASK, + setting: settings.ContentSetting.BLOCK, source: settings.SiteSettingSource.DEFAULT, }; browserProxy.resetResolver('getOriginPermissions'); @@ -301,7 +300,8 @@ // Check |siteDetailsPermission| now shows the new permission value. assertEquals( - settings.ContentSetting.ASK, siteDetailsPermission.site.setting); + settings.ContentSetting.BLOCK, + siteDetailsPermission.site.setting); assertEquals( settings.SiteSettingSource.DEFAULT, siteDetailsPermission.site.source);
diff --git a/chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h b/chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h index 6f495f9..3a5ebb5 100644 --- a/chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h +++ b/chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h
@@ -46,6 +46,7 @@ #include <string> #include "net/cert/cert_database.h" +#include "net/cert/cert_type.h" namespace mozilla_security_manager {
diff --git a/chromecast/media/audio/cast_audio_manager.cc b/chromecast/media/audio/cast_audio_manager.cc index 7627bfb..97fc9c8 100644 --- a/chromecast/media/audio/cast_audio_manager.cc +++ b/chromecast/media/audio/cast_audio_manager.cc
@@ -56,10 +56,6 @@ return false; } -void CastAudioManager::ShowAudioInputSettings() { - LOG(WARNING) << "No support for input audio devices"; -} - void CastAudioManager::GetAudioInputDeviceNames( ::media::AudioDeviceNames* device_names) { DCHECK(device_names->empty());
diff --git a/chromecast/media/audio/cast_audio_manager.h b/chromecast/media/audio/cast_audio_manager.h index 7c95557..9a7ab95f 100644 --- a/chromecast/media/audio/cast_audio_manager.h +++ b/chromecast/media/audio/cast_audio_manager.h
@@ -28,7 +28,6 @@ // AudioManagerBase implementation. bool HasAudioOutputDevices() override; bool HasAudioInputDevices() override; - void ShowAudioInputSettings() override; void GetAudioInputDeviceNames( ::media::AudioDeviceNames* device_names) override; ::media::AudioParameters GetInputStreamParameters(
diff --git a/chromecast/media/audio/cast_audio_manager_alsa.cc b/chromecast/media/audio/cast_audio_manager_alsa.cc index fa1bd58..2e49575 100644 --- a/chromecast/media/audio/cast_audio_manager_alsa.cc +++ b/chromecast/media/audio/cast_audio_manager_alsa.cc
@@ -48,10 +48,6 @@ return true; } -void CastAudioManagerAlsa::ShowAudioInputSettings() { - LOG(WARNING) << "No support for input audio devices"; -} - void CastAudioManagerAlsa::GetAudioInputDeviceNames( ::media::AudioDeviceNames* device_names) { DCHECK(device_names->empty());
diff --git a/chromecast/media/audio/cast_audio_manager_alsa.h b/chromecast/media/audio/cast_audio_manager_alsa.h index e0d8522e..3ccc6252 100644 --- a/chromecast/media/audio/cast_audio_manager_alsa.h +++ b/chromecast/media/audio/cast_audio_manager_alsa.h
@@ -30,7 +30,6 @@ // CastAudioManager implementation. bool HasAudioInputDevices() override; - void ShowAudioInputSettings() override; void GetAudioInputDeviceNames( ::media::AudioDeviceNames* device_names) override; ::media::AudioParameters GetInputStreamParameters(
diff --git a/components/autofill_strings.grdp b/components/autofill_strings.grdp index 4b5c3c12..ab81481 100644 --- a/components/autofill_strings.grdp +++ b/components/autofill_strings.grdp
@@ -167,7 +167,7 @@ </message> <message name="IDS_AUTOFILL_SHOW_ALL_SAVED_FALLBACK" desc="The text shown as an option in the suggestion drop down when a password field is clicked"> - Show all saved passwords + Show all saved passwords... </message> <!-- Autofill Credit Card Assisted Filling Infobar -->
diff --git a/components/cryptauth/BUILD.gn b/components/cryptauth/BUILD.gn index 6219419..774c25b 100644 --- a/components/cryptauth/BUILD.gn +++ b/components/cryptauth/BUILD.gn
@@ -42,6 +42,8 @@ "cryptauth_service.h", "data_with_timestamp.cc", "data_with_timestamp.h", + "device_capability_manager.cc", + "device_capability_manager.h", "device_to_device_authenticator.cc", "device_to_device_authenticator.h", "device_to_device_initiator_helper.cc", @@ -163,6 +165,7 @@ "cryptauth_enroller_impl_unittest.cc", "cryptauth_enrollment_manager_unittest.cc", "cryptauth_gcm_manager_impl_unittest.cc", + "device_capability_manager_unittest.cc", "device_to_device_authenticator_unittest.cc", "device_to_device_operations_unittest.cc", "device_to_device_secure_context_unittest.cc",
diff --git a/components/cryptauth/device_capability_manager.cc b/components/cryptauth/device_capability_manager.cc new file mode 100644 index 0000000..1e33c58 --- /dev/null +++ b/components/cryptauth/device_capability_manager.cc
@@ -0,0 +1,214 @@ +// 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 "components/cryptauth/device_capability_manager.h" + +#include "base/logging.h" +#include "components/cryptauth/proto/cryptauth_api.pb.h" + +namespace cryptauth { + +DeviceCapabilityManager::DeviceCapabilityManager( + CryptAuthClientFactory* cryptauth_client_factory) + : crypt_auth_client_factory_(cryptauth_client_factory), + weak_ptr_factory_(this) {} + +DeviceCapabilityManager::~DeviceCapabilityManager() {} + +void DeviceCapabilityManager::SetCapabilityEnabled( + const std::string& public_key, + Capability capability, + bool enabled, + const base::Closure& success_callback, + const base::Callback<void(const std::string&)>& error_callback) { + pending_requests_.emplace(base::MakeUnique<Request>( + RequestType::SET_CAPABILITY_ENABLED, Capability::CAPABILITY_UNLOCK_KEY, + public_key, enabled, success_callback, error_callback)); + ProcessRequestQueue(); +} + +void DeviceCapabilityManager::FindEligibleDevicesForCapability( + Capability capability, + const base::Callback<void(const std::vector<ExternalDeviceInfo>&, + const std::vector<IneligibleDevice>&)>& + success_callback, + const base::Callback<void(const std::string&)>& error_callback) { + pending_requests_.emplace(base::MakeUnique<Request>( + RequestType::FIND_ELIGIBLE_DEVICES_FOR_CAPABILITY, + Capability::CAPABILITY_UNLOCK_KEY, success_callback, error_callback)); + ProcessRequestQueue(); +} + +void DeviceCapabilityManager::IsCapabilityPromotable( + const std::string& public_key, + Capability capability, + const base::Callback<void(bool)>& success_callback, + const base::Callback<void(const std::string&)>& error_callback) { + pending_requests_.emplace(base::MakeUnique<Request>( + RequestType::IS_CAPABILITY_PROMOTABLE, capability, public_key, + success_callback, error_callback)); + ProcessRequestQueue(); +} + +DeviceCapabilityManager::Request::Request( + RequestType request_type, + Capability capability, + std::string public_key, + bool enabled, + const base::Closure& set_capability_callback, + const base::Callback<void(const std::string&)>& error_callback) + : request_type(request_type), + error_callback(error_callback), + capability(capability), + public_key(public_key), + set_capability_callback(set_capability_callback), + enabled(enabled) {} + +DeviceCapabilityManager::Request::Request( + RequestType request_type, + Capability capability, + const base::Callback<void(const std::vector<ExternalDeviceInfo>&, + const std::vector<IneligibleDevice>&)>& + find_eligible_devices_callback, + const base::Callback<void(const std::string&)>& error_callback) + : request_type(request_type), + error_callback(error_callback), + capability(capability), + find_eligible_devices_callback(find_eligible_devices_callback) {} + +DeviceCapabilityManager::Request::Request( + RequestType request_type, + Capability capability, + std::string public_key, + const base::Callback<void(bool)> is_device_promotable_callback, + const base::Callback<void(const std::string&)>& error_callback) + : request_type(request_type), + error_callback(error_callback), + capability(capability), + public_key(public_key), + is_device_promotable_callback(is_device_promotable_callback) {} + +DeviceCapabilityManager::Request::~Request() {} + +void DeviceCapabilityManager::CreateNewCryptAuthClient() { + DCHECK(!current_cryptauth_client_); + current_cryptauth_client_ = crypt_auth_client_factory_->CreateInstance(); +} + +void DeviceCapabilityManager::ProcessSetCapabilityEnabledRequest() { + DCHECK(current_request_->capability == Capability::CAPABILITY_UNLOCK_KEY); + SetUnlockKeyCapability(); +} + +void DeviceCapabilityManager::ProcessFindEligibleDevicesForCapability() { + DCHECK(current_request_->capability == Capability::CAPABILITY_UNLOCK_KEY); + FindEligibleUnlockDevices(); +} + +void DeviceCapabilityManager::ProcessIsCapabilityPromotableRequest() { + DCHECK(current_request_->capability == Capability::CAPABILITY_UNLOCK_KEY); + IsDeviceUnlockPromotable(); +} + +void DeviceCapabilityManager::SetUnlockKeyCapability() { + CreateNewCryptAuthClient(); + + ToggleEasyUnlockRequest request; + request.set_enable(current_request_->enabled); + request.set_apply_to_all(true); + request.set_public_key(current_request_->public_key); + + current_cryptauth_client_->ToggleEasyUnlock( + request, + base::Bind(&DeviceCapabilityManager::OnToggleEasyUnlockResponse, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&DeviceCapabilityManager::OnErrorResponse, + weak_ptr_factory_.GetWeakPtr())); +} + +void DeviceCapabilityManager::FindEligibleUnlockDevices() { + CreateNewCryptAuthClient(); + + current_cryptauth_client_->FindEligibleUnlockDevices( + FindEligibleUnlockDevicesRequest(), + base::Bind(&DeviceCapabilityManager::OnFindEligibleUnlockDevicesResponse, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&DeviceCapabilityManager::OnErrorResponse, + weak_ptr_factory_.GetWeakPtr())); +} + +void DeviceCapabilityManager::IsDeviceUnlockPromotable() { + CreateNewCryptAuthClient(); + + FindEligibleForPromotionRequest request; + request.set_promoter_public_key(current_request_->public_key); + + current_cryptauth_client_->FindEligibleForPromotion( + request, + base::Bind(&DeviceCapabilityManager::OnIsDeviceUnlockPromotableResponse, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&DeviceCapabilityManager::OnErrorResponse, + weak_ptr_factory_.GetWeakPtr())); +} + +void DeviceCapabilityManager::OnToggleEasyUnlockResponse( + const ToggleEasyUnlockResponse& response) { + current_cryptauth_client_.reset(); + current_request_->set_capability_callback.Run(); + current_request_.reset(); + ProcessRequestQueue(); +} + +void DeviceCapabilityManager::OnFindEligibleUnlockDevicesResponse( + const FindEligibleUnlockDevicesResponse& response) { + current_cryptauth_client_.reset(); + current_request_->find_eligible_devices_callback.Run( + std::vector<ExternalDeviceInfo>(response.eligible_devices().begin(), + response.eligible_devices().end()), + std::vector<IneligibleDevice>(response.ineligible_devices().begin(), + response.ineligible_devices().end())); + current_request_.reset(); + ProcessRequestQueue(); +} + +void DeviceCapabilityManager::OnIsDeviceUnlockPromotableResponse( + const FindEligibleForPromotionResponse& response) { + current_cryptauth_client_.reset(); + current_request_->is_device_promotable_callback.Run( + response.may_show_promo()); + current_request_.reset(); + ProcessRequestQueue(); +} + +void DeviceCapabilityManager::OnErrorResponse(const std::string& response) { + current_cryptauth_client_.reset(); + current_request_->error_callback.Run(response); + current_request_.reset(); + ProcessRequestQueue(); +} + +void DeviceCapabilityManager::ProcessRequestQueue() { + if (current_request_ || pending_requests_.empty()) + return; + + current_request_ = std::move(pending_requests_.front()); + pending_requests_.pop(); + + switch (current_request_->request_type) { + case RequestType::SET_CAPABILITY_ENABLED: + ProcessSetCapabilityEnabledRequest(); + return; + case RequestType::FIND_ELIGIBLE_DEVICES_FOR_CAPABILITY: + ProcessFindEligibleDevicesForCapability(); + return; + case RequestType::IS_CAPABILITY_PROMOTABLE: + ProcessIsCapabilityPromotableRequest(); + return; + default: + NOTREACHED(); + return; + } +} + +} // namespace cryptauth \ No newline at end of file
diff --git a/components/cryptauth/device_capability_manager.h b/components/cryptauth/device_capability_manager.h new file mode 100644 index 0000000..4a40037 --- /dev/null +++ b/components/cryptauth/device_capability_manager.h
@@ -0,0 +1,143 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_CRYPTAUTH_DEVICE_CAPABILITY_MANAGER_H_ +#define COMPONENTS_CRYPTAUTH_DEVICE_CAPABILITY_MANAGER_H_ + +#include <queue> + +#include "base/bind.h" +#include "base/callback_forward.h" +#include "base/memory/ptr_util.h" +#include "base/memory/weak_ptr.h" +#include "components/cryptauth/cryptauth_client.h" +#include "components/cryptauth/proto/cryptauth_api.pb.h" + +namespace cryptauth { + +// DeviceCapabilityManager sends requests to the back-end which enable/disable +// device capabilities and finds devices which contain those capabilities. Here, +// the term "capability" refers to the ability of a device to use a given +// feature (e.g. EasyUnlock or Magic Tether). +class DeviceCapabilityManager { + public: + // CAPABILITY_UNLOCK_KEY refers to EasyUnlock. + enum class Capability { CAPABILITY_UNLOCK_KEY }; + + DeviceCapabilityManager(CryptAuthClientFactory* cryptauth_client_factory); + + ~DeviceCapabilityManager(); + + // Enables or disables |capability| for the device corresponding to + // |public_key|. In error cases, |error_callback| is invoked with an error + // string. + void SetCapabilityEnabled( + const std::string& public_key, + Capability capability, + bool enabled, + const base::Closure& success_callback, + const base::Callback<void(const std::string&)>& error_callback); + + // Fetches metadata about the device which are eligible for |capability|. In + // error cases, |error_callback| is invoked with an error string. + void FindEligibleDevicesForCapability( + Capability capability, + const base::Callback<void(const std::vector<ExternalDeviceInfo>&, + const std::vector<IneligibleDevice>&)>& + success_callback, + const base::Callback<void(const std::string&)>& error_callback); + + // Determines whether a device with |public_key| is promotable for + // |capability|. In error cases, |error_callback| is invoked with an error + // string. + void IsCapabilityPromotable( + const std::string& public_key, + Capability capability, + const base::Callback<void(bool)>& success_callback, + const base::Callback<void(const std::string&)>& error_callback); + + private: + enum class RequestType { + SET_CAPABILITY_ENABLED, + FIND_ELIGIBLE_DEVICES_FOR_CAPABILITY, + IS_CAPABILITY_PROMOTABLE + }; + + struct Request { + // Used for SET_CAPABILITY_ENABLED Requests. + Request(RequestType request_type, + Capability capability, + std::string public_key, + bool enabled, + const base::Closure& set_capability_callback, + const base::Callback<void(const std::string&)>& error_callback); + + // Used for FIND_ELIGIBLE_DEVICES_FOR_CAPABILITY Requests. + Request(RequestType request_type, + Capability capability, + const base::Callback<void(const std::vector<ExternalDeviceInfo>&, + const std::vector<IneligibleDevice>&)>& + find_eligible_devices_callback, + const base::Callback<void(const std::string&)>& error_callback); + + // Used for IS_CAPABILITY_PROMOTABLE Requests. + Request(RequestType request_type, + Capability capability, + std::string public_key, + const base::Callback<void(bool)> is_device_promotable_callback, + const base::Callback<void(const std::string&)>& error_callback); + + ~Request(); + + // Defined for every request. + RequestType request_type; + base::Callback<void(const std::string&)> error_callback; + Capability capability; + + // Defined for SET_CAPABILITY_ENABLED and IS_CAPABILITY_PROMOTABLE; + // otherwise, unused. + std::string public_key; + + // Defined if |request_type_| is SET_CAPABILITY_ENABLED; otherwise, unused. + base::Closure set_capability_callback; + bool enabled; + + // Defined if |request_type_| is FIND_ELIGIBLE_DEVICES_FOR_CAPABILITY; + // otherwise, unused. + base::Callback<void(const std::vector<ExternalDeviceInfo>&, + const std::vector<IneligibleDevice>&)> + find_eligible_devices_callback; + + // Defined if |request_type_| is IS_CAPABILITY_PROMOTABLE; otherwise, + // unused. + base::Callback<void(bool)> is_device_promotable_callback; + }; + + void CreateNewCryptAuthClient(); + + void ProcessSetCapabilityEnabledRequest(); + void ProcessFindEligibleDevicesForCapability(); + void ProcessIsCapabilityPromotableRequest(); + + void SetUnlockKeyCapability(); + void FindEligibleUnlockDevices(); + void IsDeviceUnlockPromotable(); + + void OnToggleEasyUnlockResponse(const ToggleEasyUnlockResponse& response); + void OnFindEligibleUnlockDevicesResponse( + const FindEligibleUnlockDevicesResponse& response); + void OnIsDeviceUnlockPromotableResponse( + const FindEligibleForPromotionResponse& response); + void OnErrorResponse(const std::string& response); + void ProcessRequestQueue(); + + std::unique_ptr<CryptAuthClient> current_cryptauth_client_; + std::unique_ptr<Request> current_request_; + std::queue<std::unique_ptr<Request>> pending_requests_; + CryptAuthClientFactory* crypt_auth_client_factory_; + base::WeakPtrFactory<DeviceCapabilityManager> weak_ptr_factory_; +}; +} // namespace cryptauth + +#endif // COMPONENTS_CRYPTAUTH_DEVICE_CAPABILITY_MANAGER_H_
diff --git a/components/cryptauth/device_capability_manager_unittest.cc b/components/cryptauth/device_capability_manager_unittest.cc new file mode 100644 index 0000000..4f89d7e --- /dev/null +++ b/components/cryptauth/device_capability_manager_unittest.cc
@@ -0,0 +1,417 @@ +// 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 "components/cryptauth/device_capability_manager.h" + +#include <stddef.h> + +#include <chrono> +#include <memory> +#include <thread> +#include <unordered_set> +#include <utility> + +#include "base/bind.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "components/cryptauth/mock_cryptauth_client.h" +#include "components/cryptauth/remote_device.h" +#include "components/cryptauth/remote_device_test_util.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::_; +using testing::Invoke; + +namespace cryptauth { + +namespace { + +const char kSuccessResult[] = "success"; +const char kErrorOnToggleEasyUnlockResult[] = "toggleEasyUnlockError"; +const char kErrorFindEligibleUnlockDevices[] = "findEligibleUnlockDeviceError"; +const char kErrorFindEligibleForPromotion[] = "findEligibleForPromotionError"; +const std::string kTestErrorCodeTogglingIneligibleDevice = + "togglingIneligibleDevice."; + +std::vector<cryptauth::ExternalDeviceInfo> +CreateExternalDeviceInfosForRemoteDevices( + const std::vector<cryptauth::RemoteDevice> remote_devices) { + std::vector<cryptauth::ExternalDeviceInfo> device_infos; + for (const auto& remote_device : remote_devices) { + // Add an ExternalDeviceInfo with the same public key as the RemoteDevice. + cryptauth::ExternalDeviceInfo info; + info.set_public_key(remote_device.public_key); + device_infos.push_back(info); + } + return device_infos; +} + +} // namespace + +class DeviceCapabilityManagerTest + : public testing::Test, + public MockCryptAuthClientFactory::Observer { + public: + DeviceCapabilityManagerTest() + : all_test_external_device_infos_( + CreateExternalDeviceInfosForRemoteDevices( + cryptauth::GenerateTestRemoteDevices(5))), + test_eligible_external_devices_infos_( + {all_test_external_device_infos_[0], + all_test_external_device_infos_[1], + all_test_external_device_infos_[2]}), + test_ineligible_external_devices_infos_( + {all_test_external_device_infos_[3], + all_test_external_device_infos_[4]}) {} + + void SetUp() override { + mock_cryptauth_client_factory_ = + base::MakeUnique<MockCryptAuthClientFactory>( + MockCryptAuthClientFactory::MockType::MAKE_NICE_MOCKS); + mock_cryptauth_client_factory_->AddObserver(this); + device_capability_manager_ = base::MakeUnique<DeviceCapabilityManager>( + mock_cryptauth_client_factory_.get()); + } + + void OnCryptAuthClientCreated(MockCryptAuthClient* client) override { + ON_CALL(*client, ToggleEasyUnlock(_, _, _)) + .WillByDefault( + Invoke(this, &DeviceCapabilityManagerTest::MockToggleEasyUnlock)); + ON_CALL(*client, FindEligibleUnlockDevices(_, _, _)) + .WillByDefault(Invoke( + this, &DeviceCapabilityManagerTest::MockFindEligibleUnlockDevices)); + ON_CALL(*client, FindEligibleForPromotion(_, _, _)) + .WillByDefault(Invoke( + this, &DeviceCapabilityManagerTest::MockFindEligibleForPromotion)); + } + + // Mock CryptAuthClient::ToggleEasyUnlock() implementation. + void MockToggleEasyUnlock( + const ToggleEasyUnlockRequest& request, + const CryptAuthClient::ToggleEasyUnlockCallback& callback, + const CryptAuthClient::ErrorCallback& error_callback) { + toggle_easy_unlock_callback_ = callback; + error_callback_ = error_callback; + error_code_ = kErrorOnToggleEasyUnlockResult; + } + + // Mock CryptAuthClient::FindEligibleUnlockDevices() implementation. + void MockFindEligibleUnlockDevices( + const FindEligibleUnlockDevicesRequest& request, + const CryptAuthClient::FindEligibleUnlockDevicesCallback& callback, + const CryptAuthClient::ErrorCallback& error_callback) { + find_eligible_unlock_devices_callback_ = callback; + error_callback_ = error_callback; + error_code_ = kErrorFindEligibleUnlockDevices; + } + + // Mock CryptAuthClient::FindEligibleForPromotion() implementation. + void MockFindEligibleForPromotion( + const FindEligibleForPromotionRequest& request, + const CryptAuthClient::FindEligibleForPromotionCallback& callback, + const CryptAuthClient::ErrorCallback& error_callback) { + find_eligible_for_promotion_callback_ = callback; + error_callback_ = error_callback; + error_code_ = kErrorFindEligibleForPromotion; + } + + FindEligibleUnlockDevicesResponse CreateFindEligibleUnlockDevicesResponse() { + FindEligibleUnlockDevicesResponse find_eligible_unlock_devices_response; + for (const auto& device_info : test_eligible_external_devices_infos_) { + find_eligible_unlock_devices_response.add_eligible_devices()->CopyFrom( + device_info); + } + for (const auto& device_info : test_ineligible_external_devices_infos_) { + find_eligible_unlock_devices_response.add_ineligible_devices() + ->mutable_device() + ->CopyFrom(device_info); + } + return find_eligible_unlock_devices_response; + } + + void VerifyDeviceEligibility() { + // Ensure that resulting devices are not empty. Otherwise, following for + // loop checks will succeed on empty resulting devices. + EXPECT_TRUE(result_eligible_devices_.size() > 0); + EXPECT_TRUE(result_ineligible_devices_.size() > 0); + for (const auto& device_info : result_eligible_devices_) { + EXPECT_TRUE( + std::find_if( + test_eligible_external_devices_infos_.begin(), + test_eligible_external_devices_infos_.end(), + [&device_info](const cryptauth::ExternalDeviceInfo& device) { + return device.public_key() == device_info.public_key(); + }) != test_eligible_external_devices_infos_.end()); + } + for (const auto& ineligible_device : result_ineligible_devices_) { + EXPECT_TRUE( + std::find_if(test_ineligible_external_devices_infos_.begin(), + test_ineligible_external_devices_infos_.end(), + [&ineligible_device]( + const cryptauth::ExternalDeviceInfo& device) { + return device.public_key() == + ineligible_device.device().public_key(); + }) != test_ineligible_external_devices_infos_.end()); + } + result_eligible_devices_.clear(); + result_ineligible_devices_.clear(); + } + + void SetCapabilityEnabled(DeviceCapabilityManager::Capability capability, + const ExternalDeviceInfo& device_info, + bool enable) { + device_capability_manager_->SetCapabilityEnabled( + device_info.public_key(), capability, enable, + base::Bind(&DeviceCapabilityManagerTest:: + TestSuccessSetCapabilityKeyUnlockCallback, + base::Unretained(this)), + base::Bind(&DeviceCapabilityManagerTest::TestErrorCallback, + base::Unretained(this))); + } + + void FindEligibleDevicesForCapability( + DeviceCapabilityManager::Capability capability) { + device_capability_manager_->FindEligibleDevicesForCapability( + DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY, + base::Bind(&DeviceCapabilityManagerTest:: + TestSuccessFindEligibleUnlockDevicesCallback, + base::Unretained(this)), + base::Bind(&DeviceCapabilityManagerTest::TestErrorCallback, + base::Unretained(this))); + } + + void IsPromotableDevice(DeviceCapabilityManager::Capability capability, + const std::string& public_key) { + device_capability_manager_->IsCapabilityPromotable( + public_key, capability, + base::Bind(&DeviceCapabilityManagerTest:: + TestSuccessFindEligibleForPromotionDeviceCallback, + base::Unretained(this)), + base::Bind(&DeviceCapabilityManagerTest::TestErrorCallback, + base::Unretained(this))); + } + + void TestSuccessSetCapabilityKeyUnlockCallback() { result_ = kSuccessResult; } + + void TestSuccessFindEligibleUnlockDevicesCallback( + const std::vector<ExternalDeviceInfo>& eligible_devices, + const std::vector<IneligibleDevice>& ineligible_devices) { + result_ = kSuccessResult; + result_eligible_devices_ = eligible_devices; + result_ineligible_devices_ = ineligible_devices; + } + + void TestSuccessFindEligibleForPromotionDeviceCallback(bool eligible) { + result_ = kSuccessResult; + result_eligible_for_promotion_ = eligible; + } + + void TestErrorCallback(const std::string& error_message) { + result_ = error_message; + } + + void InvokeSetCapabilityKeyUnlockCallback() { + CryptAuthClient::ToggleEasyUnlockCallback success_callback = + toggle_easy_unlock_callback_; + ASSERT_TRUE(!success_callback.is_null()); + toggle_easy_unlock_callback_.Reset(); + success_callback.Run(ToggleEasyUnlockResponse()); + } + + void InvokeFindEligibleUnlockDevicesCallback( + const FindEligibleUnlockDevicesResponse& retrieved_devices_response) { + CryptAuthClient::FindEligibleUnlockDevicesCallback success_callback = + find_eligible_unlock_devices_callback_; + ASSERT_TRUE(!success_callback.is_null()); + find_eligible_unlock_devices_callback_.Reset(); + success_callback.Run(retrieved_devices_response); + } + + void InvokeFindEligibleForPromotionCallback(bool eligible_for_promotion) { + FindEligibleForPromotionResponse response; + response.set_may_show_promo(eligible_for_promotion); + CryptAuthClient::FindEligibleForPromotionCallback success_callback = + find_eligible_for_promotion_callback_; + ASSERT_TRUE(!success_callback.is_null()); + find_eligible_for_promotion_callback_.Reset(); + success_callback.Run(response); + } + + void InvokeErrorCallback() { + CryptAuthClient::ErrorCallback error_callback = error_callback_; + ASSERT_TRUE(!error_callback.is_null()); + error_callback_.Reset(); + error_callback.Run(error_code_); + } + + std::string GetResultAndReset() { + std::string result; + result.swap(result_); + return result; + } + + bool GetEligibleForPromotionAndReset() { + bool result_eligible_for_promotion = result_eligible_for_promotion_; + result_eligible_for_promotion_ = false; + return result_eligible_for_promotion; + } + + const std::vector<cryptauth::ExternalDeviceInfo> + all_test_external_device_infos_; + const std::vector<ExternalDeviceInfo> test_eligible_external_devices_infos_; + const std::vector<ExternalDeviceInfo> test_ineligible_external_devices_infos_; + + std::unique_ptr<MockCryptAuthClientFactory> mock_cryptauth_client_factory_; + std::unique_ptr<cryptauth::DeviceCapabilityManager> + device_capability_manager_; + CryptAuthClient::ToggleEasyUnlockCallback toggle_easy_unlock_callback_; + CryptAuthClient::FindEligibleUnlockDevicesCallback + find_eligible_unlock_devices_callback_; + CryptAuthClient::FindEligibleForPromotionCallback + find_eligible_for_promotion_callback_; + CryptAuthClient::ErrorCallback error_callback_; + + // Used by all tests that involve CryptauthClient network calls internally. + // Network call statuses are mocked out in place by |result_| and + // |error_code_| to keep track of the order in which DevicaCapabilityManager + // functions are called. + std::string result_; + std::string error_code_; + // For FindEligibleUnlockDevice tests. + std::vector<ExternalDeviceInfo> result_eligible_devices_; + std::vector<IneligibleDevice> result_ineligible_devices_; + // For FindEligibleForPromotion tests. + bool result_eligible_for_promotion_; + + private: + DISALLOW_COPY_AND_ASSIGN(DeviceCapabilityManagerTest); +}; + +TEST_F(DeviceCapabilityManagerTest, TestOrderUponMultipleRequests) { + SetCapabilityEnabled( + DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY, + test_eligible_external_devices_infos_[0], true /* enable */); + FindEligibleDevicesForCapability( + DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY); + IsPromotableDevice(DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY, + test_eligible_external_devices_infos_[0].public_key()); + SetCapabilityEnabled( + DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY, + test_eligible_external_devices_infos_[1], true /* enable */); + FindEligibleDevicesForCapability( + DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY); + IsPromotableDevice(DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY, + test_eligible_external_devices_infos_[1].public_key()); + + InvokeSetCapabilityKeyUnlockCallback(); + EXPECT_EQ(kSuccessResult, GetResultAndReset()); + + InvokeFindEligibleUnlockDevicesCallback( + CreateFindEligibleUnlockDevicesResponse()); + EXPECT_EQ(kSuccessResult, GetResultAndReset()); + VerifyDeviceEligibility(); + + InvokeFindEligibleForPromotionCallback(true /* eligible */); + EXPECT_EQ(kSuccessResult, GetResultAndReset()); + EXPECT_TRUE(GetEligibleForPromotionAndReset()); + + InvokeSetCapabilityKeyUnlockCallback(); + EXPECT_EQ(kSuccessResult, GetResultAndReset()); + + InvokeFindEligibleUnlockDevicesCallback( + CreateFindEligibleUnlockDevicesResponse()); + EXPECT_EQ(kSuccessResult, GetResultAndReset()); + VerifyDeviceEligibility(); + + InvokeFindEligibleForPromotionCallback(true /* eligible */); + EXPECT_EQ(kSuccessResult, GetResultAndReset()); + EXPECT_TRUE(GetEligibleForPromotionAndReset()); +} + +TEST_F(DeviceCapabilityManagerTest, TestMultipleSetUnlocksRequests) { + SetCapabilityEnabled( + DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY, + test_eligible_external_devices_infos_[0], true /* enable */); + SetCapabilityEnabled( + DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY, + test_eligible_external_devices_infos_[1], true /* enable */); + SetCapabilityEnabled( + DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY, + test_eligible_external_devices_infos_[2], true /* enable */); + + InvokeErrorCallback(); + EXPECT_EQ(kErrorOnToggleEasyUnlockResult, GetResultAndReset()); + + InvokeSetCapabilityKeyUnlockCallback(); + EXPECT_EQ(kSuccessResult, GetResultAndReset()); + + InvokeSetCapabilityKeyUnlockCallback(); + EXPECT_EQ(kSuccessResult, GetResultAndReset()); +} + +TEST_F(DeviceCapabilityManagerTest, + TestMultipleFindEligibleForUnlockDevicesRequests) { + FindEligibleDevicesForCapability( + DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY); + FindEligibleDevicesForCapability( + DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY); + FindEligibleDevicesForCapability( + DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY); + + InvokeFindEligibleUnlockDevicesCallback( + CreateFindEligibleUnlockDevicesResponse()); + EXPECT_EQ(kSuccessResult, GetResultAndReset()); + VerifyDeviceEligibility(); + + InvokeErrorCallback(); + EXPECT_EQ(kErrorFindEligibleUnlockDevices, GetResultAndReset()); + + InvokeFindEligibleUnlockDevicesCallback( + CreateFindEligibleUnlockDevicesResponse()); + EXPECT_EQ(kSuccessResult, GetResultAndReset()); + VerifyDeviceEligibility(); +} + +TEST_F(DeviceCapabilityManagerTest, TestMultipleIsPromotableRequests) { + IsPromotableDevice(DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY, + test_eligible_external_devices_infos_[0].public_key()); + IsPromotableDevice(DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY, + test_eligible_external_devices_infos_[1].public_key()); + IsPromotableDevice(DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY, + test_eligible_external_devices_infos_[2].public_key()); + + InvokeFindEligibleForPromotionCallback(true /*eligible*/); + EXPECT_EQ(kSuccessResult, GetResultAndReset()); + EXPECT_TRUE(GetEligibleForPromotionAndReset()); + + InvokeFindEligibleForPromotionCallback(true /*eligible*/); + EXPECT_EQ(kSuccessResult, GetResultAndReset()); + EXPECT_TRUE(GetEligibleForPromotionAndReset()); + + InvokeErrorCallback(); + EXPECT_EQ(kErrorFindEligibleForPromotion, GetResultAndReset()); +} + +TEST_F(DeviceCapabilityManagerTest, TestOrderViaMultipleErrors) { + SetCapabilityEnabled( + DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY, + test_eligible_external_devices_infos_[0], true /* enable */); + FindEligibleDevicesForCapability( + DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY); + IsPromotableDevice(DeviceCapabilityManager::Capability::CAPABILITY_UNLOCK_KEY, + test_eligible_external_devices_infos_[0].public_key()); + + InvokeErrorCallback(); + EXPECT_EQ(kErrorOnToggleEasyUnlockResult, GetResultAndReset()); + + InvokeErrorCallback(); + EXPECT_EQ(kErrorFindEligibleUnlockDevices, GetResultAndReset()); + + InvokeErrorCallback(); + EXPECT_EQ(kErrorFindEligibleForPromotion, GetResultAndReset()); +} + +} // namespace cryptauth \ No newline at end of file
diff --git a/components/download/internal/test/BUILD.gn b/components/download/internal/test/BUILD.gn index d19de3c..1ea6557 100644 --- a/components/download/internal/test/BUILD.gn +++ b/components/download/internal/test/BUILD.gn
@@ -18,6 +18,8 @@ "mock_client.h", "mock_controller.cc", "mock_controller.h", + "mock_download_service.cc", + "mock_download_service.h", "mock_model_client.cc", "mock_model_client.h", "noop_store.cc", @@ -26,6 +28,8 @@ "test_device_status_listener.h", "test_download_driver.cc", "test_download_driver.h", + "test_download_service.cc", + "test_download_service.h", "test_store.cc", "test_store.h", ]
diff --git a/components/download/internal/test/mock_download_service.cc b/components/download/internal/test/mock_download_service.cc new file mode 100644 index 0000000..7d8fb911 --- /dev/null +++ b/components/download/internal/test/mock_download_service.cc
@@ -0,0 +1,15 @@ +// 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 "components/download/internal/test/mock_download_service.h" + +namespace download { +namespace test { + +MockDownloadService::MockDownloadService() = default; + +MockDownloadService::~MockDownloadService() = default; + +} // namespace test +} // namespace download
diff --git a/components/download/internal/test/mock_download_service.h b/components/download/internal/test/mock_download_service.h new file mode 100644 index 0000000..b74a42243 --- /dev/null +++ b/components/download/internal/test/mock_download_service.h
@@ -0,0 +1,43 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_DOWNLOAD_INTERNAL_TEST_MOCK_DOWNLOAD_SERVICE_H_ +#define COMPONENTS_DOWNLOAD_INTERNAL_TEST_MOCK_DOWNLOAD_SERVICE_H_ + +#include "base/macros.h" +#include "components/download/public/download_params.h" +#include "components/download/public/download_service.h" +#include "components/download/public/service_config.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace download { +namespace test { + +class MockDownloadService : public DownloadService { + public: + MockDownloadService(); + ~MockDownloadService() override; + + // DownloadService implementation. + MOCK_METHOD0(GetConfig, const ServiceConfig&()); + MOCK_METHOD2(OnStartScheduledTask, + void(DownloadTaskType task_type, + const TaskFinishedCallback& callback)); + MOCK_METHOD1(OnStopScheduledTask, bool(DownloadTaskType task_type)); + MOCK_METHOD0(GetStatus, ServiceStatus()); + MOCK_METHOD1(StartDownload, void(const DownloadParams& download_params)); + MOCK_METHOD1(PauseDownload, void(const std::string& guid)); + MOCK_METHOD1(ResumeDownload, void(const std::string& guid)); + MOCK_METHOD1(CancelDownload, void(const std::string& guid)); + MOCK_METHOD2(ChangeDownloadCriteria, + void(const std::string& guid, const SchedulingParams& params)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockDownloadService); +}; + +} // namespace test +} // namespace download + +#endif // COMPONENTS_DOWNLOAD_INTERNAL_TEST_MOCK_DOWNLOAD_SERVICE_H_
diff --git a/components/download/internal/test/test_download_service.cc b/components/download/internal/test/test_download_service.cc new file mode 100644 index 0000000..7471e4f3 --- /dev/null +++ b/components/download/internal/test/test_download_service.cc
@@ -0,0 +1,145 @@ +// 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 "components/download/internal/test/test_download_service.h" + +#include "base/bind.h" +#include "base/threading/thread_task_runner_handle.h" +#include "components/download/public/client.h" +#include "components/download/public/download_params.h" +#include "components/download/public/download_service.h" +#include "components/download/public/service_config.h" + +namespace download { +namespace test { + +namespace { + +// Implementation of ServiceConfig used for testing. +class TestServiceConfig : public ServiceConfig { + public: + TestServiceConfig() = default; + ~TestServiceConfig() override = default; + + uint32_t GetMaxScheduledDownloadsPerClient() const override { return 0; } + const base::TimeDelta& GetFileKeepAliveTime() const override { + return time_delta_; + } + + private: + base::TimeDelta time_delta_; +}; + +} // namespace + +TestDownloadService::TestDownloadService() + : is_ready_(false), + fail_at_start_(false), + service_config_(base::MakeUnique<TestServiceConfig>()), + file_size_(123456789u), + client_(nullptr) {} + +TestDownloadService::~TestDownloadService() = default; + +const ServiceConfig& TestDownloadService::GetConfig() { + return *service_config_; +} + +void TestDownloadService::OnStartScheduledTask( + DownloadTaskType task_type, + const TaskFinishedCallback& callback) {} + +bool TestDownloadService::OnStopScheduledTask(DownloadTaskType task_type) { + return true; +} + +DownloadService::ServiceStatus TestDownloadService::GetStatus() { + return is_ready_ ? DownloadService::ServiceStatus::READY + : DownloadService::ServiceStatus::STARTING_UP; +} + +void TestDownloadService::StartDownload(const DownloadParams& download_params) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&TestDownloadService::HandleStartDownload, + base::Unretained(this), download_params)); +} + +void TestDownloadService::PauseDownload(const std::string& guid) {} + +void TestDownloadService::ResumeDownload(const std::string& guid) {} + +void TestDownloadService::CancelDownload(const std::string& guid) { + for (auto iter = downloads_.begin(); iter != downloads_.end(); ++iter) { + if (iter->guid == guid) { + downloads_.erase(iter); + iter->callback.Run(iter->guid, + DownloadParams::StartResult::UNEXPECTED_GUID); + return; + } + } +} + +void TestDownloadService::ChangeDownloadCriteria( + const std::string& guid, + const SchedulingParams& params) {} + +void TestDownloadService::SetFailedDownload( + const std::string& failed_download_id, + bool fail_at_start) { + failed_download_id_ = failed_download_id; + fail_at_start_ = fail_at_start; +} + +void TestDownloadService::HandleStartDownload(const DownloadParams& params) { + if (!is_ready_) { + params.callback.Run(params.guid, + DownloadParams::StartResult::INTERNAL_ERROR); + return; + } + + if (!failed_download_id_.empty() && fail_at_start_) { + params.callback.Run(params.guid, + DownloadParams::StartResult::UNEXPECTED_GUID); + return; + } + + params.callback.Run(params.guid, DownloadParams::StartResult::ACCEPTED); + + downloads_.push_back(params); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&TestDownloadService::ProcessDownload, + base::Unretained(this))); +} + +void TestDownloadService::ProcessDownload() { + DCHECK(!fail_at_start_); + if (!is_ready_ || downloads_.empty()) + return; + + DownloadParams params = downloads_.front(); + downloads_.pop_front(); + + if (!failed_download_id_.empty() && params.guid == failed_download_id_) { + OnDownloadFailed(params.guid, Client::FailureReason::ABORTED); + } else { + OnDownloadSucceeded(params.guid, base::FilePath(), file_size_); + } +} + +void TestDownloadService::OnDownloadSucceeded(const std::string& guid, + const base::FilePath& file_path, + uint64_t file_size) { + if (client_) + client_->OnDownloadSucceeded(guid, file_path, file_size); +} + +void TestDownloadService::OnDownloadFailed( + const std::string& guid, + Client::FailureReason failure_reason) { + if (client_) + client_->OnDownloadFailed(guid, failure_reason); +} + +} // namespace test +} // namespace download
diff --git a/components/download/internal/test/test_download_service.h b/components/download/internal/test/test_download_service.h new file mode 100644 index 0000000..361d55d --- /dev/null +++ b/components/download/internal/test/test_download_service.h
@@ -0,0 +1,76 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_DOWNLOAD_INTERNAL_TEST_TEST_DOWNLOAD_SERVICE_H_ +#define COMPONENTS_DOWNLOAD_INTERNAL_TEST_TEST_DOWNLOAD_SERVICE_H_ + +#include <list> + +#include "components/download/public/client.h" +#include "components/download/public/download_params.h" +#include "components/download/public/download_service.h" + +namespace download { +namespace test { + +// Implementation of DownloadService used for testing. +class TestDownloadService : public DownloadService { + public: + explicit TestDownloadService(); + ~TestDownloadService() override; + + // DownloadService implementation. + const ServiceConfig& GetConfig() override; + void OnStartScheduledTask(DownloadTaskType task_type, + const TaskFinishedCallback& callback) override; + bool OnStopScheduledTask(DownloadTaskType task_type) override; + DownloadService::ServiceStatus GetStatus() override; + void StartDownload(const DownloadParams& download_params) override; + void PauseDownload(const std::string& guid) override; + void ResumeDownload(const std::string& guid) override; + void CancelDownload(const std::string& guid) override; + void ChangeDownloadCriteria(const std::string& guid, + const SchedulingParams& params) override; + + void set_is_ready(bool is_ready) { is_ready_ = is_ready; } + + void set_client(Client* client) { client_ = client; } + + private: + // Set failed_download_id and fail_at_start. + void SetFailedDownload(const std::string& failed_download_id, + bool fail_at_start); + + // Raise success/failure events based on the starting of the download. + void HandleStartDownload(const DownloadParams& params); + + // Begin the download, raising success/failure events. + void ProcessDownload(); + + // Notify the observer a download has succeeded. + void OnDownloadSucceeded(const std::string& guid, + const base::FilePath& file_path, + uint64_t file_size); + + // Notify the observer a download has failed. + void OnDownloadFailed(const std::string& guid, + Client::FailureReason failure_reason); + + bool is_ready_; + std::string failed_download_id_; + bool fail_at_start_; + std::unique_ptr<ServiceConfig> service_config_; + uint64_t file_size_; + + Client* client_; + + std::list<DownloadParams> downloads_; + + DISALLOW_COPY_AND_ASSIGN(TestDownloadService); +}; + +} // namespace test +} // namespace download + +#endif // COMPONENTS_DOWNLOAD_INTERNAL_TEST_TEST_DOWNLOAD_SERVICE_H_
diff --git a/components/exo/notification_surface.cc b/components/exo/notification_surface.cc index 79f613b..73f7735 100644 --- a/components/exo/notification_surface.cc +++ b/components/exo/notification_surface.cc
@@ -7,73 +7,14 @@ #include "components/exo/notification_surface_manager.h" #include "components/exo/surface.h" #include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/base/cursor/cursor.h" -#include "ui/base/hit_test.h" #include "ui/gfx/geometry/rect.h" -#include "ui/views/widget/widget.h" namespace exo { -namespace { - -class CustomWindowDelegate : public aura::WindowDelegate { - public: - explicit CustomWindowDelegate(NotificationSurface* notification_surface) - : notification_surface_(notification_surface) {} - ~CustomWindowDelegate() override {} - - // Overridden from aura::WindowDelegate: - gfx::Size GetMinimumSize() const override { return gfx::Size(); } - gfx::Size GetMaximumSize() const override { return gfx::Size(); } - void OnBoundsChanged(const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) override {} - gfx::NativeCursor GetCursor(const gfx::Point& point) override { - return notification_surface_->GetCursor(point); - } - int GetNonClientComponent(const gfx::Point& point) const override { - return HTNOWHERE; - } - bool ShouldDescendIntoChildForEventHandling( - aura::Window* child, - const gfx::Point& location) override { - return true; - } - bool CanFocus() override { return true; } - void OnCaptureLost() override {} - void OnPaint(const ui::PaintContext& context) override {} - void OnDeviceScaleFactorChanged(float device_scale_factor) override {} - void OnWindowDestroying(aura::Window* window) override {} - void OnWindowDestroyed(aura::Window* window) override { delete this; } - void OnWindowTargetVisibilityChanged(bool visible) override {} - bool HasHitTestMask() const override { - return notification_surface_->HasHitTestMask(); - } - void GetHitTestMask(gfx::Path* mask) const override { - notification_surface_->GetHitTestMask(mask); - } - void OnKeyEvent(ui::KeyEvent* event) override { - // Propagates the key event upto the top-level views Widget so that we can - // trigger proper events in the views/ash level there. Event handling for - // Surfaces is done in a post event handler in keyboard.cc. - views::Widget* widget = views::Widget::GetTopLevelWidgetForNativeView( - notification_surface_->host_window()); - if (widget) - widget->OnKeyEvent(event); - } - - private: - NotificationSurface* const notification_surface_; - - DISALLOW_COPY_AND_ASSIGN(CustomWindowDelegate); -}; - -} // namespace - NotificationSurface::NotificationSurface(NotificationSurfaceManager* manager, Surface* surface, const std::string& notification_key) - : SurfaceTreeHost("ExoNotificationSurface", new CustomWindowDelegate(this)), + : SurfaceTreeHost("ExoNotificationSurface", nullptr), manager_(manager), notification_key_(notification_key) { surface->AddSurfaceObserver(this);
diff --git a/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.cc b/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.cc index 1d9a9ff..eae331d 100644 --- a/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.cc +++ b/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.cc
@@ -74,6 +74,7 @@ void BreakingNewsGCMAppHandler::StartListening( OnNewRemoteSuggestionCallback on_new_remote_suggestion_callback) { + DCHECK(!IsListening()); DCHECK(!on_new_remote_suggestion_callback.is_null()); on_new_remote_suggestion_callback_ = std::move(on_new_remote_suggestion_callback); @@ -91,6 +92,10 @@ subscription_manager_->Unsubscribe(); } +bool BreakingNewsGCMAppHandler::IsListening() const { + return !on_new_remote_suggestion_callback_.is_null(); +} + void BreakingNewsGCMAppHandler::Subscribe(bool force_token_retrieval) { // TODO(mamir): "Whether to subscribe to content suggestions server" logic // should be moved to the SubscriptionManager. @@ -283,8 +288,4 @@ << " when parsing:" << json_str; } -bool BreakingNewsGCMAppHandler::IsListening() const { - return !on_new_remote_suggestion_callback_.is_null(); -} - } // namespace ntp_snippets
diff --git a/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.h b/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.h index 64a3b958..63d00e98 100644 --- a/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.h +++ b/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.h
@@ -62,6 +62,7 @@ void StartListening( OnNewRemoteSuggestionCallback on_new_remote_suggestion_callback) override; void StopListening() override; + bool IsListening() const override; // GCMAppHandler overrides. void ShutdownHandler() override; @@ -106,8 +107,6 @@ // error. void OnJsonError(const std::string& json_str, const std::string& error); - bool IsListening() const; - gcm::GCMDriver* const gcm_driver_; instance_id::InstanceIDDriver* const instance_id_driver_; PrefService* const pref_service_;
diff --git a/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler_unittest.cc b/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler_unittest.cc index 6f288bb..a08ef486 100644 --- a/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler_unittest.cc +++ b/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler_unittest.cc
@@ -33,6 +33,7 @@ using instance_id::InstanceID; using instance_id::InstanceIDDriver; using testing::_; +using testing::AnyNumber; using testing::AtMost; using testing::NiceMock; using testing::StrictMock; @@ -466,4 +467,71 @@ task_runner->RunUntilIdle(); } +TEST_F(BreakingNewsGCMAppHandlerTest, + IsListeningShouldReturnFalseBeforeListening) { + scoped_refptr<TestMockTimeTaskRunner> task_runner( + new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now())); + auto handler = MakeHandler(task_runner); + + EXPECT_FALSE(handler->IsListening()); +} + +TEST_F(BreakingNewsGCMAppHandlerTest, + IsListeningShouldReturnTrueAfterStartListening) { + scoped_refptr<TestMockTimeTaskRunner> task_runner( + new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now())); + auto handler = MakeHandler(task_runner); + ASSERT_FALSE(handler->IsListening()); + + EXPECT_CALL(*mock_instance_id(), GetToken(_, _, _, _)) + .WillRepeatedly( + InvokeCallbackArgument<3>("token", InstanceID::Result::SUCCESS)); + handler->StartListening( + base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {})); + + EXPECT_TRUE(handler->IsListening()); +} + +TEST_F(BreakingNewsGCMAppHandlerTest, + IsListeningShouldReturnFalseAfterStopListening) { + scoped_refptr<TestMockTimeTaskRunner> task_runner( + new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now())); + auto handler = MakeHandler(task_runner); + ASSERT_FALSE(handler->IsListening()); + + EXPECT_CALL(*mock_instance_id(), GetToken(_, _, _, _)) + .WillRepeatedly( + InvokeCallbackArgument<3>("token", InstanceID::Result::SUCCESS)); + handler->StartListening( + base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {})); + ASSERT_TRUE(handler->IsListening()); + + handler->StopListening(); + + EXPECT_FALSE(handler->IsListening()); +} + +TEST_F(BreakingNewsGCMAppHandlerTest, + IsListeningShouldReturnTrueAfterSecondStartListening) { + scoped_refptr<TestMockTimeTaskRunner> task_runner( + new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now())); + auto handler = MakeHandler(task_runner); + ASSERT_FALSE(handler->IsListening()); + + EXPECT_CALL(*mock_instance_id(), GetToken(_, _, _, _)) + .WillRepeatedly( + InvokeCallbackArgument<3>("token", InstanceID::Result::SUCCESS)); + handler->StartListening( + base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {})); + ASSERT_TRUE(handler->IsListening()); + + handler->StopListening(); + ASSERT_FALSE(handler->IsListening()); + + handler->StartListening( + base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {})); + + EXPECT_TRUE(handler->IsListening()); +} + } // namespace ntp_snippets
diff --git a/components/ntp_snippets/breaking_news/breaking_news_listener.h b/components/ntp_snippets/breaking_news/breaking_news_listener.h index 3647ce91..e2fbaaf3 100644 --- a/components/ntp_snippets/breaking_news/breaking_news_listener.h +++ b/components/ntp_snippets/breaking_news/breaking_news_listener.h
@@ -27,6 +27,8 @@ // Stop listening for incoming breaking news. Any further pushed breaking news // will be ignored. Must be called while listening. virtual void StopListening() = 0; + + virtual bool IsListening() const = 0; }; } // namespace ntp_snippets
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc b/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc index 27fa5cf7..95056fe 100644 --- a/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc +++ b/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc
@@ -287,12 +287,6 @@ observer->OnCategoryStatusChanged(this, entry.first, entry.second.status); } - if (breaking_news_raw_data_provider_) { - breaking_news_raw_data_provider_->StartListening( - base::Bind(&RemoteSuggestionsProviderImpl::PrependArticleSuggestion, - base::Unretained(this))); - } - if (database_->IsErrorState()) { EnterState(State::ERROR_OCCURRED); UpdateAllCategoryStatus(CategoryStatus::LOADING_ERROR); @@ -311,7 +305,8 @@ } RemoteSuggestionsProviderImpl::~RemoteSuggestionsProviderImpl() { - if (breaking_news_raw_data_provider_) { + if (breaking_news_raw_data_provider_ && + breaking_news_raw_data_provider_->IsListening()) { breaking_news_raw_data_provider_->StopListening(); } } @@ -1085,10 +1080,21 @@ UpdateCategoryStatus(category, CategoryStatus::AVAILABLE); } } + + if (breaking_news_raw_data_provider_) { + DCHECK(!breaking_news_raw_data_provider_->IsListening()); + breaking_news_raw_data_provider_->StartListening( + base::Bind(&RemoteSuggestionsProviderImpl::PrependArticleSuggestion, + base::Unretained(this))); + } } void RemoteSuggestionsProviderImpl::EnterStateDisabled() { ClearSuggestions(); + if (breaking_news_raw_data_provider_ && + breaking_news_raw_data_provider_->IsListening()) { + breaking_news_raw_data_provider_->StopListening(); + } } void RemoteSuggestionsProviderImpl::EnterStateError() {
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc index c6b0aa8..3e04e527 100644 --- a/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc +++ b/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
@@ -51,6 +51,7 @@ #include "components/ntp_snippets/remote/remote_suggestions_database.h" #include "components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h" #include "components/ntp_snippets/remote/remote_suggestions_scheduler.h" +#include "components/ntp_snippets/remote/remote_suggestions_status_service.h" #include "components/ntp_snippets/remote/remote_suggestions_status_service_impl.h" #include "components/ntp_snippets/remote/test_utils.h" #include "components/ntp_snippets/time_serialization.h" @@ -72,6 +73,8 @@ using ntp_snippets::test::FetchedCategoryBuilder; using ntp_snippets::test::RemoteSuggestionBuilder; using testing::_; +using testing::AnyNumber; +using testing::AtMost; using testing::Contains; using testing::CreateFunctor; using testing::ElementsAre; @@ -272,10 +275,39 @@ MOCK_CONST_METHOD1(PrefetchedOfflinePageExists, bool(const GURL& url)); }; -class MockBreakingNewsListener : public BreakingNewsListener { +class FakeBreakingNewsListener : public BreakingNewsListener { public: - MOCK_METHOD1(StartListening, void(OnNewRemoteSuggestionCallback callback)); - MOCK_METHOD0(StopListening, void()); + ~FakeBreakingNewsListener() override = default; + + // BreakingNewsListener implementation. + void StartListening(OnNewRemoteSuggestionCallback callback) override { + on_new_remote_suggestion_callback_ = callback; + } + + void StopListening() override { + on_new_remote_suggestion_callback_ = OnNewRemoteSuggestionCallback(); + } + + bool IsListening() const override { + return !on_new_remote_suggestion_callback_.is_null(); + } + + void PushSuggestion(std::unique_ptr<RemoteSuggestion> suggestion) { + EXPECT_TRUE(IsListening()); + on_new_remote_suggestion_callback_.Run(std::move(suggestion)); + } + + private: + OnNewRemoteSuggestionCallback on_new_remote_suggestion_callback_; +}; + +class MockRemoteSuggestionsStatusService + : public RemoteSuggestionsStatusService { + public: + ~MockRemoteSuggestionsStatusService() override = default; + + MOCK_METHOD1(Init, void(const StatusChangeCallback& callback)); + MOCK_METHOD0(OnSignInStateChanged, void()); }; } // namespace @@ -306,10 +338,13 @@ // TODO(vitaliii): Rewrite this function to initialize a test class member // instead of creating a new provider. - std::unique_ptr<RemoteSuggestionsProviderImpl> MakeSuggestionsProvider() { + std::unique_ptr<RemoteSuggestionsProviderImpl> MakeSuggestionsProvider( + bool use_mock_prefetched_pages_tracker, + bool use_fake_breaking_news_listener, + bool use_mock_remote_suggestions_status_service) { auto provider = MakeSuggestionsProviderWithoutInitialization( - /*use_mock_prefetched_pages_tracker=*/false, - /*use_mock_breaking_news_listener=*/false); + use_mock_prefetched_pages_tracker, use_fake_breaking_news_listener, + use_mock_remote_suggestions_status_service); WaitForSuggestionsProviderInitialization(provider.get()); return provider; } @@ -317,7 +352,8 @@ std::unique_ptr<RemoteSuggestionsProviderImpl> MakeSuggestionsProviderWithoutInitialization( bool use_mock_prefetched_pages_tracker, - bool use_mock_breaking_news_listener) { + bool use_fake_breaking_news_listener, + bool use_mock_remote_suggestions_status_service) { scoped_refptr<base::SingleThreadTaskRunner> task_runner( base::ThreadTaskRunnerHandle::Get()); @@ -326,23 +362,38 @@ base::MakeUnique<StrictMock<MockRemoteSuggestionsFetcher>>(); mock_suggestions_fetcher_ = mock_suggestions_fetcher.get(); - std::unique_ptr<PrefetchedPagesTracker> prefetched_pages_tracker; + std::unique_ptr<StrictMock<MockPrefetchedPagesTracker>> + mock_prefetched_pages_tracker; if (use_mock_prefetched_pages_tracker) { - prefetched_pages_tracker = + mock_prefetched_pages_tracker = base::MakeUnique<StrictMock<MockPrefetchedPagesTracker>>(); } - prefetched_pages_tracker_ = prefetched_pages_tracker.get(); + mock_prefetched_pages_tracker_ = mock_prefetched_pages_tracker.get(); - std::unique_ptr<BreakingNewsListener> breaking_news_listener; - if (use_mock_breaking_news_listener) { - auto mock_breaking_news_listener = - base::MakeUnique<StrictMock<MockBreakingNewsListener>>(); - EXPECT_CALL(*mock_breaking_news_listener, StartListening(_)) - .WillOnce(SaveArg<0>(&on_new_remote_suggestion_callback_)); - EXPECT_CALL(*mock_breaking_news_listener, StopListening()); - breaking_news_listener = std::move(mock_breaking_news_listener); + std::unique_ptr<FakeBreakingNewsListener> fake_breaking_news_listener; + if (use_fake_breaking_news_listener) { + fake_breaking_news_listener = + base::MakeUnique<FakeBreakingNewsListener>(); } - breaking_news_listener_ = breaking_news_listener.get(); + fake_breaking_news_listener_ = fake_breaking_news_listener.get(); + + std::unique_ptr<RemoteSuggestionsStatusService> + remote_suggestions_status_service; + if (use_mock_remote_suggestions_status_service) { + auto mock_remote_suggestions_status_service = + base::MakeUnique<StrictMock<MockRemoteSuggestionsStatusService>>(); + EXPECT_CALL(*mock_remote_suggestions_status_service, Init(_)) + .WillOnce(SaveArg<0>(&status_change_callback_)); + remote_suggestions_status_service = + std::move(mock_remote_suggestions_status_service); + } else { + remote_suggestions_status_service = + base::MakeUnique<RemoteSuggestionsStatusServiceImpl>( + utils_.fake_signin_manager(), utils_.pref_service(), + std::string()); + } + remote_suggestions_status_service_ = + remote_suggestions_status_service.get(); auto image_fetcher = base::MakeUnique<NiceMock<MockImageFetcher>>(); @@ -359,9 +410,9 @@ observer_.get(), utils_.pref_service(), "fr", category_ranker_.get(), scheduler_.get(), std::move(mock_suggestions_fetcher), std::move(image_fetcher), std::move(database), - base::MakeUnique<RemoteSuggestionsStatusServiceImpl>( - utils_.fake_signin_manager(), utils_.pref_service(), std::string()), - std::move(prefetched_pages_tracker), std::move(breaking_news_listener)); + std::move(remote_suggestions_status_service), + std::move(mock_prefetched_pages_tracker), + std::move(fake_breaking_news_listener)); } std::unique_ptr<RemoteSuggestionsProviderImpl> @@ -369,7 +420,8 @@ scheduler_ = base::MakeUnique<StrictMock<MockScheduler>>(); return MakeSuggestionsProviderWithoutInitialization( /*use_mock_prefetched_pages_tracker=*/false, - /*use_mock_breaking_news_listener=*/false); + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); } void WaitForSuggestionsProviderInitialization( @@ -379,15 +431,18 @@ // TODO(treib): Find a better way to wait for initialization to finish. base::RunLoop().RunUntilIdle(); - EXPECT_NE(RemoteSuggestionsProviderImpl::State::NOT_INITED, - provider->state_); } void ResetSuggestionsProvider( - std::unique_ptr<RemoteSuggestionsProviderImpl>* provider) { + std::unique_ptr<RemoteSuggestionsProviderImpl>* provider, + bool use_mock_prefetched_pages_tracker, + bool use_fake_breaking_news_listener, + bool use_mock_remote_suggestions_status_service) { provider->reset(); observer_.reset(); - *provider = MakeSuggestionsProvider(); + *provider = MakeSuggestionsProvider( + use_mock_prefetched_pages_tracker, use_fake_breaking_news_listener, + use_mock_remote_suggestions_status_service); } void SetCategoryRanker(std::unique_ptr<CategoryRanker> category_ranker) { @@ -419,8 +474,8 @@ StrictMock<MockRemoteSuggestionsFetcher>* mock_suggestions_fetcher() { return mock_suggestions_fetcher_; } - PrefetchedPagesTracker* prefetched_pages_tracker() { - return prefetched_pages_tracker_; + StrictMock<MockPrefetchedPagesTracker>* mock_prefetched_pages_tracker() { + return mock_prefetched_pages_tracker_; } // TODO(tschumann): Make this a strict-mock. We want to avoid unneccesary // network requests. @@ -429,6 +484,9 @@ PrefService* pref_service() { return utils_.pref_service(); } RemoteSuggestionsDatabase* database() { return database_; } MockScheduler* scheduler() { return scheduler_.get(); } + FakeBreakingNewsListener* fake_breaking_news_listener() { + return fake_breaking_news_listener_; + }; void FetchTheseSuggestions( RemoteSuggestionsProviderImpl* provider, @@ -467,8 +525,14 @@ void PushArticleSuggestionToTheFront( std::unique_ptr<RemoteSuggestion> suggestion) { - EXPECT_FALSE(on_new_remote_suggestion_callback_.is_null()); - on_new_remote_suggestion_callback_.Run(std::move(suggestion)); + ASSERT_TRUE(fake_breaking_news_listener_); + fake_breaking_news_listener_->PushSuggestion(std::move(suggestion)); + } + + void ChangeRemoteSuggestionsStatus(RemoteSuggestionsStatus old_status, + RemoteSuggestionsStatus new_status) { + EXPECT_FALSE(status_change_callback_.is_null()); + status_change_callback_.Run(old_status, new_status); } void SetOrderNewRemoteCategoriesBasedOnArticlesCategoryParam(bool value) { @@ -510,14 +574,14 @@ UserClassifier user_classifier_; std::unique_ptr<FakeContentSuggestionsProviderObserver> observer_; StrictMock<MockRemoteSuggestionsFetcher>* mock_suggestions_fetcher_; - PrefetchedPagesTracker* prefetched_pages_tracker_; + StrictMock<MockPrefetchedPagesTracker>* mock_prefetched_pages_tracker_; NiceMock<MockImageFetcher>* image_fetcher_; FakeImageDecoder image_decoder_; std::unique_ptr<MockScheduler> scheduler_; - BreakingNewsListener* breaking_news_listener_; + FakeBreakingNewsListener* fake_breaking_news_listener_; + RemoteSuggestionsStatusService* remote_suggestions_status_service_; - BreakingNewsListener::OnNewRemoteSuggestionCallback - on_new_remote_suggestion_callback_; + RemoteSuggestionsStatusService::StatusChangeCallback status_change_callback_; base::ScopedTempDir database_dir_; RemoteSuggestionsDatabase* database_; @@ -526,7 +590,10 @@ }; TEST_F(RemoteSuggestionsProviderImplTest, Full) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); // TODO(vitaliii): Inline the vector creation in FetchTheseSuggestions. std::vector<FetchedCategory> fetched_categories; @@ -565,7 +632,10 @@ // Don't send an initial response -- we want to test what happens without any // server status. - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); // The articles category should be there by default, and have a title. CategoryInfo info_before = provider->GetCategoryInfo(articles_category()); @@ -601,7 +671,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, MultipleCategories) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( FetchedCategoryBuilder() @@ -668,7 +741,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, ArticleCategoryInfo) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); CategoryInfo article_info = provider->GetCategoryInfo(articles_category()); EXPECT_THAT(article_info.additional_action(), Eq(ContentSuggestionsAdditionalAction::FETCH)); @@ -676,7 +752,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, ExperimentalCategoryInfo) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( FetchedCategoryBuilder() @@ -731,7 +810,10 @@ EXPECT_CALL(*raw_mock_ranker, AppendCategoryIfNecessary(Category::FromRemoteCategory(12))); } - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); FetchTheseSuggestions(provider.get(), /*interactive_request=*/true, Status::Success(), std::move(fetched_categories)); } @@ -783,7 +865,10 @@ InsertCategoryAfterIfNecessary(Category::FromRemoteCategory(12), articles_category())); } - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); FetchTheseSuggestions(provider.get(), /*interactive_request=*/true, Status::Success(), std::move(fetched_categories)); } @@ -805,13 +890,19 @@ EXPECT_CALL(*raw_mock_ranker, InsertCategoryBeforeIfNecessary(_, _)).Times(0); EXPECT_CALL(*raw_mock_ranker, AppendCategoryIfNecessary(Category::FromRemoteCategory(11))); - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); FetchTheseSuggestions(provider.get(), /*interactive_request=*/true, Status::Success(), std::move(fetched_categories)); } TEST_F(RemoteSuggestionsProviderImplTest, PersistCategoryInfos) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( FetchedCategoryBuilder() @@ -838,7 +929,11 @@ Category::FromRemoteCategory(kUnknownRemoteCategoryId)); // Recreate the provider to simulate a Chrome restart. - ResetSuggestionsProvider(&provider); + ResetSuggestionsProvider( + &provider, + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); // The categories should have been restored. ASSERT_NE(observer().StatusForCategory(articles_category()), @@ -864,7 +959,10 @@ TEST_F(RemoteSuggestionsProviderImplTest, PersistRemoteCategoryOrder) { // We create a provider with a normal ranker to store the order. - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( FetchedCategoryBuilder() @@ -906,11 +1004,18 @@ EXPECT_CALL(*raw_mock_ranker, AppendCategoryIfNecessary(Category::FromRemoteCategory(12))); } - ResetSuggestionsProvider(&provider); + ResetSuggestionsProvider( + &provider, + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); } TEST_F(RemoteSuggestionsProviderImplTest, PersistSuggestions) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( FetchedCategoryBuilder() @@ -932,7 +1037,11 @@ ASSERT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1)); // Recreate the provider to simulate a Chrome restart. - ResetSuggestionsProvider(&provider); + ResetSuggestionsProvider( + &provider, + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); // The suggestions in both categories should have been restored. EXPECT_THAT(observer().SuggestionsForCategory(articles_category()), @@ -942,7 +1051,10 @@ TEST_F(RemoteSuggestionsProviderImplTest, DontNotifyIfNotAvailable) { // Get some suggestions into the database. - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( FetchedCategoryBuilder() @@ -967,7 +1079,11 @@ pref_service()->SetBoolean(prefs::kEnableSnippets, false); // Recreate the provider to simulate a Chrome start. - ResetSuggestionsProvider(&provider); + ResetSuggestionsProvider( + &provider, + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); ASSERT_THAT(RemoteSuggestionsProviderImpl::State::DISABLED, Eq(provider->state_)); @@ -979,7 +1095,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, Clear) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( @@ -999,7 +1118,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, ReplaceSuggestions) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::string first("http://first"); std::vector<FetchedCategory> fetched_categories; @@ -1029,7 +1151,10 @@ TEST_F(RemoteSuggestionsProviderImplTest, ShouldResolveFetchedSuggestionThumbnail) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( @@ -1055,7 +1180,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, ShouldFetchMore) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( @@ -1088,7 +1216,10 @@ TEST_F(RemoteSuggestionsProviderImplTest, ShouldResolveFetchedMoreSuggestionThumbnail) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( @@ -1124,10 +1255,10 @@ // should not add any suggestions to B. TEST_F(RemoteSuggestionsProviderImplTest, ShouldNotChangeSuggestionsInOtherSurfacesWhenFetchingMore) { - auto provider = MakeSuggestionsProviderWithoutInitialization( + auto provider = MakeSuggestionsProvider( /*use_mock_prefetched_pages_tracker=*/false, - /*use_mock_breaking_news_listener=*/false); - WaitForSuggestionsProviderInitialization(provider.get()); + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); // Fetch a suggestion. std::vector<FetchedCategory> fetched_categories; @@ -1178,10 +1309,10 @@ // there as well. TEST_F(RemoteSuggestionsProviderImplTest, ShouldNotAffectFetchMoreInOtherSurfacesWhenFetchingMore) { - auto provider = MakeSuggestionsProviderWithoutInitialization( + auto provider = MakeSuggestionsProvider( /*use_mock_prefetched_pages_tracker=*/false, - /*use_mock_breaking_news_listener=*/false); - WaitForSuggestionsProviderInitialization(provider.get()); + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); // Fetch more on the surface A. std::vector<FetchedCategory> fetched_categories; @@ -1247,7 +1378,10 @@ TEST_F(RemoteSuggestionsProviderImplTest, ClearHistoryShouldDeleteArchivedSuggestions) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); // First get suggestions into the archived state which happens through // subsequent fetches. Then we verify the entries are gone from the 'archived' // state by trying to load their images (and we shouldn't even know the URLs @@ -1316,7 +1450,8 @@ TEST_F(RemoteSuggestionsProviderImplTest, ReturnFetchRequestEmptyBeforeInit) { auto provider = MakeSuggestionsProviderWithoutInitialization( /*use_mock_prefetched_pages_tracker=*/false, - /*use_mock_breaking_news_listener=*/false); + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); RemoteSuggestionsFetcher::SnippetsAvailableCallback snippets_callback; EXPECT_CALL(*mock_suggestions_fetcher(), FetchSnippets(_, _)).Times(0); MockFunction<void(Status, const std::vector<ContentSuggestion>&)> loaded; @@ -1329,7 +1464,10 @@ TEST_F(RemoteSuggestionsProviderImplTest, ShouldForwardTemporaryErrorFromFetcher) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); RemoteSuggestionsFetcher::SnippetsAvailableCallback snippets_callback; MockFunction<void(Status, const std::vector<ContentSuggestion>&)> loaded; @@ -1352,7 +1490,10 @@ TEST_F(RemoteSuggestionsProviderImplTest, ShouldNotAddNewSuggestionsAfterFetchError) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); FetchTheseSuggestions( provider.get(), /*interactive_request=*/false, @@ -1364,7 +1505,10 @@ TEST_F(RemoteSuggestionsProviderImplTest, ShouldNotClearOldSuggestionsAfterFetchError) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back(FetchedCategory( @@ -1391,7 +1535,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, Dismiss) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; const FetchedCategoryBuilder category_builder = @@ -1443,7 +1590,11 @@ IsEmpty()); // The suggestion should stay dismissed even after re-creating the provider. - ResetSuggestionsProvider(&provider); + ResetSuggestionsProvider( + &provider, + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); fetched_categories.clear(); fetched_categories.push_back(category_builder.Build()); FetchTheseSuggestions(provider.get(), /*interactive_request=*/true, @@ -1464,7 +1615,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, GetDismissed) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( @@ -1508,7 +1662,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, RemoveExpiredDismissedContent) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( @@ -1556,7 +1713,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, ExpiredContentNotRemoved) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( @@ -1573,7 +1733,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, TestSingleSource) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( @@ -1599,7 +1762,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, TestSingleSourceWithMissingData) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( @@ -1616,7 +1782,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, LogNumArticlesHistogram) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); base::HistogramTester tester; @@ -1700,7 +1869,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, DismissShouldRespectAllKnownUrls) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); const std::vector<std::string> source_urls = { "http://mashable.com/2016/05/11/stolen", @@ -1750,7 +1922,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, ImageReturnedWithTheSameId) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( @@ -1783,7 +1958,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, EmptyImageReturnedForNonExistentId) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); // Create a non-empty image so that we can test the image gets updated. gfx::Image image = gfx::test::CreateImage(1, 1); @@ -1804,7 +1982,10 @@ // Testing that the provider is not accessing the database is tricky. // Therefore, we simply put in some data making sure that if the provider asks // the database, it will get a wrong answer. - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); ContentSuggestion::ID unknown_id = MakeArticleID(kSuggestionUrl2); database()->SaveImage(unknown_id.id_within_category(), "some image blob"); @@ -1826,7 +2007,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, ClearHistoryRemovesAllSuggestions) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( @@ -1864,7 +2048,10 @@ ShouldKeepArticlesCategoryAvailableAfterClearHistory) { // If the provider marks that category as NOT_PROVIDED, then it won't be shown // at all in the UI and the user cannot load new data :-/. - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); ASSERT_THAT(observer().StatusForCategory(articles_category()), Eq(CategoryStatus::AVAILABLE)); @@ -1876,7 +2063,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, ShouldClearOrphanedImagesOnRestart) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( @@ -1912,7 +2102,11 @@ // The image should still be available until a restart happens. EXPECT_FALSE( FetchImage(provider.get(), MakeArticleID(kSuggestionUrl)).IsEmpty()); - ResetSuggestionsProvider(&provider); + ResetSuggestionsProvider( + &provider, + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); // After the restart, the image should be garbage collected. EXPECT_TRUE( FetchImage(provider.get(), MakeArticleID(kSuggestionUrl)).IsEmpty()); @@ -1920,7 +2114,10 @@ TEST_F(RemoteSuggestionsProviderImplTest, ShouldHandleMoreThanMaxSuggestionsInResponse) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; FetchedCategoryBuilder category_builder; @@ -1945,7 +2142,8 @@ // not be initialized until the test clock is set. auto provider = MakeSuggestionsProviderWithoutInitialization( /*use_mock_prefetched_pages_tracker=*/false, - /*use_mock_breaking_news_listener=*/false); + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); auto simple_test_clock = base::MakeUnique<base::SimpleTestClock>(); base::SimpleTestClock* simple_test_clock_ptr = simple_test_clock.get(); @@ -2054,10 +2252,10 @@ TEST_F(RemoteSuggestionsProviderImplTest, ShouldExcludeKnownSuggestionsWithoutTruncatingWhenFetchingMore) { - auto provider = MakeSuggestionsProviderWithoutInitialization( + auto provider = MakeSuggestionsProvider( /*use_mock_prefetched_pages_tracker=*/false, - /*use_mock_breaking_news_listener=*/false); - WaitForSuggestionsProviderInitialization(provider.get()); + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::set<std::string> known_ids; for (int i = 0; i < 200; ++i) { @@ -2077,10 +2275,10 @@ TEST_F(RemoteSuggestionsProviderImplTest, ShouldExcludeDismissedSuggestionsWhenFetchingMore) { - auto provider = MakeSuggestionsProviderWithoutInitialization( + auto provider = MakeSuggestionsProvider( /*use_mock_prefetched_pages_tracker=*/false, - /*use_mock_breaking_news_listener=*/false); - WaitForSuggestionsProviderInitialization(provider.get()); + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( @@ -2111,10 +2309,10 @@ TEST_F(RemoteSuggestionsProviderImplTest, ShouldTruncateExcludedDismissedSuggestionsWhenFetchingMore) { - auto provider = MakeSuggestionsProviderWithoutInitialization( + auto provider = MakeSuggestionsProvider( /*use_mock_prefetched_pages_tracker=*/false, - /*use_mock_breaking_news_listener=*/false); - WaitForSuggestionsProviderInitialization(provider.get()); + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; FetchedCategoryBuilder category_builder; @@ -2149,10 +2347,10 @@ TEST_F(RemoteSuggestionsProviderImplTest, ShouldPreferLatestExcludedDismissedSuggestionsWhenFetchingMore) { - auto provider = MakeSuggestionsProviderWithoutInitialization( + auto provider = MakeSuggestionsProvider( /*use_mock_prefetched_pages_tracker=*/false, - /*use_mock_breaking_news_listener=*/false); - WaitForSuggestionsProviderInitialization(provider.get()); + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; FetchedCategoryBuilder category_builder; @@ -2194,10 +2392,10 @@ TEST_F(RemoteSuggestionsProviderImplTest, ShouldExcludeDismissedSuggestionsFromAllCategoriesWhenFetchingMore) { - auto provider = MakeSuggestionsProviderWithoutInitialization( + auto provider = MakeSuggestionsProvider( /*use_mock_prefetched_pages_tracker=*/false, - /*use_mock_breaking_news_listener=*/false); - WaitForSuggestionsProviderInitialization(provider.get()); + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); // Add article suggestions. std::vector<FetchedCategory> fetched_categories; @@ -2251,10 +2449,10 @@ TEST_F(RemoteSuggestionsProviderImplTest, ShouldPreferTargetCategoryExcludedDismissedSuggestionsWhenFetchingMore) { - auto provider = MakeSuggestionsProviderWithoutInitialization( + auto provider = MakeSuggestionsProvider( /*use_mock_prefetched_pages_tracker=*/false, - /*use_mock_breaking_news_listener=*/false); - WaitForSuggestionsProviderInitialization(provider.get()); + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); // Add article suggestions. std::vector<FetchedCategory> fetched_categories; @@ -2309,7 +2507,10 @@ kMaxAdditionalPrefetchedSuggestions, kMaxAgeForAdditionalPrefetchedSuggestion); - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( FetchedCategoryBuilder() @@ -2328,12 +2529,12 @@ kMaxAdditionalPrefetchedSuggestions, kMaxAgeForAdditionalPrefetchedSuggestion); - auto provider = MakeSuggestionsProviderWithoutInitialization( + auto provider = MakeSuggestionsProvider( /*use_mock_prefetched_pages_tracker=*/true, - /*use_mock_breaking_news_listener=*/false); - auto* mock_tracker = static_cast<StrictMock<MockPrefetchedPagesTracker>*>( - prefetched_pages_tracker()); - WaitForSuggestionsProviderInitialization(provider.get()); + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); + StrictMock<MockPrefetchedPagesTracker>* mock_tracker = + mock_prefetched_pages_tracker(); EXPECT_CALL(*mock_tracker, IsInitialized()).WillRepeatedly(Return(true)); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( @@ -2380,12 +2581,12 @@ kMaxAdditionalPrefetchedSuggestions, kMaxAgeForAdditionalPrefetchedSuggestion); - auto provider = MakeSuggestionsProviderWithoutInitialization( + auto provider = MakeSuggestionsProvider( /*use_mock_prefetched_pages_tracker=*/true, - /*use_mock_breaking_news_listener=*/false); - auto* mock_tracker = static_cast<StrictMock<MockPrefetchedPagesTracker>*>( - prefetched_pages_tracker()); - WaitForSuggestionsProviderInitialization(provider.get()); + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); + StrictMock<MockPrefetchedPagesTracker>* mock_tracker = + mock_prefetched_pages_tracker(); EXPECT_CALL(*mock_tracker, IsInitialized()).WillRepeatedly(Return(true)); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( @@ -2432,9 +2633,10 @@ auto provider = MakeSuggestionsProviderWithoutInitialization( /*use_mock_prefetched_pages_tracker=*/true, - /*use_mock_breaking_news_listener=*/false); - auto* mock_tracker = static_cast<StrictMock<MockPrefetchedPagesTracker>*>( - prefetched_pages_tracker()); + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); + StrictMock<MockPrefetchedPagesTracker>* mock_tracker = + mock_prefetched_pages_tracker(); WaitForSuggestionsProviderInitialization(provider.get()); const int prefetched_suggestions_count = @@ -2486,12 +2688,12 @@ kMaxAdditionalPrefetchedSuggestions, kMaxAgeForAdditionalPrefetchedSuggestion); - auto provider = MakeSuggestionsProviderWithoutInitialization( + auto provider = MakeSuggestionsProvider( /*use_mock_prefetched_pages_tracker=*/true, - /*use_mock_breaking_news_listener=*/false); - auto* mock_tracker = static_cast<StrictMock<MockPrefetchedPagesTracker>*>( - prefetched_pages_tracker()); - WaitForSuggestionsProviderInitialization(provider.get()); + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); + StrictMock<MockPrefetchedPagesTracker>* mock_tracker = + mock_prefetched_pages_tracker(); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( @@ -2558,12 +2760,12 @@ kMaxAdditionalPrefetchedSuggestions, kMaxAgeForAdditionalPrefetchedSuggestion); - auto provider = MakeSuggestionsProviderWithoutInitialization( + auto provider = MakeSuggestionsProvider( /*use_mock_prefetched_pages_tracker=*/true, - /*use_mock_breaking_news_listener=*/false); - auto* mock_tracker = static_cast<StrictMock<MockPrefetchedPagesTracker>*>( - prefetched_pages_tracker()); - WaitForSuggestionsProviderInitialization(provider.get()); + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); + StrictMock<MockPrefetchedPagesTracker>* mock_tracker = + mock_prefetched_pages_tracker(); std::vector<FetchedCategory> fetched_categories; const int prefetched_suggestions_count = @@ -2616,9 +2818,10 @@ auto provider = MakeSuggestionsProviderWithoutInitialization( /*use_mock_prefetched_pages_tracker=*/true, - /*use_mock_breaking_news_listener=*/false); - auto* mock_tracker = static_cast<StrictMock<MockPrefetchedPagesTracker>*>( - prefetched_pages_tracker()); + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); + StrictMock<MockPrefetchedPagesTracker>* mock_tracker = + mock_prefetched_pages_tracker(); auto wrapped_provider_clock = base::MakeUnique<base::SimpleTestClock>(); base::SimpleTestClock* provider_clock = wrapped_provider_clock.get(); @@ -2702,12 +2905,12 @@ kMaxAdditionalPrefetchedSuggestions, kMaxAgeForAdditionalPrefetchedSuggestion); - auto provider = MakeSuggestionsProviderWithoutInitialization( + auto provider = MakeSuggestionsProvider( /*use_mock_prefetched_pages_tracker=*/true, - /*use_mock_breaking_news_listener=*/false); - auto* mock_tracker = static_cast<StrictMock<MockPrefetchedPagesTracker>*>( - prefetched_pages_tracker()); - WaitForSuggestionsProviderInitialization(provider.get()); + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); + StrictMock<MockPrefetchedPagesTracker>* mock_tracker = + mock_prefetched_pages_tracker(); base::OnceCallback<void()> initialization_completed_callback; EXPECT_CALL(*mock_tracker, IsInitialized()).WillRepeatedly(Return(false)); @@ -2735,7 +2938,10 @@ TEST_F(RemoteSuggestionsProviderImplTest, ShouldRestoreSuggestionsFromDatabaseInSameOrderAsFetched) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; fetched_categories.push_back( @@ -2763,7 +2969,11 @@ Property(&ContentSuggestion::id, MakeArticleID("http://3.com")), Property(&ContentSuggestion::id, MakeArticleID("http://2.com")))); - ResetSuggestionsProvider(&provider); + ResetSuggestionsProvider( + &provider, + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); EXPECT_THAT( observer().SuggestionsForCategory(articles_category()), ElementsAre( @@ -2775,7 +2985,10 @@ // TODO(vitaliii): Remove this test (as well as the score fallback) in M64. TEST_F(RemoteSuggestionsProviderImplTest, ShouldSortSuggestionsWithoutRanksByScore) { - auto provider = MakeSuggestionsProvider(); + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); // Write suggestions without ranks (i.e. with default values) directly to // database to simulate behaviour of M61. @@ -2801,7 +3014,11 @@ database()->SaveSnippets(suggestions); - ResetSuggestionsProvider(&provider); + ResetSuggestionsProvider( + &provider, + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/false, + /*use_mock_remote_suggestions_status_service=*/false); EXPECT_THAT( observer().SuggestionsForCategory(articles_category()), ElementsAre( @@ -2813,10 +3030,10 @@ TEST_F(RemoteSuggestionsProviderImplTest, PrependingShouldNotAffectOtherSuggestions) { // Set up the provider with some article suggestions. - auto provider = MakeSuggestionsProviderWithoutInitialization( + auto provider = MakeSuggestionsProvider( /*use_mock_prefetched_pages_tracker=*/false, - /*use_mock_breaking_news_listener=*/true); - WaitForSuggestionsProviderInitialization(provider.get()); + /*use_fake_breaking_news_listener=*/true, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; FetchedCategoryBuilder category_builder = FetchedCategoryBuilder().SetCategory(articles_category()); @@ -2855,10 +3072,10 @@ } TEST_F(RemoteSuggestionsProviderImplTest, ShouldNotPrependDismissedSuggestion) { - auto provider = MakeSuggestionsProviderWithoutInitialization( + auto provider = MakeSuggestionsProvider( /*use_mock_prefetched_pages_tracker=*/false, - /*use_mock_breaking_news_listener=*/true); - WaitForSuggestionsProviderInitialization(provider.get()); + /*use_fake_breaking_news_listener=*/true, + /*use_mock_remote_suggestions_status_service=*/false); // Prepend an article suggestion. const RemoteSuggestionBuilder suggestion_builder = @@ -2884,10 +3101,10 @@ TEST_F(RemoteSuggestionsProviderImplTest, ShouldRestorePrependedSuggestionOnTopAfterRestart) { // Set up the provider with some article suggestions. - auto provider = MakeSuggestionsProviderWithoutInitialization( + auto provider = MakeSuggestionsProvider( /*use_mock_prefetched_pages_tracker=*/false, - /*use_mock_breaking_news_listener=*/true); - WaitForSuggestionsProviderInitialization(provider.get()); + /*use_fake_breaking_news_listener=*/true, + /*use_mock_remote_suggestions_status_service=*/false); std::vector<FetchedCategory> fetched_categories; FetchedCategoryBuilder category_builder = FetchedCategoryBuilder().SetCategory(articles_category()); @@ -2911,7 +3128,11 @@ PushArticleSuggestionToTheFront(std::move(prepended_suggestion)); // Reset the provider to imitate browser restart. - ResetSuggestionsProvider(&provider); + ResetSuggestionsProvider( + &provider, + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/true, + /*use_mock_remote_suggestions_status_service=*/false); // Check that prepended suggestion is in the front of the restored list and // all other suggestions are present in the same order. @@ -2928,4 +3149,86 @@ ElementsAreArray(expected)); } +TEST_F(RemoteSuggestionsProviderImplTest, + ShouldNotStartListeningForBreakingNewsIfSuggestionsDisabledAtStartup) { + auto provider = MakeSuggestionsProviderWithoutInitialization( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/true, + /*use_mock_remote_suggestions_status_service=*/true); + + FakeBreakingNewsListener* fake_listener = fake_breaking_news_listener(); + EXPECT_FALSE(fake_listener->IsListening()); + + WaitForSuggestionsProviderInitialization(provider.get()); + EXPECT_FALSE(fake_listener->IsListening()); + + // Notify the provider about status change (simulating startup). The provider + // should not start listening, because the suggestions are disabled. + ChangeRemoteSuggestionsStatus(RemoteSuggestionsStatus::EXPLICITLY_DISABLED, + RemoteSuggestionsStatus::EXPLICITLY_DISABLED); + EXPECT_FALSE(fake_listener->IsListening()); +} + +TEST_F(RemoteSuggestionsProviderImplTest, + ShouldStartListeningForBreakingNewsIfSuggestionsEnabledAtStartup) { + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/true, + /*use_mock_remote_suggestions_status_service=*/true); + + FakeBreakingNewsListener* fake_listener = fake_breaking_news_listener(); + ASSERT_FALSE(fake_listener->IsListening()); + + // Notify the provider about status change (simulating startup). The provider + // should start listening, because the suggestions are enabled. + ChangeRemoteSuggestionsStatus( + RemoteSuggestionsStatus::EXPLICITLY_DISABLED, + RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT); + EXPECT_TRUE(fake_listener->IsListening()); +} + +TEST_F(RemoteSuggestionsProviderImplTest, + ShouldStartListeningForBreakingNewsIfSuggestionsEnabled) { + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/true, + /*use_mock_remote_suggestions_status_service=*/true); + + FakeBreakingNewsListener* fake_listener = fake_breaking_news_listener(); + + // Notify the provider about status change (simulating startup). + ChangeRemoteSuggestionsStatus(RemoteSuggestionsStatus::EXPLICITLY_DISABLED, + RemoteSuggestionsStatus::EXPLICITLY_DISABLED); + ASSERT_FALSE(fake_listener->IsListening()); + + // Simulate the user enabling suggestions by notifying the status change. The + // provider should start listening. + ChangeRemoteSuggestionsStatus( + RemoteSuggestionsStatus::EXPLICITLY_DISABLED, + RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT); + EXPECT_TRUE(fake_listener->IsListening()); +} + +TEST_F(RemoteSuggestionsProviderImplTest, + ShouldStopListeningForBreakingNewsIfSuggestionsDisabled) { + auto provider = MakeSuggestionsProvider( + /*use_mock_prefetched_pages_tracker=*/false, + /*use_fake_breaking_news_listener=*/true, + /*use_mock_remote_suggestions_status_service=*/true); + + FakeBreakingNewsListener* fake_listener = fake_breaking_news_listener(); + + // Notify the provider about status change (simulating startup). + ChangeRemoteSuggestionsStatus( + RemoteSuggestionsStatus::EXPLICITLY_DISABLED, + RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT); + ASSERT_TRUE(fake_listener->IsListening()); + + // Simulate the user disabling suggestions by notifying the status change. The + // provider should stop listening. + ChangeRemoteSuggestionsStatus(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT, + RemoteSuggestionsStatus::EXPLICITLY_DISABLED); + EXPECT_FALSE(fake_listener->IsListening()); +} + } // namespace ntp_snippets
diff --git a/components/offline_pages/core/prefetch/BUILD.gn b/components/offline_pages/core/prefetch/BUILD.gn index 51d8f44..8e65f7a 100644 --- a/components/offline_pages/core/prefetch/BUILD.gn +++ b/components/offline_pages/core/prefetch/BUILD.gn
@@ -11,6 +11,8 @@ sources = [ "add_unique_urls_task.cc", "add_unique_urls_task.h", + "download_completed_task.cc", + "download_completed_task.h", "generate_page_bundle_request.cc", "generate_page_bundle_request.h", "generate_page_bundle_task.cc", @@ -19,6 +21,10 @@ "get_operation_request.h", "get_operation_task.cc", "get_operation_task.h", + "import_archives_task.cc", + "import_archives_task.h", + "import_completed_task.cc", + "import_completed_task.h", "mark_operation_done_task.cc", "mark_operation_done_task.h", "offline_metrics_collector.h", @@ -31,6 +37,7 @@ "prefetch_gcm_app_handler.cc", "prefetch_gcm_app_handler.h", "prefetch_gcm_handler.h", + "prefetch_importer.cc", "prefetch_importer.h", "prefetch_item.cc", "prefetch_item.h", @@ -128,10 +135,13 @@ testonly = true sources = [ "add_unique_urls_task_unittest.cc", + "download_completed_task_unittest.cc", "generate_page_bundle_request_unittest.cc", "generate_page_bundle_task_unittest.cc", "get_operation_request_unittest.cc", "get_operation_task_unittest.cc", + "import_archives_task_unittest.cc", + "import_completed_task_unittest.cc", "mark_operation_done_task_unittest.cc", "prefetch_dispatcher_impl_unittest.cc", "prefetch_downloader_unittest.cc",
diff --git a/components/offline_pages/core/prefetch/download_completed_task.cc b/components/offline_pages/core/prefetch/download_completed_task.cc new file mode 100644 index 0000000..d5b83a8 --- /dev/null +++ b/components/offline_pages/core/prefetch/download_completed_task.cc
@@ -0,0 +1,108 @@ +// 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 "components/offline_pages/core/prefetch/download_completed_task.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/files/file_path.h" +#include "base/logging.h" +#include "components/offline_pages/core/prefetch/prefetch_types.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store.h" +#include "sql/connection.h" +#include "sql/statement.h" +#include "url/gurl.h" + +namespace offline_pages { +namespace { + +bool UpdatePrefetchItemOnDownloadSuccessSync(const std::string& guid, + const base::FilePath& file_path, + int64_t file_size, + sql::Connection* db) { + static const char kSql[] = + "UPDATE prefetch_items" + " SET state = ?, file_path = ?, file_size = ?" + " WHERE guid = ? AND state = ?"; + + sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); + statement.BindInt(0, static_cast<int>(PrefetchItemState::DOWNLOADED)); + statement.BindString(1, file_path.AsUTF8Unsafe()); + statement.BindInt64(2, file_size); + statement.BindString(3, guid); + statement.BindInt(4, static_cast<int>(PrefetchItemState::DOWNLOADING)); + + return statement.Run(); +} + +bool UpdatePrefetchItemOnDownloadErrorSync(const std::string& guid, + sql::Connection* db) { + static const char kSql[] = + "UPDATE prefetch_items" + " SET state = ?, error_code = ?" + " WHERE guid = ? AND state = ?"; + + sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); + statement.BindInt(0, static_cast<int>(PrefetchItemState::FINISHED)); + statement.BindInt(1, static_cast<int>(PrefetchItemErrorCode::DOWNLOAD_ERROR)); + statement.BindString(2, guid); + statement.BindInt(3, static_cast<int>(PrefetchItemState::DOWNLOADING)); + + return statement.Run(); +} + +} // namespace + +DownloadCompletedTask::DownloadCompletedTask( + PrefetchStore* prefetch_store, + const PrefetchDownloadResult& download_result) + : prefetch_store_(prefetch_store), + download_result_(download_result), + weak_ptr_factory_(this) { + DCHECK(!download_result_.download_id.empty()); +} + +DownloadCompletedTask::~DownloadCompletedTask() {} + +void DownloadCompletedTask::Run() { + if (download_result_.success) { + prefetch_store_->Execute( + base::BindOnce(&UpdatePrefetchItemOnDownloadSuccessSync, + download_result_.download_id, download_result_.file_path, + download_result_.file_size), + base::BindOnce(&DownloadCompletedTask::OnDownloadSuccessUpdated, + weak_ptr_factory_.GetWeakPtr())); + } else { + prefetch_store_->Execute( + base::BindOnce(&UpdatePrefetchItemOnDownloadErrorSync, + download_result_.download_id), + base::BindOnce(&DownloadCompletedTask::OnDownloadErrorUpdated, + weak_ptr_factory_.GetWeakPtr())); + } +} + +void DownloadCompletedTask::OnDownloadSuccessUpdated(bool success) { + // No further action can be done if the database fails to be updated. The + // cleanup task should eventually kick in to clean this up. + if (success) { + // TODO(jianli): Calls SchedulePipelineProcessing to process the download. + NOTIMPLEMENTED(); + } + + TaskComplete(); +} + +void DownloadCompletedTask::OnDownloadErrorUpdated(bool success) { + // No further action can be done if the database fails to be updated. The + // cleanup task should eventually kick in to clean this up. + if (success) { + // TODO(jianli): Calls SchedulePipelineProcessing to process the item in + // finished error state. + NOTIMPLEMENTED(); + } + + TaskComplete(); +} + +} // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/download_completed_task.h b/components/offline_pages/core/prefetch/download_completed_task.h new file mode 100644 index 0000000..6a99692 --- /dev/null +++ b/components/offline_pages/core/prefetch/download_completed_task.h
@@ -0,0 +1,39 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_DOWNLOAD_COMPLETED_TASK_H_ +#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_DOWNLOAD_COMPLETED_TASK_H_ + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "components/offline_pages/core/prefetch/prefetch_types.h" +#include "components/offline_pages/core/task.h" + +namespace offline_pages { +class PrefetchStore; + +// Task that responses to the completed download. +class DownloadCompletedTask : public Task { + public: + DownloadCompletedTask(PrefetchStore* prefetch_store, + const PrefetchDownloadResult& download_result); + ~DownloadCompletedTask() override; + + void Run() override; + + private: + void OnDownloadSuccessUpdated(bool success); + void OnDownloadErrorUpdated(bool success); + + PrefetchStore* prefetch_store_; // Outlives this class. + PrefetchDownloadResult download_result_; + + base::WeakPtrFactory<DownloadCompletedTask> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(DownloadCompletedTask); +}; + +} // namespace offline_pages + +#endif // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_DOWNLOAD_COMPLETED_TASK_H_
diff --git a/components/offline_pages/core/prefetch/download_completed_task_unittest.cc b/components/offline_pages/core/prefetch/download_completed_task_unittest.cc new file mode 100644 index 0000000..1b4497fd --- /dev/null +++ b/components/offline_pages/core/prefetch/download_completed_task_unittest.cc
@@ -0,0 +1,153 @@ +// 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 "components/offline_pages/core/prefetch/download_completed_task.h" + +#include <string> +#include <vector> + +#include "base/test/test_simple_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "base/time/time.h" +#include "components/offline_pages/core/prefetch/prefetch_item.h" +#include "components/offline_pages/core/prefetch/prefetch_types.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store_test_util.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store_utils.h" +#include "sql/connection.h" +#include "sql/statement.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace offline_pages { + +namespace { +const int64_t kTestOfflineID = 1111; +const int64_t kTestOfflineID2 = 223344; +const char kTestGUID[] = "1a150628-1b56-44da-a85a-c575120af180"; +const char kTestGUID2[] = "736edb12-98f6-41c2-8e50-a667694511a5"; +const base::FilePath kTestFilePath(FILE_PATH_LITERAL("foo")); +const int64_t kTestFileSize = 88888; +} // namespace + +class DownloadCompletedTaskTest : public testing::Test { + public: + DownloadCompletedTaskTest(); + ~DownloadCompletedTaskTest() override = default; + + void SetUp() override; + void TearDown() override; + + void PumpLoop(); + + PrefetchStore* store() { return store_test_util_.store(); } + PrefetchStoreTestUtil* store_util() { return &store_test_util_; } + + private: + scoped_refptr<base::TestSimpleTaskRunner> task_runner_; + base::ThreadTaskRunnerHandle task_runner_handle_; + PrefetchStoreTestUtil store_test_util_; +}; + +DownloadCompletedTaskTest::DownloadCompletedTaskTest() + : task_runner_(new base::TestSimpleTaskRunner), + task_runner_handle_(task_runner_), + store_test_util_(task_runner_) {} + +void DownloadCompletedTaskTest::SetUp() { + store_test_util_.BuildStoreInMemory(); + + PrefetchItem item; + item.offline_id = kTestOfflineID; + item.guid = kTestGUID; + item.state = PrefetchItemState::DOWNLOADING; + item.creation_time = base::Time::Now(); + item.freshness_time = item.creation_time; + EXPECT_TRUE(store_test_util_.InsertPrefetchItem(item)); + + PrefetchItem item2; + item2.offline_id = kTestOfflineID2; + item2.guid = kTestGUID2; + item2.state = PrefetchItemState::NEW_REQUEST; + item2.creation_time = base::Time::Now(); + item2.freshness_time = item.creation_time; + EXPECT_TRUE(store_test_util_.InsertPrefetchItem(item2)); +} + +void DownloadCompletedTaskTest::TearDown() { + store_test_util_.DeleteStore(); + PumpLoop(); +} + +void DownloadCompletedTaskTest::PumpLoop() { + task_runner_->RunUntilIdle(); +} + +TEST_F(DownloadCompletedTaskTest, UpdateItemOnDownloadSuccess) { + PrefetchDownloadResult download_result(kTestGUID, kTestFilePath, + kTestFileSize); + DownloadCompletedTask task(store(), download_result); + task.Run(); + PumpLoop(); + + std::unique_ptr<PrefetchItem> item = + store_util()->GetPrefetchItem(kTestOfflineID); + EXPECT_EQ(PrefetchItemState::DOWNLOADED, item->state); + EXPECT_EQ(kTestGUID, item->guid); + EXPECT_EQ(kTestFilePath, item->file_path); + EXPECT_EQ(kTestFileSize, item->file_size); +} + +TEST_F(DownloadCompletedTaskTest, UpdateItemOnDownloadError) { + PrefetchDownloadResult download_result; + download_result.download_id = kTestGUID; + download_result.success = false; + DownloadCompletedTask task(store(), download_result); + task.Run(); + PumpLoop(); + + std::unique_ptr<PrefetchItem> item = + store_util()->GetPrefetchItem(kTestOfflineID); + EXPECT_EQ(PrefetchItemState::FINISHED, item->state); + EXPECT_EQ(PrefetchItemErrorCode::DOWNLOAD_ERROR, item->error_code); + EXPECT_EQ(kTestGUID, item->guid); + EXPECT_TRUE(item->file_path.empty()); + EXPECT_EQ(0, item->file_size); +} + +TEST_F(DownloadCompletedTaskTest, NoUpdateOnMismatchedDownloadSuccess) { + PrefetchDownloadResult download_result(kTestGUID2, kTestFilePath, + kTestFileSize); + DownloadCompletedTask task(store(), download_result); + task.Run(); + PumpLoop(); + + // Item will only be updated when both offline_id and state match. + std::unique_ptr<PrefetchItem> item = + store_util()->GetPrefetchItem(kTestOfflineID); + EXPECT_EQ(PrefetchItemState::DOWNLOADING, item->state); + + std::unique_ptr<PrefetchItem> item2 = + store_util()->GetPrefetchItem(kTestOfflineID2); + EXPECT_EQ(PrefetchItemState::NEW_REQUEST, item2->state); +} + +TEST_F(DownloadCompletedTaskTest, NoUpdateOnMismatchedDownloadError) { + PrefetchDownloadResult download_result; + download_result.download_id = kTestGUID2; + download_result.success = false; + DownloadCompletedTask task(store(), download_result); + task.Run(); + PumpLoop(); + + // Item will only be updated when both offline_id and state match. + std::unique_ptr<PrefetchItem> item = + store_util()->GetPrefetchItem(kTestOfflineID); + EXPECT_EQ(PrefetchItemState::DOWNLOADING, item->state); + + std::unique_ptr<PrefetchItem> item2 = + store_util()->GetPrefetchItem(kTestOfflineID2); + EXPECT_EQ(PrefetchItemState::NEW_REQUEST, item2->state); +} + +} // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/import_archives_task.cc b/components/offline_pages/core/prefetch/import_archives_task.cc new file mode 100644 index 0000000..1de35ca1 --- /dev/null +++ b/components/offline_pages/core/prefetch/import_archives_task.cc
@@ -0,0 +1,107 @@ +// 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 "components/offline_pages/core/prefetch/import_archives_task.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/files/file_path.h" +#include "base/logging.h" +#include "components/offline_pages/core/prefetch/prefetch_types.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store.h" +#include "sql/connection.h" +#include "sql/statement.h" +#include "sql/transaction.h" +#include "url/gurl.h" + +namespace offline_pages { +namespace { + +std::vector<PrefetchArchiveInfo> GetArchivesSync(sql::Connection* db) { + static const char kSql[] = + "SELECT offline_id, client_namespace, client_id, requested_url," + " final_archived_url, title, file_path, file_size" + " FROM prefetch_items" + " WHERE state = ?"; + sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); + statement.BindInt(0, static_cast<int>(PrefetchItemState::DOWNLOADED)); + + std::vector<PrefetchArchiveInfo> archives; + while (statement.Step()) { + PrefetchArchiveInfo archive; + archive.offline_id = statement.ColumnInt64(0); + archive.client_id.name_space = statement.ColumnString(1); + archive.client_id.id = statement.ColumnString(2); + archive.url = GURL(statement.ColumnString(3)); + archive.final_archived_url = GURL(statement.ColumnString(4)); + archive.title = statement.ColumnString16(5); + archive.file_path = + base::FilePath::FromUTF8Unsafe(statement.ColumnString(6)); + archive.file_size = statement.ColumnInt64(7); + archives.push_back(archive); + } + + return archives; +} + +bool UpdateToImportingStateSync(int64_t offline_id, sql::Connection* db) { + static const char kSql[] = + "UPDATE prefetch_items" + " SET state = ?" + " WHERE offline_id = ?"; + + sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); + statement.BindInt(0, static_cast<int>(PrefetchItemState::IMPORTING)); + statement.BindInt64(1, offline_id); + + return statement.Run(); +} + +std::vector<PrefetchArchiveInfo> GetArchivesAndUpdateToImportingStateSync( + sql::Connection* db) { + sql::Transaction transaction(db); + if (!transaction.Begin()) + return std::vector<PrefetchArchiveInfo>(); + + std::vector<PrefetchArchiveInfo> archives = GetArchivesSync(db); + if (archives.empty()) + return std::vector<PrefetchArchiveInfo>(); + + for (const auto& archive : archives) { + if (!UpdateToImportingStateSync(archive.offline_id, db)) + return std::vector<PrefetchArchiveInfo>(); + } + + if (!transaction.Commit()) + return std::vector<PrefetchArchiveInfo>(); + + return archives; +} + +} // namespace + +ImportArchivesTask::ImportArchivesTask(PrefetchStore* prefetch_store, + PrefetchImporter* prefetch_importer) + : prefetch_store_(prefetch_store), + prefetch_importer_(prefetch_importer), + weak_ptr_factory_(this) {} + +ImportArchivesTask::~ImportArchivesTask() {} + +void ImportArchivesTask::Run() { + prefetch_store_->Execute( + base::BindOnce(&GetArchivesAndUpdateToImportingStateSync), + base::BindOnce(&ImportArchivesTask::OnArchivesRetrieved, + weak_ptr_factory_.GetWeakPtr())); +} + +void ImportArchivesTask::OnArchivesRetrieved( + std::vector<PrefetchArchiveInfo> archives) { + for (const auto& archive : archives) + prefetch_importer_->ImportArchive(archive); + + TaskComplete(); +} + +} // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/import_archives_task.h b/components/offline_pages/core/prefetch/import_archives_task.h new file mode 100644 index 0000000..c661297e --- /dev/null +++ b/components/offline_pages/core/prefetch/import_archives_task.h
@@ -0,0 +1,42 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_IMPORT_ARCHIVES_TASK_H_ +#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_IMPORT_ARCHIVES_TASK_H_ + +#include <vector> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "components/offline_pages/core/prefetch/prefetch_importer.h" +#include "components/offline_pages/core/prefetch/prefetch_types.h" +#include "components/offline_pages/core/task.h" + +namespace offline_pages { +class PrefetchStore; + +// Task that attempts to import a downloaded archive to offline page model. +class ImportArchivesTask : public Task { + public: + ImportArchivesTask(PrefetchStore* prefetch_store, + PrefetchImporter* prefetch_importer); + ~ImportArchivesTask() override; + + void Run() override; + + private: + void OnArchivesRetrieved(std::vector<PrefetchArchiveInfo> archive); + + PrefetchStore* prefetch_store_; // Outlives this class. + PrefetchImporter* prefetch_importer_; // Outlives this class. + PrefetchArchiveInfo archive_; + + base::WeakPtrFactory<ImportArchivesTask> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(ImportArchivesTask); +}; + +} // namespace offline_pages + +#endif // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_IMPORT_ARCHIVES_TASK_H_
diff --git a/components/offline_pages/core/prefetch/import_archives_task_unittest.cc b/components/offline_pages/core/prefetch/import_archives_task_unittest.cc new file mode 100644 index 0000000..1ab6f462 --- /dev/null +++ b/components/offline_pages/core/prefetch/import_archives_task_unittest.cc
@@ -0,0 +1,180 @@ +// 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 "components/offline_pages/core/prefetch/import_archives_task.h" + +#include <string> +#include <vector> + +#include "base/strings/utf_string_conversions.h" +#include "base/test/test_simple_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "base/time/time.h" +#include "components/offline_pages/core/prefetch/prefetch_importer.h" +#include "components/offline_pages/core/prefetch/prefetch_item.h" +#include "components/offline_pages/core/prefetch/prefetch_types.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store_test_util.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store_utils.h" +#include "sql/connection.h" +#include "sql/statement.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace offline_pages { + +namespace { + +const int64_t kTestOfflineID = 1111; +const int64_t kTestOfflineID2 = 223344; +const int64_t kTestOfflineID3 = 987; +const GURL kTestURL("http://sample.org"); +const GURL kTestURL2("http://sample.org"); +const GURL kTestFinalURL("https://sample.org/foo"); +const GURL kTestFinalURL2("https://sample.org/foo"); +const ClientId kTestClientID("Foo", "Bar"); +const ClientId kTestClientID2("Foo2", "Bar2"); +const base::string16 kTestTitle = base::ASCIIToUTF16("Hello"); +const base::string16 kTestTitle2 = base::ASCIIToUTF16("Hello2"); +const base::FilePath kTestFilePath(FILE_PATH_LITERAL("foo")); +const base::FilePath kTestFilePath2(FILE_PATH_LITERAL("foo2")); +const int64_t kTestFileSize = 88888; +const int64_t kTestFileSize2 = 999; + +class TestPrefetchImporter : public PrefetchImporter { + public: + TestPrefetchImporter() : PrefetchImporter(nullptr) {} + ~TestPrefetchImporter() override = default; + + void ImportArchive(const PrefetchArchiveInfo& archive) override { + archives_.push_back(archive); + } + + const std::vector<PrefetchArchiveInfo>& archives() const { return archives_; } + + private: + std::vector<PrefetchArchiveInfo> archives_; +}; + +} // namespace + +class ImportArchivesTaskTest : public testing::Test { + public: + ImportArchivesTaskTest(); + ~ImportArchivesTaskTest() override = default; + + void SetUp() override; + void TearDown() override; + + void PumpLoop(); + + PrefetchStore* store() { return store_test_util_.store(); } + PrefetchStoreTestUtil* store_util() { return &store_test_util_; } + TestPrefetchImporter* importer() { return &test_importer_; } + + private: + scoped_refptr<base::TestSimpleTaskRunner> task_runner_; + base::ThreadTaskRunnerHandle task_runner_handle_; + PrefetchStoreTestUtil store_test_util_; + TestPrefetchImporter test_importer_; +}; + +ImportArchivesTaskTest::ImportArchivesTaskTest() + : task_runner_(new base::TestSimpleTaskRunner), + task_runner_handle_(task_runner_), + store_test_util_(task_runner_) {} + +void ImportArchivesTaskTest::SetUp() { + store_test_util_.BuildStoreInMemory(); + + PrefetchItem item; + item.offline_id = kTestOfflineID; + item.state = PrefetchItemState::DOWNLOADED; + item.url = kTestURL; + item.final_archived_url = kTestFinalURL; + item.client_id = kTestClientID; + item.title = kTestTitle; + item.file_path = kTestFilePath; + item.file_size = kTestFileSize; + item.creation_time = base::Time::Now(); + item.freshness_time = item.creation_time; + EXPECT_TRUE(store_test_util_.InsertPrefetchItem(item)); + + PrefetchItem item2; + item2.offline_id = kTestOfflineID2; + item2.state = PrefetchItemState::DOWNLOADED; + item2.url = kTestURL2; + item2.final_archived_url = kTestFinalURL2; + item2.client_id = kTestClientID2; + item2.title = kTestTitle2; + item2.file_path = kTestFilePath2; + item2.file_size = kTestFileSize2; + item2.creation_time = base::Time::Now(); + item2.freshness_time = item.creation_time; + EXPECT_TRUE(store_test_util_.InsertPrefetchItem(item2)); + + PrefetchItem item3; + item3.offline_id = kTestOfflineID3; + item3.state = PrefetchItemState::NEW_REQUEST; + item3.creation_time = base::Time::Now(); + item3.freshness_time = item.creation_time; + EXPECT_TRUE(store_test_util_.InsertPrefetchItem(item3)); +} + +void ImportArchivesTaskTest::TearDown() { + store_test_util_.DeleteStore(); + PumpLoop(); +} + +void ImportArchivesTaskTest::PumpLoop() { + task_runner_->RunUntilIdle(); +} + +TEST_F(ImportArchivesTaskTest, Importing) { + ImportArchivesTask task(store(), importer()); + task.Run(); + PumpLoop(); + + // Two items are updated. + std::unique_ptr<PrefetchItem> item = + store_util()->GetPrefetchItem(kTestOfflineID); + EXPECT_EQ(PrefetchItemState::IMPORTING, item->state); + + item = store_util()->GetPrefetchItem(kTestOfflineID2); + EXPECT_EQ(PrefetchItemState::IMPORTING, item->state); + + // One item is not updated. + item = store_util()->GetPrefetchItem(kTestOfflineID3); + EXPECT_EQ(PrefetchItemState::NEW_REQUEST, item->state); + + // Validate the info passed to PrefetchImporter. + ASSERT_EQ(2u, importer()->archives().size()); + + PrefetchArchiveInfo archive1; + PrefetchArchiveInfo archive2; + if (importer()->archives()[0].offline_id == kTestOfflineID) { + archive1 = importer()->archives()[0]; + archive2 = importer()->archives()[1]; + } + if (importer()->archives()[1].offline_id == kTestOfflineID) { + archive1 = importer()->archives()[1]; + archive2 = importer()->archives()[0]; + } + EXPECT_EQ(kTestOfflineID, archive1.offline_id); + EXPECT_EQ(kTestClientID, archive1.client_id); + EXPECT_EQ(kTestURL, archive1.url); + EXPECT_EQ(kTestFinalURL, archive1.final_archived_url); + EXPECT_EQ(kTestTitle, archive1.title); + EXPECT_EQ(kTestFilePath, archive1.file_path); + EXPECT_EQ(kTestFileSize, archive1.file_size); + + EXPECT_EQ(kTestOfflineID2, archive2.offline_id); + EXPECT_EQ(kTestClientID2, archive2.client_id); + EXPECT_EQ(kTestURL2, archive2.url); + EXPECT_EQ(kTestFinalURL2, archive2.final_archived_url); + EXPECT_EQ(kTestTitle2, archive2.title); + EXPECT_EQ(kTestFilePath2, archive2.file_path); + EXPECT_EQ(kTestFileSize2, archive2.file_size); +} + +} // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/import_completed_task.cc b/components/offline_pages/core/prefetch/import_completed_task.cc new file mode 100644 index 0000000..cd806d00 --- /dev/null +++ b/components/offline_pages/core/prefetch/import_completed_task.cc
@@ -0,0 +1,69 @@ +// 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 "components/offline_pages/core/prefetch/import_completed_task.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/logging.h" +#include "components/offline_pages/core/prefetch/prefetch_types.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store.h" +#include "sql/connection.h" +#include "sql/statement.h" +#include "url/gurl.h" + +namespace offline_pages { +namespace { + +bool UpdateToFinishedStateSync(int64_t offline_id, + bool success, + sql::Connection* db) { + static const char kSql[] = + "UPDATE prefetch_items" + " SET state = ?, error_code = ?" + " WHERE offline_id = ? AND state = ?"; + + sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); + statement.BindInt(0, static_cast<int>(PrefetchItemState::FINISHED)); + statement.BindInt( + 1, static_cast<int>(success ? PrefetchItemErrorCode::SUCCESS + : PrefetchItemErrorCode::IMPORT_ERROR)); + statement.BindInt64(2, offline_id); + statement.BindInt(3, static_cast<int>(PrefetchItemState::IMPORTING)); + + return statement.Run(); +} + +} // namespace + +ImportCompletedTask::ImportCompletedTask(PrefetchStore* prefetch_store, + int64_t offline_id, + bool success) + : prefetch_store_(prefetch_store), + offline_id_(offline_id), + success_(success), + weak_ptr_factory_(this) {} + +ImportCompletedTask::~ImportCompletedTask() {} + +void ImportCompletedTask::Run() { + prefetch_store_->Execute( + base::BindOnce(&UpdateToFinishedStateSync, offline_id_, success_), + base::BindOnce(&ImportCompletedTask::OnStateUpdatedToFinished, + weak_ptr_factory_.GetWeakPtr())); +} + +void ImportCompletedTask::OnStateUpdatedToFinished(bool success) { + // No further action can be done if the database fails to be updated. The + // cleanup task should eventually kick in to clean this up. + if (success) { + // TODO(jianli): Calls SchedulePipelineProcessing to process the finished + // item. + NOTIMPLEMENTED(); + } + + TaskComplete(); +} + +} // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/import_completed_task.h b/components/offline_pages/core/prefetch/import_completed_task.h new file mode 100644 index 0000000..fc4e427 --- /dev/null +++ b/components/offline_pages/core/prefetch/import_completed_task.h
@@ -0,0 +1,40 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_IMPORT_COMPLETED_TASK_H_ +#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_IMPORT_COMPLETED_TASK_H_ + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "components/offline_pages/core/prefetch/prefetch_types.h" +#include "components/offline_pages/core/task.h" + +namespace offline_pages { +class PrefetchStore; + +// Task that responses to the completed import. +class ImportCompletedTask : public Task { + public: + ImportCompletedTask(PrefetchStore* prefetch_store, + int64_t offline_id, + bool success); + ~ImportCompletedTask() override; + + void Run() override; + + private: + void OnStateUpdatedToFinished(bool success); + + PrefetchStore* prefetch_store_; // Outlives this class. + int64_t offline_id_; + bool success_; + + base::WeakPtrFactory<ImportCompletedTask> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(ImportCompletedTask); +}; + +} // namespace offline_pages + +#endif // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_IMPORT_COMPLETED_TASK_H_
diff --git a/components/offline_pages/core/prefetch/import_completed_task_unittest.cc b/components/offline_pages/core/prefetch/import_completed_task_unittest.cc new file mode 100644 index 0000000..ff3220b0 --- /dev/null +++ b/components/offline_pages/core/prefetch/import_completed_task_unittest.cc
@@ -0,0 +1,134 @@ +// 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 "components/offline_pages/core/prefetch/import_completed_task.h" + +#include <string> +#include <vector> + +#include "base/strings/utf_string_conversions.h" +#include "base/test/test_simple_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "base/time/time.h" +#include "components/offline_pages/core/prefetch/prefetch_importer.h" +#include "components/offline_pages/core/prefetch/prefetch_item.h" +#include "components/offline_pages/core/prefetch/prefetch_types.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store_test_util.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store_utils.h" +#include "sql/connection.h" +#include "sql/statement.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace offline_pages { + +namespace { +const int64_t kTestOfflineID = 1111; +const int64_t kTestOfflineID2 = 223344; +} // namespace + +class ImportCompletedTaskTest : public testing::Test { + public: + ImportCompletedTaskTest(); + ~ImportCompletedTaskTest() override = default; + + void SetUp() override; + void TearDown() override; + + void PumpLoop(); + + PrefetchStore* store() { return store_test_util_.store(); } + PrefetchStoreTestUtil* store_util() { return &store_test_util_; } + + private: + scoped_refptr<base::TestSimpleTaskRunner> task_runner_; + base::ThreadTaskRunnerHandle task_runner_handle_; + PrefetchStoreTestUtil store_test_util_; +}; + +ImportCompletedTaskTest::ImportCompletedTaskTest() + : task_runner_(new base::TestSimpleTaskRunner), + task_runner_handle_(task_runner_), + store_test_util_(task_runner_) {} + +void ImportCompletedTaskTest::SetUp() { + store_test_util_.BuildStoreInMemory(); + + PrefetchItem item; + item.offline_id = kTestOfflineID; + item.state = PrefetchItemState::IMPORTING; + item.creation_time = base::Time::Now(); + item.freshness_time = item.creation_time; + EXPECT_TRUE(store_test_util_.InsertPrefetchItem(item)); + + PrefetchItem item2; + item2.offline_id = kTestOfflineID2; + item2.state = PrefetchItemState::NEW_REQUEST; + item2.creation_time = base::Time::Now(); + item2.freshness_time = item.creation_time; + EXPECT_TRUE(store_test_util_.InsertPrefetchItem(item2)); +} + +void ImportCompletedTaskTest::TearDown() { + store_test_util_.DeleteStore(); + PumpLoop(); +} + +void ImportCompletedTaskTest::PumpLoop() { + task_runner_->RunUntilIdle(); +} + +TEST_F(ImportCompletedTaskTest, ImportSuccess) { + ImportCompletedTask task(store(), kTestOfflineID, true); + task.Run(); + PumpLoop(); + + std::unique_ptr<PrefetchItem> item = + store_util()->GetPrefetchItem(kTestOfflineID); + EXPECT_EQ(PrefetchItemState::FINISHED, item->state); + EXPECT_EQ(PrefetchItemErrorCode::SUCCESS, item->error_code); +} + +TEST_F(ImportCompletedTaskTest, ImportError) { + ImportCompletedTask task(store(), kTestOfflineID, false); + task.Run(); + PumpLoop(); + + std::unique_ptr<PrefetchItem> item = + store_util()->GetPrefetchItem(kTestOfflineID); + EXPECT_EQ(PrefetchItemState::FINISHED, item->state); + EXPECT_EQ(PrefetchItemErrorCode::IMPORT_ERROR, item->error_code); +} + +TEST_F(ImportCompletedTaskTest, NoUpdateOnMismatchedImportSuccess) { + ImportCompletedTask task(store(), kTestOfflineID2, true); + task.Run(); + PumpLoop(); + + // Item will only be updated when both guid and state match. + std::unique_ptr<PrefetchItem> item = + store_util()->GetPrefetchItem(kTestOfflineID); + EXPECT_EQ(PrefetchItemState::IMPORTING, item->state); + + std::unique_ptr<PrefetchItem> item2 = + store_util()->GetPrefetchItem(kTestOfflineID2); + EXPECT_EQ(PrefetchItemState::NEW_REQUEST, item2->state); +} + +TEST_F(ImportCompletedTaskTest, NoUpdateOnMismatchedImportError) { + ImportCompletedTask task(store(), kTestOfflineID2, false); + task.Run(); + PumpLoop(); + + // Item will only be updated when both guid and state match. + std::unique_ptr<PrefetchItem> item = + store_util()->GetPrefetchItem(kTestOfflineID); + EXPECT_EQ(PrefetchItemState::IMPORTING, item->state); + + std::unique_ptr<PrefetchItem> item2 = + store_util()->GetPrefetchItem(kTestOfflineID2); + EXPECT_EQ(PrefetchItemState::NEW_REQUEST, item2->state); +} + +} // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher.h b/components/offline_pages/core/prefetch/prefetch_dispatcher.h index 0373440a..abc658f5 100644 --- a/components/offline_pages/core/prefetch/prefetch_dispatcher.h +++ b/components/offline_pages/core/prefetch/prefetch_dispatcher.h
@@ -97,6 +97,13 @@ virtual void GCMOperationCompletedMessageReceived( const std::string& operation_name) = 0; + // Called when a download is completed successfully or fails. + virtual void DownloadCompleted( + const PrefetchDownloadResult& download_result) = 0; + + // Called when an archive import is completed successfully or fails. + virtual void ImportCompleted(int64_t offline_id, bool success) = 0; + // Used by the test to signal the completion of the background task. virtual void RequestFinishBackgroundTaskForTest() = 0; };
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc index 91cd0894..ad2f57a 100644 --- a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc +++ b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc
@@ -15,11 +15,15 @@ #include "components/offline_pages/core/offline_event_logger.h" #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/prefetch/add_unique_urls_task.h" +#include "components/offline_pages/core/prefetch/download_completed_task.h" #include "components/offline_pages/core/prefetch/generate_page_bundle_task.h" #include "components/offline_pages/core/prefetch/get_operation_task.h" +#include "components/offline_pages/core/prefetch/import_archives_task.h" +#include "components/offline_pages/core/prefetch/import_completed_task.h" #include "components/offline_pages/core/prefetch/mark_operation_done_task.h" #include "components/offline_pages/core/prefetch/prefetch_background_task_handler.h" #include "components/offline_pages/core/prefetch/prefetch_gcm_handler.h" +#include "components/offline_pages/core/prefetch/prefetch_importer.h" #include "components/offline_pages/core/prefetch/prefetch_network_request_factory.h" #include "components/offline_pages/core/prefetch/prefetch_service.h" #include "components/offline_pages/core/prefetch/prefetch_types.h" @@ -107,6 +111,11 @@ base::Bind(&PrefetchDispatcherImpl::DidGenerateBundleRequest, weak_factory_.GetWeakPtr())); task_queue_.AddTask(std::move(generate_page_bundle_task)); + + std::unique_ptr<Task> import_archives_task = + base::MakeUnique<ImportArchivesTask>(service_->GetPrefetchStore(), + service_->GetPrefetchImporter()); + task_queue_.AddTask(std::move(import_archives_task)); } void PrefetchDispatcherImpl::StopBackgroundTask() { @@ -162,6 +171,37 @@ LogRequestResult("GetOperationRequest", status, operation_name, pages); } +void PrefetchDispatcherImpl::DownloadCompleted( + const PrefetchDownloadResult& download_result) { + if (!IsPrefetchingOfflinePagesEnabled()) + return; + + service_->GetLogger()->RecordActivity( + "Download " + download_result.download_id + + (download_result.success ? "succeeded" : "failed")); + if (download_result.success) { + service_->GetLogger()->RecordActivity( + "Download size: " + std::to_string(download_result.file_size)); + } + + PrefetchStore* prefetch_store = service_->GetPrefetchStore(); + task_queue_.AddTask( + base::MakeUnique<DownloadCompletedTask>(prefetch_store, download_result)); +} + +void PrefetchDispatcherImpl::ImportCompleted(int64_t offline_id, bool success) { + if (!IsPrefetchingOfflinePagesEnabled()) + return; + + service_->GetLogger()->RecordActivity("Importing archive " + + std::to_string(offline_id) + + (success ? "succeeded" : "failed")); + + PrefetchStore* prefetch_store = service_->GetPrefetchStore(); + task_queue_.AddTask(base::MakeUnique<ImportCompletedTask>( + prefetch_store, offline_id, success)); +} + void PrefetchDispatcherImpl::LogRequestResult( const std::string& request_name_for_logging, PrefetchRequestStatus status,
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h index 3a30252b..0404fa0 100644 --- a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h +++ b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h
@@ -38,6 +38,9 @@ void StopBackgroundTask() override; void GCMOperationCompletedMessageReceived( const std::string& operation_name) override; + void DownloadCompleted( + const PrefetchDownloadResult& download_result) override; + void ImportCompleted(int64_t offline_id, bool success) override; void RequestFinishBackgroundTaskForTest() override; // TaskQueue::Delegate implementation:
diff --git a/components/offline_pages/core/prefetch/prefetch_downloader.cc b/components/offline_pages/core/prefetch/prefetch_downloader.cc index 05a06ba4..47f0591 100644 --- a/components/offline_pages/core/prefetch/prefetch_downloader.cc +++ b/components/offline_pages/core/prefetch/prefetch_downloader.cc
@@ -94,8 +94,16 @@ void PrefetchDownloader::OnDownloadSucceeded(const std::string& download_id, const base::FilePath& file_path, uint64_t file_size) { - if (callback_) - callback_.Run(PrefetchDownloadResult(download_id, file_path, file_size)); + // The file is not likely to be that big. Treat it as error if so. + if (file_size > static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) { + OnDownloadFailed(download_id); + return; + } + + if (callback_) { + callback_.Run(PrefetchDownloadResult(download_id, file_path, + static_cast<int64_t>(file_size))); + } } void PrefetchDownloader::OnDownloadFailed(const std::string& download_id) {
diff --git a/components/offline_pages/core/prefetch/prefetch_importer.cc b/components/offline_pages/core/prefetch/prefetch_importer.cc new file mode 100644 index 0000000..b7febd0 --- /dev/null +++ b/components/offline_pages/core/prefetch/prefetch_importer.cc
@@ -0,0 +1,18 @@ +// 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 "components/offline_pages/core/prefetch/prefetch_importer.h" + +#include "components/offline_pages/core/prefetch/prefetch_dispatcher.h" + +namespace offline_pages { + +PrefetchImporter::PrefetchImporter(PrefetchDispatcher* dispatcher) + : dispatcher_(dispatcher) {} + +void PrefetchImporter::NotifyImportCompleted(int64_t offline_id, bool success) { + dispatcher_->ImportCompleted(offline_id, success); +} + +} // namespace offline_pages \ No newline at end of file
diff --git a/components/offline_pages/core/prefetch/prefetch_importer.h b/components/offline_pages/core/prefetch/prefetch_importer.h index 1ef3edf6..c9e84c7 100644 --- a/components/offline_pages/core/prefetch/prefetch_importer.h +++ b/components/offline_pages/core/prefetch/prefetch_importer.h
@@ -5,36 +5,30 @@ #ifndef COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_IMPORTER_H_ #define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_IMPORTER_H_ -#include <string> - -class GURL; -namespace base { -class FilePath; -} // namespace base +#include "components/offline_pages/core/prefetch/prefetch_types.h" namespace offline_pages { -struct ClientId; +class PrefetchDispatcher; // Interface to import the downloaded archive such that it can be rendered as // offline page. class PrefetchImporter { public: - using CompletedCallback = - base::Callback<void(bool success, int64_t offline_id)>; - + explicit PrefetchImporter(PrefetchDispatcher* dispatcher); virtual ~PrefetchImporter() = default; // Imports the downloaded archive by moving the file into archive directory // and creating an entry in the offline metadata database. - virtual void ImportFile(const GURL& url, - const GURL& original_url, - const base::string16& title, - int64_t offline_id, - const ClientId& client_id, - const base::FilePath& file_path, - int64_t file_size, - const CompletedCallback& callback) = 0; + virtual void ImportArchive(const PrefetchArchiveInfo& info) = 0; + + protected: + void NotifyImportCompleted(int64_t offline_id, bool success); + + private: + PrefetchDispatcher* dispatcher_; + + DISALLOW_COPY_AND_ASSIGN(PrefetchImporter); }; } // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_item.cc b/components/offline_pages/core/prefetch/prefetch_item.cc index 76f19fce..2fcc6a6 100644 --- a/components/offline_pages/core/prefetch/prefetch_item.cc +++ b/components/offline_pages/core/prefetch/prefetch_item.cc
@@ -30,7 +30,8 @@ archive_body_length == other.archive_body_length && creation_time == other.creation_time && freshness_time == other.freshness_time && - error_code == other.error_code; + error_code == other.error_code && title == other.title && + file_path == other.file_path && file_size == other.file_size; } bool PrefetchItem::operator!=(const PrefetchItem& other) const {
diff --git a/components/offline_pages/core/prefetch/prefetch_item.h b/components/offline_pages/core/prefetch/prefetch_item.h index 768f73ad..3a64e11 100644 --- a/components/offline_pages/core/prefetch/prefetch_item.h +++ b/components/offline_pages/core/prefetch/prefetch_item.h
@@ -8,6 +8,7 @@ #include <stdint.h> #include <string> +#include "base/files/file_path.h" #include "base/time/time.h" #include "components/offline_pages/core/client_id.h" #include "components/offline_pages/core/prefetch/prefetch_types.h" @@ -101,6 +102,15 @@ // The reason why the item was set to the FINISHED state. Should be // disregarded until reaching that state. PrefetchItemErrorCode error_code = PrefetchItemErrorCode::SUCCESS; + + // The title of the page. + base::string16 title; + + // The file path to the archive of the page. + base::FilePath file_path; + + // The size of the archive file. + int64_t file_size = 0; }; } // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_types.cc b/components/offline_pages/core/prefetch/prefetch_types.cc index 7f68f57..ab6d0a2 100644 --- a/components/offline_pages/core/prefetch/prefetch_types.cc +++ b/components/offline_pages/core/prefetch/prefetch_types.cc
@@ -14,7 +14,7 @@ PrefetchDownloadResult::PrefetchDownloadResult(const std::string& download_id, const base::FilePath& file_path, - uint64_t file_size) + int64_t file_size) : download_id(download_id), success(true), file_path(file_path), @@ -23,4 +23,15 @@ PrefetchDownloadResult::PrefetchDownloadResult( const PrefetchDownloadResult& other) = default; +PrefetchArchiveInfo::PrefetchArchiveInfo() = default; + +PrefetchArchiveInfo::PrefetchArchiveInfo(const PrefetchArchiveInfo& other) = + default; + +PrefetchArchiveInfo::~PrefetchArchiveInfo() = default; + +bool PrefetchArchiveInfo::empty() const { + return offline_id == 0; +} + } // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_types.h b/components/offline_pages/core/prefetch/prefetch_types.h index 3708133..55a7cb7 100644 --- a/components/offline_pages/core/prefetch/prefetch_types.h +++ b/components/offline_pages/core/prefetch/prefetch_types.h
@@ -88,6 +88,11 @@ RECEIVED_BUNDLE, // This item's archive is currently being downloaded. DOWNLOADING, + // The archive has been downloaded, waiting to be imported into offline pages + // model. + DOWNLOADED, + // The archive is being imported into offline pages model. + IMPORTING, // Item has finished processing, successfully or otherwise, and is waiting to // be processed for stats reporting to UMA. FINISHED, @@ -106,6 +111,8 @@ // Got too many Urls from suggestions, canceled this one. See kMaxUrlsToSend // defined in GeneratePageBundleTask. TOO_MANY_NEW_URLS, + DOWNLOAD_ERROR, + IMPORT_ERROR, }; // Callback invoked upon completion of a prefetch request. @@ -133,19 +140,35 @@ PrefetchDownloadResult(); PrefetchDownloadResult(const std::string& download_id, const base::FilePath& file_path, - uint64_t file_size); + int64_t file_size); PrefetchDownloadResult(const PrefetchDownloadResult& other); std::string download_id; bool success = false; base::FilePath file_path; - uint64_t file_size = 0u; + int64_t file_size = 0; }; // Callback invoked upon completion of a download. using PrefetchDownloadCompletedCallback = base::Callback<void(const PrefetchDownloadResult& result)>; +// Describes all the info needed to import an archive. +struct PrefetchArchiveInfo { + PrefetchArchiveInfo(); + PrefetchArchiveInfo(const PrefetchArchiveInfo& other); + ~PrefetchArchiveInfo(); + bool empty() const; + + int64_t offline_id = 0; // Defaults to invalid id. + ClientId client_id; + GURL url; + GURL final_archived_url; + base::string16 title; + base::FilePath file_path; + int64_t file_size = 0; +}; + } // namespace offline_pages #endif // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_TYPES_H_
diff --git a/components/offline_pages/core/prefetch/store/prefetch_store.cc b/components/offline_pages/core/prefetch/store/prefetch_store.cc index 626c021..43c16a6 100644 --- a/components/offline_pages/core/prefetch/store/prefetch_store.cc +++ b/components/offline_pages/core/prefetch/store/prefetch_store.cc
@@ -53,7 +53,10 @@ " requested_url VARCHAR NOT NULL DEFAULT ''," " final_archived_url VARCHAR NOT NULL DEFAULT ''," " operation_name VARCHAR NOT NULL DEFAULT ''," - " archive_body_name VARCHAR NOT NULL DEFAULT ''" + " archive_body_name VARCHAR NOT NULL DEFAULT ''," + " title VARCHAR NOT NULL DEFAULT ''," + " file_path VARCHAR NOT NULL DEFAULT ''," + " file_size INTEGER NOT NULL DEFAULT 0" ")"; return db->Execute(kSql); }
diff --git a/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc b/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc index 4110ee991..6e6e3d7a 100644 --- a/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc +++ b/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc
@@ -39,12 +39,15 @@ "requested_url, " "final_archived_url, " "operation_name, " - "archive_body_name"; + "archive_body_name, " + "title, " + "file_path, " + "file_size"; bool InsertPrefetchItemSync(const PrefetchItem& item, sql::Connection* db) { static const std::string kSql = base::StringPrintf( "INSERT INTO prefetch_items (%s)" - " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", kSqlAllColumnNames); sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql.c_str())); statement.BindInt64(0, item.offline_id); @@ -63,6 +66,9 @@ statement.BindString(13, item.final_archived_url.spec()); statement.BindString(14, item.operation_name); statement.BindString(15, item.archive_body_name); + statement.BindString16(16, item.title); + statement.BindString(17, item.file_path.AsUTF8Unsafe()); + statement.BindInt64(18, item.file_size); return statement.Run(); } @@ -80,7 +86,7 @@ // Populates the PrefetchItem with the data from the current row of the passed // in statement following the natural column ordering. void PopulatePrefetchItem(const sql::Statement& statement, PrefetchItem* item) { - DCHECK_EQ(16, statement.ColumnCount()); + DCHECK_EQ(19, statement.ColumnCount()); DCHECK(item); // Fields are assigned to the item in the order they are stored in the SQL @@ -101,6 +107,9 @@ item->final_archived_url = GURL(statement.ColumnString(13)); item->operation_name = statement.ColumnString(14); item->archive_body_name = statement.ColumnString(15); + item->title = statement.ColumnString16(16); + item->file_path = base::FilePath::FromUTF8Unsafe(statement.ColumnString(17)); + item->file_size = statement.ColumnInt64(18); } std::unique_ptr<PrefetchItem> GetPrefetchItemSync(int64_t offline_id,
diff --git a/components/offline_pages/core/prefetch/store/prefetch_store_utils.h b/components/offline_pages/core/prefetch/store/prefetch_store_utils.h index 036b672..7c8a77d 100644 --- a/components/offline_pages/core/prefetch/store/prefetch_store_utils.h +++ b/components/offline_pages/core/prefetch/store/prefetch_store_utils.h
@@ -12,6 +12,7 @@ } // namespace sql namespace offline_pages { + // Useful helper functions to implement PrefetchStore related operations. class PrefetchStoreUtils { public:
diff --git a/components/offline_pages/core/prefetch/test_prefetch_dispatcher.cc b/components/offline_pages/core/prefetch/test_prefetch_dispatcher.cc index af2c771..1fd8418 100644 --- a/components/offline_pages/core/prefetch/test_prefetch_dispatcher.cc +++ b/components/offline_pages/core/prefetch/test_prefetch_dispatcher.cc
@@ -46,5 +46,11 @@ operation_list.push_back(operation_name); } +void TestPrefetchDispatcher::DownloadCompleted( + const PrefetchDownloadResult& download_result) {} + +void TestPrefetchDispatcher::ImportCompleted(int64_t offline_id, bool success) { +} + void TestPrefetchDispatcher::RequestFinishBackgroundTaskForTest() {} } // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/test_prefetch_dispatcher.h b/components/offline_pages/core/prefetch/test_prefetch_dispatcher.h index 6534ac9e..86bb1ded 100644 --- a/components/offline_pages/core/prefetch/test_prefetch_dispatcher.h +++ b/components/offline_pages/core/prefetch/test_prefetch_dispatcher.h
@@ -32,6 +32,9 @@ void SchedulePipelineProcessing() override; void GCMOperationCompletedMessageReceived( const std::string& operation_name) override; + void DownloadCompleted( + const PrefetchDownloadResult& download_result) override; + void ImportCompleted(int64_t offline_id, bool success) override; void RequestFinishBackgroundTaskForTest() override; std::string latest_name_space;
diff --git a/components/offline_pages/core/prefetch/test_prefetch_importer.h b/components/offline_pages/core/prefetch/test_prefetch_importer.h index 939b4ea..1600ef2 100644 --- a/components/offline_pages/core/prefetch/test_prefetch_importer.h +++ b/components/offline_pages/core/prefetch/test_prefetch_importer.h
@@ -12,17 +12,10 @@ // Testing prefetch importer that does nothing. class TestPrefetchImporter : public PrefetchImporter { public: - TestPrefetchImporter() {} + TestPrefetchImporter() : PrefetchImporter(nullptr) {} ~TestPrefetchImporter() override = default; - void ImportFile(const GURL& url, - const GURL& original_url, - const base::string16& title, - int64_t offline_id, - const ClientId& client_id, - const base::FilePath& file_path, - int64_t file_size, - const CompletedCallback& callback) override {} + void ImportArchive(const PrefetchArchiveInfo& archive) override {} }; } // namespace offline_pages
diff --git a/components/password_manager/content/browser/BUILD.gn b/components/password_manager/content/browser/BUILD.gn index 3081181..352243c4 100644 --- a/components/password_manager/content/browser/BUILD.gn +++ b/components/password_manager/content/browser/BUILD.gn
@@ -6,12 +6,12 @@ sources = [ "bad_message.cc", "bad_message.h", + "content_credential_manager.cc", + "content_credential_manager.h", "content_password_manager_driver.cc", "content_password_manager_driver.h", "content_password_manager_driver_factory.cc", "content_password_manager_driver_factory.h", - "credential_manager_impl.cc", - "credential_manager_impl.h", "password_manager_internals_service_factory.cc", "password_manager_internals_service_factory.h", ] @@ -35,8 +35,8 @@ source_set("unit_tests") { testonly = true sources = [ + "content_credential_manager_unittest.cc", "content_password_manager_driver_unittest.cc", - "credential_manager_impl_unittest.cc", ] deps = [ ":browser",
diff --git a/components/password_manager/content/browser/content_credential_manager.cc b/components/password_manager/content/browser/content_credential_manager.cc new file mode 100644 index 0000000..4097c85 --- /dev/null +++ b/components/password_manager/content/browser/content_credential_manager.cc
@@ -0,0 +1,71 @@ +// 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 "components/password_manager/content/browser/content_credential_manager.h" + +#include <utility> + +#include "base/bind.h" +#include "base/memory/ptr_util.h" + +namespace password_manager { + +// ContentCredentialManager ------------------------------------------------- + +ContentCredentialManager::ContentCredentialManager( + PasswordManagerClient* client) + : impl_(client), binding_(this) {} + +ContentCredentialManager::~ContentCredentialManager() {} + +void ContentCredentialManager::BindRequest( + mojom::CredentialManagerAssociatedRequest request) { + DCHECK(!binding_.is_bound()); + binding_.Bind(std::move(request)); + + // The browser side will close the message pipe on DidFinishNavigation before + // the renderer side would be destroyed, and the renderer never explicitly + // closes the pipe. So a connection error really means an error here, in which + // case the renderer will try to reconnect when the next call to the API is + // made. Make sure this implementation will no longer be bound to a broken + // pipe once that happens, so the DCHECK above will succeed. + binding_.set_connection_error_handler(base::Bind( + &ContentCredentialManager::DisconnectBinding, base::Unretained(this))); +} + +bool ContentCredentialManager::HasBinding() const { + return binding_.is_bound(); +} + +void ContentCredentialManager::DisconnectBinding() { + binding_.Close(); +} + +bool ContentCredentialManager::IsZeroClickAllowed() const { + return impl_.IsZeroClickAllowed(); +} + +PasswordStore::FormDigest +ContentCredentialManager::GetSynthesizedFormForOrigin() const { + return impl_.GetSynthesizedFormForOrigin(); +} + +void ContentCredentialManager::Store(const CredentialInfo& credential, + StoreCallback callback) { + impl_.Store(credential, std::move(callback)); +} + +void ContentCredentialManager::PreventSilentAccess( + PreventSilentAccessCallback callback) { + impl_.PreventSilentAccess(std::move(callback)); +} + +void ContentCredentialManager::Get(CredentialMediationRequirement mediation, + bool include_passwords, + const std::vector<GURL>& federations, + GetCallback callback) { + impl_.Get(mediation, include_passwords, federations, std::move(callback)); +} + +} // namespace password_manager
diff --git a/components/password_manager/content/browser/content_credential_manager.h b/components/password_manager/content/browser/content_credential_manager.h new file mode 100644 index 0000000..8712c07e --- /dev/null +++ b/components/password_manager/content/browser/content_credential_manager.h
@@ -0,0 +1,55 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PASSWORD_MANAGER_CONTENT_BROWSER_CONTENT_CREDENTIAL_MANAGER_H_ +#define COMPONENTS_PASSWORD_MANAGER_CONTENT_BROWSER_CONTENT_CREDENTIAL_MANAGER_H_ + +#include "components/password_manager/core/browser/credential_manager_impl.h" +#include "components/password_manager/core/common/credential_manager_types.h" +#include "mojo/public/cpp/bindings/associated_binding.h" +#include "third_party/WebKit/public/platform/modules/credentialmanager/credential_manager.mojom.h" + +class GURL; + +namespace password_manager { +class PasswordManagerClient; +struct CredentialInfo; + +// Implements mojom::CredentialManager using core class CredentialManagerImpl. +// Methods Store, PreventSilentAccess and Get are invoked from the renderer +// with callbacks as arguments. PasswordManagerClient is used to invoke UI. +class ContentCredentialManager : public mojom::CredentialManager { + public: + explicit ContentCredentialManager(PasswordManagerClient* client); + ~ContentCredentialManager() override; + + void BindRequest(mojom::CredentialManagerAssociatedRequest request); + bool HasBinding() const; + void DisconnectBinding(); + + // TODO(tgarbus): Methods IsZeroClickAllowed and GetSynthesizedFormForOrigin + // are used only in unit tests. Remove them after the tests have been moved + // to core. + bool IsZeroClickAllowed() const; + PasswordStore::FormDigest GetSynthesizedFormForOrigin() const; + + // mojom::CredentialManager methods: + void Store(const CredentialInfo& credential, StoreCallback callback) override; + void PreventSilentAccess(PreventSilentAccessCallback callback) override; + void Get(CredentialMediationRequirement mediation, + bool include_passwords, + const std::vector<GURL>& federations, + GetCallback callback) override; + + private: + CredentialManagerImpl impl_; + + mojo::AssociatedBinding<mojom::CredentialManager> binding_; + + DISALLOW_COPY_AND_ASSIGN(ContentCredentialManager); +}; + +} // namespace password_manager + +#endif // COMPONENTS_PASSWORD_MANAGER_CONTENT_BROWSER_CONTENT_CREDENTIAL_MANAGER_H_
diff --git a/components/password_manager/content/browser/credential_manager_impl_unittest.cc b/components/password_manager/content/browser/content_credential_manager_unittest.cc similarity index 89% rename from components/password_manager/content/browser/credential_manager_impl_unittest.cc rename to components/password_manager/content/browser/content_credential_manager_unittest.cc index 5e79909..d74747c 100644 --- a/components/password_manager/content/browser/credential_manager_impl_unittest.cc +++ b/components/password_manager/content/browser/content_credential_manager_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/password_manager/content/browser/credential_manager_impl.h" +#include "components/password_manager/content/browser/content_credential_manager.h" #include <stdint.h> @@ -12,24 +12,18 @@ #include <vector> #include "base/bind.h" -#include "base/command_line.h" -#include "base/location.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "components/password_manager/core/browser/android_affiliation/mock_affiliated_match_helper.h" -#include "components/password_manager/core/browser/credential_manager_password_form_manager.h" #include "components/password_manager/core/browser/password_manager.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" -#include "components/password_manager/core/browser/stub_password_manager_driver.h" #include "components/password_manager/core/browser/test_password_store.h" #include "components/password_manager/core/common/credential_manager_types.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/testing_pref_service.h" -#include "content/public/browser/web_contents.h" -#include "content/public/test/mock_render_process_host.h" #include "content/public/test/test_renderer_host.h" #include "content/public/test/test_utils.h" #include "testing/gmock/include/gmock/gmock.h" @@ -38,7 +32,6 @@ #include "url/url_constants.h" using content::BrowserContext; -using content::WebContents; using testing::_; using testing::ElementsAre; @@ -69,7 +62,8 @@ const GURL& origin, const CredentialsCallback& callback)); - explicit MockPasswordManagerClient(PasswordStore* store) : store_(store) { + explicit MockPasswordManagerClient(PasswordStore* store) + : store_(store), password_manager_(this) { prefs_.registry()->RegisterBooleanPref(prefs::kCredentialsEnableAutosignin, true); prefs_.registry()->RegisterBooleanPref( @@ -94,6 +88,12 @@ PrefService* GetPrefs() override { return &prefs_; } + const PasswordManager* GetPasswordManager() const override { + return &password_manager_; + } + + const GURL& GetLastCommittedEntryURL() const override { return example_url_; } + bool PromptUserToChooseCredentials( std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms, const GURL& origin, @@ -134,55 +134,21 @@ TestingPrefServiceSimple prefs_; PasswordStore* store_; std::unique_ptr<PasswordFormManager> manager_; + PasswordManager password_manager_; + const GURL example_url_ = GURL(kTestWebOrigin); DISALLOW_COPY_AND_ASSIGN(MockPasswordManagerClient); }; -class TestCredentialManagerImpl : public CredentialManagerImpl { - public: - TestCredentialManagerImpl(content::WebContents* web_contents, - PasswordManagerClient* client, - PasswordManagerDriver* driver); - - private: - base::WeakPtr<PasswordManagerDriver> GetDriver() override; - - base::WeakPtr<PasswordManagerDriver> driver_; -}; - -TestCredentialManagerImpl::TestCredentialManagerImpl( - content::WebContents* web_contents, - PasswordManagerClient* client, - PasswordManagerDriver* driver) - : CredentialManagerImpl(web_contents, client), - driver_(driver->AsWeakPtr()) {} - -base::WeakPtr<PasswordManagerDriver> TestCredentialManagerImpl::GetDriver() { - return driver_; -} - -class SlightlyLessStubbyPasswordManagerDriver - : public StubPasswordManagerDriver { - public: - explicit SlightlyLessStubbyPasswordManagerDriver( - PasswordManagerClient* client) - : password_manager_(client) {} - - PasswordManager* GetPasswordManager() override { return &password_manager_; } - - private: - PasswordManager password_manager_; -}; - -// Callbacks from CredentialManagerImpl methods +// Callbacks from ContentCredentialManager methods void RespondCallback(bool* called) { *called = true; } void GetCredentialCallback(bool* called, - mojom::CredentialManagerError* out_error, + CredentialManagerError* out_error, base::Optional<CredentialInfo>* out_info, - mojom::CredentialManagerError error, + CredentialManagerError error, const base::Optional<CredentialInfo>& info) { *called = true; *out_error = error; @@ -197,9 +163,9 @@ } // namespace -class CredentialManagerImplTest : public content::RenderViewHostTestHarness { +class ContentCredentialManagerTest : public content::RenderViewHostTestHarness { public: - CredentialManagerImplTest() {} + ContentCredentialManagerTest() {} void SetUp() override { content::RenderViewHostTestHarness::SetUp(); @@ -207,10 +173,7 @@ store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr); client_.reset( new testing::NiceMock<MockPasswordManagerClient>(store_.get())); - stub_driver_.reset( - new SlightlyLessStubbyPasswordManagerDriver(client_.get())); - cm_service_impl_.reset(new TestCredentialManagerImpl( - web_contents(), client_.get(), stub_driver_.get())); + cm_service_impl_.reset(new ContentCredentialManager(client_.get())); ON_CALL(*client_, IsSavingAndFillingEnabledForCurrentPage()) .WillByDefault(testing::Return(true)); ON_CALL(*client_, IsFillingEnabledForCurrentPage()) @@ -225,7 +188,7 @@ form_.display_name = base::ASCIIToUTF16("Display Name"); form_.icon_url = GURL("https://example.com/icon.png"); form_.password_value = base::ASCIIToUTF16("Password"); - form_.origin = web_contents()->GetLastCommittedURL().GetOrigin(); + form_.origin = client_->GetLastCommittedEntryURL(); form_.signon_realm = form_.origin.GetOrigin().spec(); form_.scheme = autofill::PasswordForm::SCHEME_HTML; form_.skip_zero_click = false; @@ -287,7 +250,7 @@ bool include_passwords, const std::vector<GURL>& federations) { bool called = false; - mojom::CredentialManagerError error; + CredentialManagerError error; base::Optional<CredentialInfo> credential; EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _)) .Times(testing::Exactly(0)); @@ -298,7 +261,7 @@ RunAllPendingTasks(); EXPECT_TRUE(called); - EXPECT_EQ(mojom::CredentialManagerError::SUCCESS, error); + EXPECT_EQ(CredentialManagerError::SUCCESS, error); EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY, credential->type); } @@ -307,7 +270,7 @@ const std::vector<GURL>& federations, CredentialType type) { bool called = false; - mojom::CredentialManagerError error; + CredentialManagerError error; base::Optional<CredentialInfo> credential; EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _)) .Times(testing::Exactly(0)); @@ -318,7 +281,7 @@ RunAllPendingTasks(); EXPECT_TRUE(called); - EXPECT_EQ(mojom::CredentialManagerError::SUCCESS, error); + EXPECT_EQ(CredentialManagerError::SUCCESS, error); EXPECT_EQ(type, credential->type); } @@ -327,7 +290,7 @@ const std::vector<GURL>& federations, CredentialType type) { bool called = false; - mojom::CredentialManagerError error; + CredentialManagerError error; base::Optional<CredentialInfo> credential; CallGet(mediation, include_passwords, federations, base::Bind(&GetCredentialCallback, &called, &error, &credential)); @@ -335,27 +298,27 @@ RunAllPendingTasks(); EXPECT_TRUE(called); - EXPECT_EQ(mojom::CredentialManagerError::SUCCESS, error); + EXPECT_EQ(CredentialManagerError::SUCCESS, error); EXPECT_EQ(type, credential->type); } - CredentialManagerImpl* cm_service_impl() { return cm_service_impl_.get(); } + ContentCredentialManager* cm_service_impl() { return cm_service_impl_.get(); } - // Helpers for testing CredentialManagerImpl methods. + // Helpers for testing ContentCredentialManager methods. void CallStore(const CredentialInfo& info, - CredentialManagerImpl::StoreCallback callback) { + ContentCredentialManager::StoreCallback callback) { cm_service_impl_->Store(info, std::move(callback)); } void CallPreventSilentAccess( - CredentialManagerImpl::PreventSilentAccessCallback callback) { + ContentCredentialManager::PreventSilentAccessCallback callback) { cm_service_impl_->PreventSilentAccess(std::move(callback)); } void CallGet(CredentialMediationRequirement mediation, bool include_passwords, const std::vector<GURL>& federations, - CredentialManagerImpl::GetCallback callback) { + ContentCredentialManager::GetCallback callback) { cm_service_impl_->Get(mediation, include_passwords, federations, std::move(callback)); } @@ -371,11 +334,10 @@ autofill::PasswordForm cross_origin_form_; scoped_refptr<TestPasswordStore> store_; std::unique_ptr<testing::NiceMock<MockPasswordManagerClient>> client_; - std::unique_ptr<SlightlyLessStubbyPasswordManagerDriver> stub_driver_; - std::unique_ptr<CredentialManagerImpl> cm_service_impl_; + std::unique_ptr<ContentCredentialManager> cm_service_impl_; }; -TEST_F(CredentialManagerImplTest, IsZeroClickAllowed) { +TEST_F(ContentCredentialManagerTest, IsZeroClickAllowed) { // IsZeroClickAllowed is uneffected by the first-run status. client_->set_zero_click_enabled(true); client_->set_first_run_seen(true); @@ -394,7 +356,7 @@ EXPECT_FALSE(cm_service_impl()->IsZeroClickAllowed()); } -TEST_F(CredentialManagerImplTest, CredentialManagerOnStore) { +TEST_F(ContentCredentialManagerTest, CredentialManagerOnStore) { CredentialInfo info(form_, CredentialType::CREDENTIAL_TYPE_PASSWORD); EXPECT_CALL(*client_, PromptUserToSavePasswordPtr(_)) .Times(testing::Exactly(1)); @@ -424,7 +386,7 @@ EXPECT_EQ(autofill::PasswordForm::SCHEME_HTML, new_form.scheme); } -TEST_F(CredentialManagerImplTest, CredentialManagerOnStoreFederated) { +TEST_F(ContentCredentialManagerTest, CredentialManagerOnStoreFederated) { EXPECT_CALL(*client_, PromptUserToSavePasswordPtr(_)) .Times(testing::Exactly(1)); EXPECT_CALL(*client_, NotifyStorePasswordCalled()); @@ -457,7 +419,7 @@ EXPECT_EQ(autofill::PasswordForm::SCHEME_HTML, new_form.scheme); } -TEST_F(CredentialManagerImplTest, StoreFederatedAfterPassword) { +TEST_F(ContentCredentialManagerTest, StoreFederatedAfterPassword) { // Populate the PasswordStore with a form. store_->AddLogin(form_); @@ -492,7 +454,7 @@ ElementsAre(federated)); } -TEST_F(CredentialManagerImplTest, CredentialManagerStoreOverwrite) { +TEST_F(ContentCredentialManagerTest, CredentialManagerStoreOverwrite) { // Populate the PasswordStore with a form. store_->AddLogin(form_); RunAllPendingTasks(); @@ -519,7 +481,7 @@ passwords[form_.signon_realm][0].password_value); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerStorePSLMatchDoesNotTriggerBubble) { autofill::PasswordForm psl_form = subdomain_form_; psl_form.username_value = form_.username_value; @@ -545,7 +507,7 @@ EXPECT_EQ(1U, passwords[psl_form.signon_realm].size()); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerStorePSLMatchWithDifferentUsernameTriggersBubble) { base::string16 delta = base::ASCIIToUTF16("_totally_different"); autofill::PasswordForm psl_form = subdomain_form_; @@ -576,7 +538,7 @@ EXPECT_EQ(info.password, pending_cred.password_value); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerStorePSLMatchWithDifferentPasswordTriggersBubble) { base::string16 delta = base::ASCIIToUTF16("_totally_different"); autofill::PasswordForm psl_form = subdomain_form_; @@ -607,7 +569,7 @@ EXPECT_EQ(info.password, pending_cred.password_value); } -TEST_F(CredentialManagerImplTest, CredentialManagerStoreOverwriteZeroClick) { +TEST_F(ContentCredentialManagerTest, CredentialManagerStoreOverwriteZeroClick) { form_.skip_zero_click = true; store_->AddLogin(form_); RunAllPendingTasks(); @@ -628,7 +590,7 @@ EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerFederatedStoreOverwriteZeroClick) { form_.federation_origin = url::Origin(GURL("https://example.com/")); form_.password_value = base::string16(); @@ -653,7 +615,7 @@ EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click); } -TEST_F(CredentialManagerImplTest, CredentialManagerGetOverwriteZeroClick) { +TEST_F(ContentCredentialManagerTest, CredentialManagerGetOverwriteZeroClick) { // Set the global zero click flag on, and populate the PasswordStore with a // form that's set to skip zero click and has a primary key that won't match // credentials initially created via `store()`. @@ -671,7 +633,7 @@ EXPECT_CALL(*client_, NotifyUserAutoSigninPtr()).Times(testing::Exactly(0)); bool called = false; - mojom::CredentialManagerError error; + CredentialManagerError error; base::Optional<CredentialInfo> credential; CallGet(CredentialMediationRequirement::kOptional, true, federations, base::Bind(&GetCredentialCallback, &called, &error, &credential)); @@ -679,14 +641,14 @@ RunAllPendingTasks(); EXPECT_TRUE(called); - EXPECT_EQ(mojom::CredentialManagerError::SUCCESS, error); + EXPECT_EQ(CredentialManagerError::SUCCESS, error); // Verify that the update toggled the skip_zero_click flag. TestPasswordStore::PasswordMap passwords = store_->stored_passwords(); EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerSignInWithSavingDisabledForCurrentPage) { CredentialInfo info(form_, CredentialType::CREDENTIAL_TYPE_PASSWORD); EXPECT_CALL(*client_, IsSavingAndFillingEnabledForCurrentPage()) @@ -704,7 +666,7 @@ EXPECT_FALSE(client_->pending_manager()); } -TEST_F(CredentialManagerImplTest, CredentialManagerOnPreventSilentAccess) { +TEST_F(ContentCredentialManagerTest, CredentialManagerOnPreventSilentAccess) { store_->AddLogin(form_); store_->AddLogin(subdomain_form_); store_->AddLogin(cross_origin_form_); @@ -736,7 +698,7 @@ EXPECT_FALSE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnPreventSilentAccessIncognito) { EXPECT_CALL(*client_, IsSavingAndFillingEnabledForCurrentPage()) .WillRepeatedly(testing::Return(false)); @@ -760,7 +722,7 @@ EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnPreventSilentAccessWithAffiliation) { store_->AddLogin(form_); store_->AddLogin(cross_origin_form_); @@ -797,7 +759,7 @@ EXPECT_FALSE(passwords[affiliated_form2_.signon_realm][0].skip_zero_click); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnRequestCredentialWithEmptyPasswordStore) { std::vector<GURL> federations; EXPECT_CALL(*client_, PromptUserToSavePasswordPtr(_)) @@ -810,7 +772,7 @@ federations, CredentialType::CREDENTIAL_TYPE_EMPTY); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnRequestCredentialWithEmptyUsernames) { form_.username_value.clear(); store_->AddLogin(form_); @@ -823,7 +785,7 @@ federations, CredentialType::CREDENTIAL_TYPE_EMPTY); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnRequestCredentialWithPSLCredential) { store_->AddLogin(subdomain_form_); subdomain_form_.is_public_suffix_match = true; @@ -837,7 +799,7 @@ CredentialType::CREDENTIAL_TYPE_PASSWORD); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnRequestCredentialWithPSLAndNormalCredentials) { store_->AddLogin(form_); store_->AddLogin(origin_path_form_); @@ -853,7 +815,7 @@ CredentialType::CREDENTIAL_TYPE_PASSWORD); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnRequestCredentialWithEmptyAndNonemptyUsernames) { store_->AddLogin(form_); autofill::PasswordForm empty = form_; @@ -869,7 +831,7 @@ CredentialType::CREDENTIAL_TYPE_PASSWORD); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnRequestCredentialWithDuplicates) { // Add 6 credentials. Two buckets of duplicates, one empty username and one // federated one. There should be just 3 in the account chooser. @@ -904,7 +866,7 @@ _, _)); bool called = false; - mojom::CredentialManagerError error; + CredentialManagerError error; base::Optional<CredentialInfo> credential; std::vector<GURL> federations; federations.push_back(GURL("https://google.com/")); @@ -914,7 +876,7 @@ RunAllPendingTasks(); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnRequestCredentialWithCrossOriginPasswordStore) { store_->AddLogin(cross_origin_form_); @@ -929,7 +891,7 @@ federations, CredentialType::CREDENTIAL_TYPE_EMPTY); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnRequestCredentialWithFullPasswordStore) { client_->set_zero_click_enabled(false); store_->AddLogin(form_); @@ -940,7 +902,7 @@ EXPECT_CALL(*client_, NotifyUserAutoSigninPtr()).Times(testing::Exactly(0)); bool called = false; - mojom::CredentialManagerError error; + CredentialManagerError error; base::Optional<CredentialInfo> credential; CallGet(CredentialMediationRequirement::kOptional, true, federations, base::Bind(&GetCredentialCallback, &called, &error, &credential)); @@ -948,11 +910,11 @@ RunAllPendingTasks(); EXPECT_TRUE(called); - EXPECT_EQ(mojom::CredentialManagerError::SUCCESS, error); + EXPECT_EQ(CredentialManagerError::SUCCESS, error); } TEST_F( - CredentialManagerImplTest, + ContentCredentialManagerTest, CredentialManagerOnRequestCredentialWithZeroClickOnlyEmptyPasswordStore) { std::vector<GURL> federations; EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _)) @@ -963,7 +925,7 @@ federations); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnRequestCredentialWithZeroClickOnlyFullPasswordStore) { store_->AddLogin(form_); client_->set_first_run_seen(true); @@ -977,7 +939,7 @@ CredentialType::CREDENTIAL_TYPE_PASSWORD); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnRequestCredentialWithoutPasswords) { store_->AddLogin(form_); client_->set_first_run_seen(true); @@ -990,7 +952,7 @@ federations); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnRequestCredentialFederatedMatch) { form_.federation_origin = url::Origin(GURL("https://example.com/")); form_.password_value = base::string16(); @@ -1007,7 +969,7 @@ CredentialType::CREDENTIAL_TYPE_FEDERATED); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnRequestCredentialFederatedNoMatch) { form_.federation_origin = url::Origin(GURL("https://example.com/")); form_.password_value = base::string16(); @@ -1023,7 +985,7 @@ federations); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnRequestCredentialAffiliatedPasswordMatch) { store_->AddLogin(affiliated_form1_); client_->set_first_run_seen(true); @@ -1044,7 +1006,7 @@ CredentialType::CREDENTIAL_TYPE_PASSWORD); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnRequestCredentialAffiliatedPasswordNoMatch) { store_->AddLogin(affiliated_form1_); client_->set_first_run_seen(true); @@ -1064,7 +1026,7 @@ federations); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnRequestCredentialAffiliatedFederatedMatch) { affiliated_form1_.federation_origin = url::Origin(GURL("https://example.com/")); @@ -1088,7 +1050,7 @@ CredentialType::CREDENTIAL_TYPE_FEDERATED); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnRequestCredentialAffiliatedFederatedNoMatch) { affiliated_form1_.federation_origin = url::Origin(GURL("https://example.com/")); @@ -1111,7 +1073,7 @@ federations); } -TEST_F(CredentialManagerImplTest, RequestCredentialWithoutFirstRun) { +TEST_F(ContentCredentialManagerTest, RequestCredentialWithoutFirstRun) { client_->set_first_run_seen(false); store_->AddLogin(form_); @@ -1125,7 +1087,7 @@ federations); } -TEST_F(CredentialManagerImplTest, RequestCredentialWithFirstRunAndSkip) { +TEST_F(ContentCredentialManagerTest, RequestCredentialWithFirstRunAndSkip) { client_->set_first_run_seen(true); form_.skip_zero_click = true; @@ -1140,7 +1102,7 @@ federations); } -TEST_F(CredentialManagerImplTest, RequestCredentialWithTLSErrors) { +TEST_F(ContentCredentialManagerTest, RequestCredentialWithTLSErrors) { // If we encounter TLS errors, we won't return credentials. EXPECT_CALL(*client_, IsFillingEnabledForCurrentPage()) .WillRepeatedly(testing::Return(false)); @@ -1153,7 +1115,7 @@ federations); } -TEST_F(CredentialManagerImplTest, RequestCredentialWhilePrerendering) { +TEST_F(ContentCredentialManagerTest, RequestCredentialWhilePrerendering) { // The client disallows the credential manager for the current page. EXPECT_CALL(*client_, OnCredentialManagerUsed()) .WillRepeatedly(testing::Return(false)); @@ -1166,7 +1128,7 @@ federations); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnRequestCredentialWithZeroClickOnlyTwoPasswordStore) { store_->AddLogin(form_); store_->AddLogin(origin_path_form_); @@ -1181,7 +1143,7 @@ federations, CredentialType::CREDENTIAL_TYPE_EMPTY); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, OnRequestCredentialWithZeroClickOnlyAndSkipZeroClickPasswordStore) { form_.skip_zero_click = true; store_->AddLogin(form_); @@ -1198,7 +1160,7 @@ federations, CredentialType::CREDENTIAL_TYPE_EMPTY); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, OnRequestCredentialWithZeroClickOnlyCrossOriginPasswordStore) { store_->AddLogin(cross_origin_form_); @@ -1216,7 +1178,7 @@ federations, CredentialType::CREDENTIAL_TYPE_EMPTY); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, CredentialManagerOnRequestCredentialWhileRequestPending) { client_->set_zero_click_enabled(false); store_->AddLogin(form_); @@ -1228,14 +1190,14 @@ // 1st request. bool called_1 = false; - mojom::CredentialManagerError error_1; + CredentialManagerError error_1; base::Optional<CredentialInfo> credential_1; CallGet( CredentialMediationRequirement::kOptional, true, federations, base::Bind(&GetCredentialCallback, &called_1, &error_1, &credential_1)); // 2nd request. bool called_2 = false; - mojom::CredentialManagerError error_2; + CredentialManagerError error_2; base::Optional<CredentialInfo> credential_2; CallGet( CredentialMediationRequirement::kOptional, true, federations, @@ -1250,16 +1212,16 @@ // Check that the second request triggered a rejection. EXPECT_TRUE(called_2); - EXPECT_EQ(mojom::CredentialManagerError::PENDINGREQUEST, error_2); + EXPECT_EQ(CredentialManagerError::PENDINGREQUEST, error_2); EXPECT_FALSE(credential_2); // Check that the first request resolves. EXPECT_TRUE(called_1); - EXPECT_EQ(mojom::CredentialManagerError::SUCCESS, error_1); + EXPECT_EQ(CredentialManagerError::SUCCESS, error_1); EXPECT_NE(CredentialType::CREDENTIAL_TYPE_EMPTY, credential_1->type); } -TEST_F(CredentialManagerImplTest, ResetSkipZeroClickAfterPrompt) { +TEST_F(ContentCredentialManagerTest, ResetSkipZeroClickAfterPrompt) { // Turn on the global zero-click flag, and add two credentials in separate // origins, both set to skip zero-click. client_->set_zero_click_enabled(true); @@ -1293,7 +1255,7 @@ EXPECT_CALL(*client_, NotifyUserAutoSigninPtr()).Times(testing::Exactly(0)); bool called = false; - mojom::CredentialManagerError error; + CredentialManagerError error; base::Optional<CredentialInfo> credential; CallGet(CredentialMediationRequirement::kOptional, true, federations, base::Bind(&GetCredentialCallback, &called, &error, &credential)); @@ -1308,7 +1270,8 @@ EXPECT_TRUE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click); } -TEST_F(CredentialManagerImplTest, NoResetSkipZeroClickAfterPromptInIncognito) { +TEST_F(ContentCredentialManagerTest, + NoResetSkipZeroClickAfterPromptInIncognito) { EXPECT_CALL(*client_, IsIncognito()).WillRepeatedly(testing::Return(true)); // Turn on the global zero-click flag which should be overriden by Incognito. client_->set_zero_click_enabled(true); @@ -1329,7 +1292,7 @@ EXPECT_CALL(*client_, NotifyUserAutoSigninPtr()).Times(testing::Exactly(0)); bool called = false; - mojom::CredentialManagerError error; + CredentialManagerError error; base::Optional<CredentialInfo> credential; CallGet(CredentialMediationRequirement::kOptional, true, std::vector<GURL>(), base::Bind(&GetCredentialCallback, &called, &error, &credential)); @@ -1343,7 +1306,7 @@ EXPECT_TRUE(passwords[form_.signon_realm][0].skip_zero_click); } -TEST_F(CredentialManagerImplTest, IncognitoZeroClickRequestCredential) { +TEST_F(ContentCredentialManagerTest, IncognitoZeroClickRequestCredential) { EXPECT_CALL(*client_, IsIncognito()).WillRepeatedly(testing::Return(true)); store_->AddLogin(form_); @@ -1356,7 +1319,8 @@ federations, CredentialType::CREDENTIAL_TYPE_EMPTY); } -TEST_F(CredentialManagerImplTest, ZeroClickWithAffiliatedFormInPasswordStore) { +TEST_F(ContentCredentialManagerTest, + ZeroClickWithAffiliatedFormInPasswordStore) { // Insert the affiliated form into the store, and mock out the association // with the current origin. As it's the only form matching the origin, it // ought to be returned automagically. @@ -1377,7 +1341,7 @@ CredentialType::CREDENTIAL_TYPE_PASSWORD); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, ZeroClickWithTwoAffiliatedFormsInPasswordStore) { // Insert two affiliated forms into the store, and mock out the association // with the current origin. Multiple forms === no zero-click sign in. @@ -1399,7 +1363,7 @@ federations); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, ZeroClickWithUnaffiliatedFormsInPasswordStore) { // Insert the affiliated form into the store, but don't mock out the // association with the current origin. No association === no zero-click sign @@ -1427,7 +1391,7 @@ federations); } -TEST_F(CredentialManagerImplTest, +TEST_F(ContentCredentialManagerTest, ZeroClickWithFormAndUnaffiliatedFormsInPasswordStore) { // Insert the affiliated form into the store, along with a real form for the // origin, and don't mock out the association with the current origin. No @@ -1449,7 +1413,7 @@ CredentialType::CREDENTIAL_TYPE_PASSWORD); } -TEST_F(CredentialManagerImplTest, ZeroClickWithPSLCredential) { +TEST_F(ContentCredentialManagerTest, ZeroClickWithPSLCredential) { subdomain_form_.skip_zero_click = false; store_->AddLogin(subdomain_form_); @@ -1457,7 +1421,7 @@ std::vector<GURL>()); } -TEST_F(CredentialManagerImplTest, ZeroClickWithPSLAndNormalCredentials) { +TEST_F(ContentCredentialManagerTest, ZeroClickWithPSLAndNormalCredentials) { form_.password_value.clear(); form_.federation_origin = url::Origin(GURL("https://google.com/")); form_.signon_realm = "federation://" + form_.origin.host() + "/google.com"; @@ -1471,7 +1435,7 @@ CredentialType::CREDENTIAL_TYPE_FEDERATED); } -TEST_F(CredentialManagerImplTest, ZeroClickAfterMigratingHttpCredential) { +TEST_F(ContentCredentialManagerTest, ZeroClickAfterMigratingHttpCredential) { // There is an http credential saved. It should be migrated and used for auto // sign-in. form_.origin = HttpURLFromHttps(form_.origin); @@ -1486,7 +1450,7 @@ CredentialType::CREDENTIAL_TYPE_PASSWORD); } -TEST_F(CredentialManagerImplTest, MigrateWithEmptyStore) { +TEST_F(ContentCredentialManagerTest, MigrateWithEmptyStore) { // HTTP scheme is valid for localhost. Nothing should crash. NavigateAndCommit(GURL("http://127.0.0.1:8000/")); @@ -1495,13 +1459,13 @@ federations); } -TEST_F(CredentialManagerImplTest, MediationRequiredPreventsAutoSignIn) { +TEST_F(ContentCredentialManagerTest, MediationRequiredPreventsAutoSignIn) { form_.skip_zero_click = false; store_->AddLogin(form_); std::vector<GURL> federations; bool called = false; - mojom::CredentialManagerError error; + CredentialManagerError error; base::Optional<CredentialInfo> credential; EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _)) @@ -1513,11 +1477,11 @@ RunAllPendingTasks(); EXPECT_TRUE(called); - EXPECT_EQ(mojom::CredentialManagerError::SUCCESS, error); + EXPECT_EQ(CredentialManagerError::SUCCESS, error); EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_PASSWORD, credential->type); } -TEST_F(CredentialManagerImplTest, GetSynthesizedFormForOrigin) { +TEST_F(ContentCredentialManagerTest, GetSynthesizedFormForOrigin) { PasswordStore::FormDigest synthesized = cm_service_impl_->GetSynthesizedFormForOrigin(); EXPECT_EQ(kTestWebOrigin, synthesized.origin.spec()); @@ -1525,7 +1489,7 @@ EXPECT_EQ(autofill::PasswordForm::SCHEME_HTML, synthesized.scheme); } -TEST_F(CredentialManagerImplTest, BlacklistPasswordCredential) { +TEST_F(ContentCredentialManagerTest, BlacklistPasswordCredential) { EXPECT_CALL(*client_, PromptUserToSavePasswordPtr(_)); CredentialInfo info(form_, CredentialType::CREDENTIAL_TYPE_PASSWORD); @@ -1550,7 +1514,7 @@ EXPECT_THAT(passwords[form_.signon_realm], testing::ElementsAre(blacklisted)); } -TEST_F(CredentialManagerImplTest, BlacklistFederatedCredential) { +TEST_F(ContentCredentialManagerTest, BlacklistFederatedCredential) { form_.federation_origin = url::Origin(GURL("https://example.com/")); form_.password_value = base::string16(); form_.signon_realm = "federation://example.com/example.com"; @@ -1581,7 +1545,7 @@ testing::ElementsAre(blacklisted)); } -TEST_F(CredentialManagerImplTest, RespectBlacklistingPasswordCredential) { +TEST_F(ContentCredentialManagerTest, RespectBlacklistingPasswordCredential) { autofill::PasswordForm blacklisted; blacklisted.blacklisted_by_user = true; blacklisted.origin = form_.origin; @@ -1599,7 +1563,7 @@ EXPECT_TRUE(client_->pending_manager()->IsBlacklisted()); } -TEST_F(CredentialManagerImplTest, RespectBlacklistingFederatedCredential) { +TEST_F(ContentCredentialManagerTest, RespectBlacklistingFederatedCredential) { autofill::PasswordForm blacklisted; blacklisted.blacklisted_by_user = true; blacklisted.origin = form_.origin;
diff --git a/components/password_manager/content/browser/credential_manager_impl.h b/components/password_manager/content/browser/credential_manager_impl.h deleted file mode 100644 index 8a4bf3d..0000000 --- a/components/password_manager/content/browser/credential_manager_impl.h +++ /dev/null
@@ -1,111 +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 COMPONENTS_PASSWORD_MANAGER_CONTENT_BROWSER_CONTENT_CREDENTIAL_MANAGER_IMPL_H_ -#define COMPONENTS_PASSWORD_MANAGER_CONTENT_BROWSER_CONTENT_CREDENTIAL_MANAGER_IMPL_H_ - -#include <memory> - -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "components/password_manager/core/browser/credential_manager_password_form_manager.h" -#include "components/password_manager/core/browser/credential_manager_pending_prevent_silent_access_task.h" -#include "components/password_manager/core/browser/credential_manager_pending_request_task.h" -#include "components/password_manager/core/browser/password_store_consumer.h" -#include "components/password_manager/core/common/credential_manager_types.h" -#include "components/prefs/pref_member.h" -#include "content/public/browser/web_contents_observer.h" -#include "mojo/public/cpp/bindings/associated_binding.h" -#include "third_party/WebKit/public/platform/modules/credentialmanager/credential_manager.mojom.h" - -class GURL; - -namespace autofill { -struct PasswordForm; -} - -namespace content { -class WebContents; -} - -namespace password_manager { -class CredentialManagerPasswordFormManager; -class PasswordManagerClient; -class PasswordManagerDriver; -class PasswordStore; -struct CredentialInfo; - -class CredentialManagerImpl - : public mojom::CredentialManager, - public content::WebContentsObserver, - public CredentialManagerPasswordFormManagerDelegate, - public CredentialManagerPendingRequestTaskDelegate, - public CredentialManagerPendingPreventSilentAccessTaskDelegate { - public: - CredentialManagerImpl(content::WebContents* web_contents, - PasswordManagerClient* client); - ~CredentialManagerImpl() override; - - void BindRequest(mojom::CredentialManagerAssociatedRequest request); - bool HasBinding() const; - void DisconnectBinding(); - - // mojom::CredentialManager methods: - void Store(const CredentialInfo& credential, StoreCallback callback) override; - void PreventSilentAccess(PreventSilentAccessCallback callback) override; - void Get(CredentialMediationRequirement mediation, - bool include_passwords, - const std::vector<GURL>& federations, - GetCallback callback) override; - - // CredentialManagerPendingRequestTaskDelegate: - bool IsZeroClickAllowed() const override; - GURL GetOrigin() const override; - void SendCredential(const SendCredentialCallback& send_callback, - const CredentialInfo& info) override; - void SendPasswordForm(const SendCredentialCallback& send_callback, - CredentialMediationRequirement mediation, - const autofill::PasswordForm* form) override; - PasswordManagerClient* client() const override; - - // CredentialManagerPendingSignedOutTaskDelegate: - PasswordStore* GetPasswordStore() override; - void DoneRequiringUserMediation() override; - - // CredentialManagerPasswordFormManagerDelegate: - void OnProvisionalSaveComplete() override; - - // Returns FormDigest for the current URL. - PasswordStore::FormDigest GetSynthesizedFormForOrigin() const; - - private: - // Returns the driver for the current main frame. - // Virtual for testing. - virtual base::WeakPtr<PasswordManagerDriver> GetDriver(); - - PasswordManagerClient* client_; - std::unique_ptr<CredentialManagerPasswordFormManager> form_manager_; - - // Set to false to disable automatic signing in. - BooleanPrefMember auto_signin_enabled_; - - // When 'OnRequestCredential' is called, it in turn calls out to the - // PasswordStore; we push enough data into Pending*Task objects so that - // they can properly respond to the request once the PasswordStore gives - // us data. - std::unique_ptr<CredentialManagerPendingRequestTask> pending_request_; - std::unique_ptr<CredentialManagerPendingPreventSilentAccessTask> - pending_require_user_mediation_; - - mojo::AssociatedBinding<mojom::CredentialManager> binding_; - - base::WeakPtrFactory<CredentialManagerImpl> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(CredentialManagerImpl); -}; - -} // namespace password_manager - -#endif // COMPONENTS_PASSWORD_MANAGER_CONTENT_BROWSER_CONTENT_CREDENTIAL_MANAGER_IMPL_H_
diff --git a/components/password_manager/content/common/credential_manager.typemap b/components/password_manager/content/common/credential_manager.typemap index b3f4a5a..e77f29f14 100644 --- a/components/password_manager/content/common/credential_manager.typemap +++ b/components/password_manager/content/common/credential_manager.typemap
@@ -18,4 +18,5 @@ "password_manager.mojom.CredentialType=password_manager::CredentialType", "password_manager.mojom.CredentialMediationRequirement=password_manager::CredentialMediationRequirement", "password_manager.mojom.CredentialInfo=password_manager::CredentialInfo", + "password_manager.mojom.CredentialManagerError=password_manager::CredentialManagerError", ]
diff --git a/components/password_manager/content/common/credential_manager_struct_traits.cc b/components/password_manager/content/common/credential_manager_struct_traits.cc index 4ca8787b..b55a2d9f 100644 --- a/components/password_manager/content/common/credential_manager_struct_traits.cc +++ b/components/password_manager/content/common/credential_manager_struct_traits.cc
@@ -49,6 +49,53 @@ } // static +mojom::CredentialManagerError +EnumTraits<mojom::CredentialManagerError, CredentialManagerError>::ToMojom( + CredentialManagerError input) { + switch (input) { + case CredentialManagerError::SUCCESS: + return mojom::CredentialManagerError::SUCCESS; + case CredentialManagerError::DISABLED: + return mojom::CredentialManagerError::DISABLED; + case CredentialManagerError::PENDINGREQUEST: + return mojom::CredentialManagerError::PENDINGREQUEST; + case CredentialManagerError::PASSWORDSTOREUNAVAILABLE: + return mojom::CredentialManagerError::PASSWORDSTOREUNAVAILABLE; + case CredentialManagerError::UNKNOWN: + return mojom::CredentialManagerError::UNKNOWN; + } + + NOTREACHED(); + return mojom::CredentialManagerError::UNKNOWN; +} + +// static +bool EnumTraits<mojom::CredentialManagerError, CredentialManagerError>:: + FromMojom(mojom::CredentialManagerError input, + CredentialManagerError* output) { + switch (input) { + case mojom::CredentialManagerError::SUCCESS: + *output = CredentialManagerError::SUCCESS; + return true; + case mojom::CredentialManagerError::DISABLED: + *output = CredentialManagerError::DISABLED; + return true; + case mojom::CredentialManagerError::PENDINGREQUEST: + *output = CredentialManagerError::PENDINGREQUEST; + return true; + case mojom::CredentialManagerError::PASSWORDSTOREUNAVAILABLE: + *output = CredentialManagerError::PASSWORDSTOREUNAVAILABLE; + return true; + case mojom::CredentialManagerError::UNKNOWN: + *output = CredentialManagerError::UNKNOWN; + return true; + } + + NOTREACHED(); + return false; +} + +// static mojom::CredentialMediationRequirement EnumTraits< mojom::CredentialMediationRequirement, CredentialMediationRequirement>::ToMojom(CredentialMediationRequirement
diff --git a/components/password_manager/content/common/credential_manager_struct_traits.h b/components/password_manager/content/common/credential_manager_struct_traits.h index 1fffa0d6..9f4fec56 100644 --- a/components/password_manager/content/common/credential_manager_struct_traits.h +++ b/components/password_manager/content/common/credential_manager_struct_traits.h
@@ -22,6 +22,15 @@ }; template <> +struct EnumTraits<password_manager::mojom::CredentialManagerError, + password_manager::CredentialManagerError> { + static password_manager::mojom::CredentialManagerError ToMojom( + password_manager::CredentialManagerError input); + static bool FromMojom(password_manager::mojom::CredentialManagerError input, + password_manager::CredentialManagerError* output); +}; + +template <> struct EnumTraits<password_manager::mojom::CredentialMediationRequirement, password_manager::CredentialMediationRequirement> { static password_manager::mojom::CredentialMediationRequirement ToMojom(
diff --git a/components/password_manager/content/renderer/credential_manager_client.cc b/components/password_manager/content/renderer/credential_manager_client.cc index f0e3081..5f96590 100644 --- a/components/password_manager/content/renderer/credential_manager_client.cc +++ b/components/password_manager/content/renderer/credential_manager_client.cc
@@ -89,21 +89,21 @@ } blink::WebCredentialManagerError GetWebCredentialManagerErrorFromMojo( - mojom::CredentialManagerError error) { + CredentialManagerError error) { switch (error) { - case mojom::CredentialManagerError::DISABLED: + case CredentialManagerError::DISABLED: return blink::WebCredentialManagerError:: kWebCredentialManagerDisabledError; - case mojom::CredentialManagerError::PENDINGREQUEST: + case CredentialManagerError::PENDINGREQUEST: return blink::WebCredentialManagerError:: kWebCredentialManagerPendingRequestError; - case mojom::CredentialManagerError::PASSWORDSTOREUNAVAILABLE: + case CredentialManagerError::PASSWORDSTOREUNAVAILABLE: return blink::WebCredentialManagerError:: kWebCredentialManagerPasswordStoreUnavailableError; - case mojom::CredentialManagerError::UNKNOWN: + case CredentialManagerError::UNKNOWN: return blink::WebCredentialManagerError:: kWebCredentialManagerUnknownError; - case mojom::CredentialManagerError::SUCCESS: + case CredentialManagerError::SUCCESS: NOTREACHED(); break; } @@ -161,7 +161,7 @@ void NotifySuccess(const CredentialInfo& info); - void NotifyError(mojom::CredentialManagerError error); + void NotifyError(CredentialManagerError error); private: std::unique_ptr<blink::WebCredentialManagerClient::RequestCallbacks> @@ -188,7 +188,7 @@ } } -void RequestCallbacksWrapper::NotifyError(mojom::CredentialManagerError error) { +void RequestCallbacksWrapper::NotifyError(CredentialManagerError error) { if (callbacks_) { callbacks_->OnError(GetWebCredentialManagerErrorFromMojo(error)); callbacks_.reset(); @@ -201,9 +201,9 @@ } void RespondToRequestCallback(RequestCallbacksWrapper* callbacks_wrapper, - mojom::CredentialManagerError error, + CredentialManagerError error, const base::Optional<CredentialInfo>& info) { - if (error == mojom::CredentialManagerError::SUCCESS) { + if (error == CredentialManagerError::SUCCESS) { DCHECK(info); callbacks_wrapper->NotifySuccess(*info); } else {
diff --git a/components/password_manager/content/renderer/credential_manager_client_browsertest.cc b/components/password_manager/content/renderer/credential_manager_client_browsertest.cc index 85647cb..42ced0e7 100644 --- a/components/password_manager/content/renderer/credential_manager_client_browsertest.cc +++ b/components/password_manager/content/renderer/credential_manager_client_browsertest.cc
@@ -63,14 +63,13 @@ if (url == kTestCredentialPassword) { CredentialInfo info; info.type = CredentialType::CREDENTIAL_TYPE_PASSWORD; - std::move(callback).Run(mojom::CredentialManagerError::SUCCESS, info); + std::move(callback).Run(CredentialManagerError::SUCCESS, info); } else if (url == kTestCredentialEmpty) { - std::move(callback).Run(mojom::CredentialManagerError::SUCCESS, + std::move(callback).Run(CredentialManagerError::SUCCESS, CredentialInfo()); } else if (url == kTestCredentialReject) { - std::move(callback).Run( - mojom::CredentialManagerError::PASSWORDSTOREUNAVAILABLE, - base::nullopt); + std::move(callback).Run(CredentialManagerError::PASSWORDSTOREUNAVAILABLE, + base::nullopt); } }
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn index ddaef4e..e95b78ea 100644 --- a/components/password_manager/core/browser/BUILD.gn +++ b/components/password_manager/core/browser/BUILD.gn
@@ -35,6 +35,8 @@ "android_affiliation/test_affiliation_fetcher_factory.h", "browser_save_password_progress_logger.cc", "browser_save_password_progress_logger.h", + "credential_manager_impl.cc", + "credential_manager_impl.h", "credential_manager_logger.cc", "credential_manager_logger.h", "credential_manager_password_form_manager.cc",
diff --git a/components/password_manager/content/browser/credential_manager_impl.cc b/components/password_manager/core/browser/credential_manager_impl.cc similarity index 68% rename from components/password_manager/content/browser/credential_manager_impl.cc rename to components/password_manager/core/browser/credential_manager_impl.cc index e50d837..17b0ba65 100644 --- a/components/password_manager/content/browser/credential_manager_impl.cc +++ b/components/password_manager/core/browser/credential_manager_impl.cc
@@ -1,87 +1,40 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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 "components/password_manager/core/browser/credential_manager_impl.h" -#include "components/password_manager/content/browser/credential_manager_impl.h" - -#include <utility> - -#include "base/bind.h" -#include "base/memory/ptr_util.h" #include "base/metrics/user_metrics.h" -#include "base/strings/string16.h" -#include "base/strings/utf_string_conversions.h" -#include "components/autofill/core/common/password_form.h" -#include "components/password_manager/content/browser/content_password_manager_driver.h" -#include "components/password_manager/content/browser/content_password_manager_driver_factory.h" -#include "components/password_manager/core/browser/android_affiliation/affiliated_match_helper.h" #include "components/password_manager/core/browser/credential_manager_logger.h" #include "components/password_manager/core/browser/form_fetcher_impl.h" #include "components/password_manager/core/browser/form_saver.h" -#include "components/password_manager/core/browser/password_manager_client.h" -#include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/password_manager_util.h" -#include "components/password_manager/core/browser/password_store.h" #include "components/password_manager/core/common/password_manager_pref_names.h" -#include "content/public/browser/web_contents.h" namespace password_manager { namespace { -void RunMojoGetCallback(mojom::CredentialManager::GetCallback callback, - const CredentialInfo& info) { - std::move(callback).Run(mojom::CredentialManagerError::SUCCESS, info); +void RunGetCallback(GetCallback callback, const CredentialInfo& info) { + std::move(callback).Run(CredentialManagerError::SUCCESS, info); } } // namespace -// CredentialManagerImpl ------------------------------------------------- - -CredentialManagerImpl::CredentialManagerImpl(content::WebContents* web_contents, - PasswordManagerClient* client) - : WebContentsObserver(web_contents), - client_(client), - binding_(this), - weak_factory_(this) { - DCHECK(web_contents); +CredentialManagerImpl::CredentialManagerImpl(PasswordManagerClient* client) + : client_(client) { auto_signin_enabled_.Init(prefs::kCredentialsEnableAutosignin, client_->GetPrefs()); } CredentialManagerImpl::~CredentialManagerImpl() {} -void CredentialManagerImpl::BindRequest( - mojom::CredentialManagerAssociatedRequest request) { - DCHECK(!binding_.is_bound()); - binding_.Bind(std::move(request)); - - // The browser side will close the message pipe on DidFinishNavigation before - // the renderer side would be destroyed, and the renderer never explicitly - // closes the pipe. So a connection error really means an error here, in which - // case the renderer will try to reconnect when the next call to the API is - // made. Make sure this implementation will no longer be bound to a broken - // pipe once that happens, so the DCHECK above will succeed. - binding_.set_connection_error_handler(base::Bind( - &CredentialManagerImpl::DisconnectBinding, base::Unretained(this))); -} - -bool CredentialManagerImpl::HasBinding() const { - return binding_.is_bound(); -} - -void CredentialManagerImpl::DisconnectBinding() { - binding_.Close(); -} - void CredentialManagerImpl::Store(const CredentialInfo& credential, StoreCallback callback) { DCHECK_NE(CredentialType::CREDENTIAL_TYPE_EMPTY, credential.type); if (password_manager_util::IsLoggingActive(client_)) { CredentialManagerLogger(client_->GetLogManager()) - .LogStoreCredential(web_contents()->GetLastCommittedURL(), - credential.type); + .LogStoreCredential(GetLastCommittedURL(), credential.type); } // Send acknowledge response back. @@ -93,7 +46,7 @@ client_->NotifyStorePasswordCalled(); - GURL origin = web_contents()->GetLastCommittedURL().GetOrigin(); + GURL origin = GetLastCommittedURL().GetOrigin(); std::unique_ptr<autofill::PasswordForm> form( CreatePasswordFormFromCredentialInfo(credential, origin)); @@ -105,54 +58,16 @@ auto form_fetcher = base::MakeUnique<FormFetcherImpl>( PasswordStore::FormDigest(*observed_form), client_, false, false); form_manager_ = base::MakeUnique<CredentialManagerPasswordFormManager>( - client_, GetDriver(), *observed_form, std::move(form), this, nullptr, + client_, *observed_form, std::move(form), this, nullptr, std::move(form_fetcher)); form_manager_->Init(nullptr); } -void CredentialManagerImpl::OnProvisionalSaveComplete() { - DCHECK(form_manager_); - DCHECK(client_->IsSavingAndFillingEnabledForCurrentPage()); - const autofill::PasswordForm& form = form_manager_->pending_credentials(); - - if (form_manager_->IsPendingCredentialsPublicSuffixMatch()) { - // Having a credential with a PSL match implies there is no credential with - // an exactly matching origin and username. In order to avoid showing a save - // bubble to the user Save() is called directly. - form_manager_->Save(); - return; - } - - if (!form.federation_origin.unique()) { - // If this is a federated credential, check it against the federated matches - // produced by the PasswordFormManager. If a match is found, update it and - // return. - for (auto* match : form_manager_->form_fetcher()->GetFederatedMatches()) { - if (match->username_value == form.username_value && - match->federation_origin.IsSameOriginWith(form.federation_origin)) { - form_manager_->Update(*match); - return; - } - } - } else if (!form_manager_->IsNewLogin()) { - // Otherwise, if this is not a new password credential, update the existing - // credential without prompting the user. This will also update the - // 'skip_zero_click' state, as we've gotten an explicit signal that the page - // understands the credential management API and so can be trusted to notify - // us when they sign the user out. - form_manager_->Update(*form_manager_->preferred_match()); - return; - } - - // Otherwise, this is a new form, so as the user if they'd like to save. - client_->PromptUserToSaveOrUpdatePassword(std::move(form_manager_), false); -} - void CredentialManagerImpl::PreventSilentAccess( PreventSilentAccessCallback callback) { if (password_manager_util::IsLoggingActive(client_)) { CredentialManagerLogger(client_->GetLogManager()) - .LogPreventSilentAccess(web_contents()->GetLastCommittedURL()); + .LogPreventSilentAccess(GetLastCommittedURL()); } // Send acknowledge response back. std::move(callback).Run(); @@ -178,15 +93,13 @@ PasswordStore* store = GetPasswordStore(); if (password_manager_util::IsLoggingActive(client_)) { CredentialManagerLogger(client_->GetLogManager()) - .LogRequestCredential(web_contents()->GetLastCommittedURL(), mediation, - federations); + .LogRequestCredential(GetLastCommittedURL(), mediation, federations); } if (pending_request_ || !store) { // Callback error. std::move(callback).Run( - pending_request_ - ? mojom::CredentialManagerError::PENDINGREQUEST - : mojom::CredentialManagerError::PASSWORDSTOREUNAVAILABLE, + pending_request_ ? CredentialManagerError::PENDINGREQUEST + : CredentialManagerError::PASSWORDSTOREUNAVAILABLE, base::nullopt); LogCredentialManagerGetResult(metrics_util::CREDENTIAL_MANAGER_GET_REJECTED, mediation); @@ -197,8 +110,7 @@ // page is being prerendered. if (!client_->IsFillingEnabledForCurrentPage() || !client_->OnCredentialManagerUsed()) { - std::move(callback).Run(mojom::CredentialManagerError::SUCCESS, - CredentialInfo()); + std::move(callback).Run(CredentialManagerError::SUCCESS, CredentialInfo()); LogCredentialManagerGetResult(metrics_util::CREDENTIAL_MANAGER_GET_NONE, mediation); return; @@ -207,15 +119,14 @@ if (mediation == CredentialMediationRequirement::kSilent && !IsZeroClickAllowed()) { // Callback with empty credential info. - std::move(callback).Run(mojom::CredentialManagerError::SUCCESS, - CredentialInfo()); + std::move(callback).Run(CredentialManagerError::SUCCESS, CredentialInfo()); LogCredentialManagerGetResult( metrics_util::CREDENTIAL_MANAGER_GET_NONE_ZERO_CLICK_OFF, mediation); return; } pending_request_.reset(new CredentialManagerPendingRequestTask( - this, base::Bind(&RunMojoGetCallback, base::Passed(&callback)), mediation, + this, base::Bind(&RunGetCallback, base::Passed(&callback)), mediation, include_passwords, federations)); // This will result in a callback to // PendingRequestTask::OnGetPasswordStoreResults(). @@ -227,17 +138,17 @@ return *auto_signin_enabled_ && !client_->IsIncognito(); } -GURL CredentialManagerImpl::GetOrigin() const { - return web_contents()->GetLastCommittedURL().GetOrigin(); +PasswordStore::FormDigest CredentialManagerImpl::GetSynthesizedFormForOrigin() + const { + PasswordStore::FormDigest digest = {autofill::PasswordForm::SCHEME_HTML, + std::string(), + GetLastCommittedURL().GetOrigin()}; + digest.signon_realm = digest.origin.spec(); + return digest; } -base::WeakPtr<PasswordManagerDriver> CredentialManagerImpl::GetDriver() { - ContentPasswordManagerDriverFactory* driver_factory = - ContentPasswordManagerDriverFactory::FromWebContents(web_contents()); - DCHECK(driver_factory); - PasswordManagerDriver* driver = - driver_factory->GetDriverForFrame(web_contents()->GetMainFrame()); - return driver->AsWeakPtr(); +GURL CredentialManagerImpl::GetOrigin() const { + return GetLastCommittedURL().GetOrigin(); } void CredentialManagerImpl::SendCredential( @@ -248,7 +159,7 @@ if (password_manager_util::IsLoggingActive(client_)) { CredentialManagerLogger(client_->GetLogManager()) - .LogSendCredential(web_contents()->GetLastCommittedURL(), info.type); + .LogSendCredential(GetLastCommittedURL(), info.type); } send_callback.Run(info); pending_request_.reset(); @@ -298,13 +209,46 @@ pending_require_user_mediation_.reset(); } -PasswordStore::FormDigest CredentialManagerImpl::GetSynthesizedFormForOrigin() - const { - PasswordStore::FormDigest digest = { - autofill::PasswordForm::SCHEME_HTML, std::string(), - web_contents()->GetLastCommittedURL().GetOrigin()}; - digest.signon_realm = digest.origin.spec(); - return digest; +void CredentialManagerImpl::OnProvisionalSaveComplete() { + DCHECK(form_manager_); + DCHECK(client_->IsSavingAndFillingEnabledForCurrentPage()); + const autofill::PasswordForm& form = form_manager_->pending_credentials(); + + if (form_manager_->IsPendingCredentialsPublicSuffixMatch()) { + // Having a credential with a PSL match implies there is no credential with + // an exactly matching origin and username. In order to avoid showing a save + // bubble to the user Save() is called directly. + form_manager_->Save(); + return; + } + + if (!form.federation_origin.unique()) { + // If this is a federated credential, check it against the federated matches + // produced by the PasswordFormManager. If a match is found, update it and + // return. + for (auto* match : form_manager_->form_fetcher()->GetFederatedMatches()) { + if (match->username_value == form.username_value && + match->federation_origin.IsSameOriginWith(form.federation_origin)) { + form_manager_->Update(*match); + return; + } + } + } else if (!form_manager_->IsNewLogin()) { + // Otherwise, if this is not a new password credential, update the existing + // credential without prompting the user. This will also update the + // 'skip_zero_click' state, as we've gotten an explicit signal that the page + // understands the credential management API and so can be trusted to notify + // us when they sign the user out. + form_manager_->Update(*form_manager_->preferred_match()); + return; + } + + // Otherwise, this is a new form, so as the user if they'd like to save. + client_->PromptUserToSaveOrUpdatePassword(std::move(form_manager_), false); +} + +GURL CredentialManagerImpl::GetLastCommittedURL() const { + return client_->GetLastCommittedEntryURL(); } } // namespace password_manager
diff --git a/components/password_manager/core/browser/credential_manager_impl.h b/components/password_manager/core/browser/credential_manager_impl.h new file mode 100644 index 0000000..a71b2577 --- /dev/null +++ b/components/password_manager/core/browser/credential_manager_impl.h
@@ -0,0 +1,92 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_CREDENTIAL_MANAGER_IMPL_H_ +#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_CREDENTIAL_MANAGER_IMPL_H_ + +#include "components/password_manager/core/browser/credential_manager_password_form_manager.h" +#include "components/password_manager/core/browser/credential_manager_pending_prevent_silent_access_task.h" +#include "components/password_manager/core/browser/credential_manager_pending_request_task.h" +#include "components/password_manager/core/common/credential_manager_types.h" +#include "components/prefs/pref_member.h" + +namespace password_manager { + +using StoreCallback = base::OnceCallback<void()>; +using PreventSilentAccessCallback = base::OnceCallback<void()>; +using GetCallback = + base::OnceCallback<void(CredentialManagerError, + const base::Optional<CredentialInfo>&)>; + +// Class implementing Credential Manager methods Store, PreventSilentAccess +// and Get in a platform independent way. Each method takes a callback as an +// argument and runs the callback with the result. Platform specific code +// and UI invocations are performed by PasswordManagerClient taken in +// constructor. +class CredentialManagerImpl + : public CredentialManagerPendingPreventSilentAccessTaskDelegate, + public CredentialManagerPendingRequestTaskDelegate, + public CredentialManagerPasswordFormManagerDelegate { + public: + explicit CredentialManagerImpl(PasswordManagerClient* client); + ~CredentialManagerImpl() override; + + void Store(const CredentialInfo& credential, StoreCallback callback); + void PreventSilentAccess(PreventSilentAccessCallback callback); + void Get(CredentialMediationRequirement mediation, + bool include_passwords, + const std::vector<GURL>& federations, + GetCallback callback); + + // TODO(tgarbus): Move IsZeroClickAllowed to private once + // IsZeroClickAllowed is removed from ContentCredentialManager. + // CredentialManagerPendingRequestTaskDelegate: + bool IsZeroClickAllowed() const override; + + // TODO(tgarbus): Move GetSynthesizedFormForOrigin to private once + // GetSynthesizedFormForOrigin is removed from ContentCredentialManager. + // Returns FormDigest for the current URL. + PasswordStore::FormDigest GetSynthesizedFormForOrigin() const; + + private: + // CredentialManagerPendingRequestTaskDelegate: + GURL GetOrigin() const override; + void SendCredential(const SendCredentialCallback& send_callback, + const CredentialInfo& info) override; + void SendPasswordForm(const SendCredentialCallback& send_callback, + CredentialMediationRequirement mediation, + const autofill::PasswordForm* form) override; + PasswordManagerClient* client() const override; + + // CredentialManagerPendingPreventSilentAccessTaskDelegate: + PasswordStore* GetPasswordStore() override; + void DoneRequiringUserMediation() override; + + // CredentialManagerPasswordFormManagerDelegate: + void OnProvisionalSaveComplete() override; + + GURL GetLastCommittedURL() const; + + PasswordManagerClient* client_; + + // Set to false to disable automatic signing in. + BooleanPrefMember auto_signin_enabled_; + + // Used to store or update a credential. Calls OnProvisionalSaveComplete + // on this delegate. + std::unique_ptr<CredentialManagerPasswordFormManager> form_manager_; + // Retrieves credentials from the PasswordStore and calls + // SendCredential on this delegate. SendCredential then runs a callback + // which was passed as an argument to Get(). + std::unique_ptr<CredentialManagerPendingRequestTask> pending_request_; + // Notifies the PasswordStore that the origin requires user mediation. + // Calls DoneRequiringUserMediation on this delegate. + std::unique_ptr<CredentialManagerPendingPreventSilentAccessTask> + pending_require_user_mediation_; + + DISALLOW_COPY_AND_ASSIGN(CredentialManagerImpl); +}; + +} // namespace password_manager + +#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_CREDENTIAL_MANAGER_IMPL_H_
diff --git a/components/password_manager/core/browser/credential_manager_password_form_manager.cc b/components/password_manager/core/browser/credential_manager_password_form_manager.cc index ee3dd044..6ba306b2 100644 --- a/components/password_manager/core/browser/credential_manager_password_form_manager.cc +++ b/components/password_manager/core/browser/credential_manager_password_form_manager.cc
@@ -21,15 +21,14 @@ CredentialManagerPasswordFormManager::CredentialManagerPasswordFormManager( PasswordManagerClient* client, - base::WeakPtr<PasswordManagerDriver> driver, const PasswordForm& observed_form, std::unique_ptr<autofill::PasswordForm> saved_form, CredentialManagerPasswordFormManagerDelegate* delegate, std::unique_ptr<FormSaver> form_saver, std::unique_ptr<FormFetcher> form_fetcher) - : PasswordFormManager(driver->GetPasswordManager(), + : PasswordFormManager(client->GetPasswordManager(), client, - driver, + nullptr, observed_form, (form_saver ? std::move(form_saver) : base::MakeUnique<FormSaverImpl>(
diff --git a/components/password_manager/core/browser/credential_manager_password_form_manager.h b/components/password_manager/core/browser/credential_manager_password_form_manager.h index 6f052bb..052e3a1b 100644 --- a/components/password_manager/core/browser/credential_manager_password_form_manager.h +++ b/components/password_manager/core/browser/credential_manager_password_form_manager.h
@@ -16,7 +16,6 @@ namespace password_manager { class PasswordManagerClient; -class PasswordManagerDriver; // A delegate that is notified when CredentialManagerPasswordFormManager // finishes working with password forms. @@ -40,7 +39,6 @@ // This class does not take ownership of |delegate|. CredentialManagerPasswordFormManager( PasswordManagerClient* client, - base::WeakPtr<PasswordManagerDriver> driver, const autofill::PasswordForm& observed_form, std::unique_ptr<autofill::PasswordForm> saved_form, CredentialManagerPasswordFormManagerDelegate* delegate,
diff --git a/components/password_manager/core/browser/credential_manager_password_form_manager_unittest.cc b/components/password_manager/core/browser/credential_manager_password_form_manager_unittest.cc index 585d88e0..0dbde46 100644 --- a/components/password_manager/core/browser/credential_manager_password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/credential_manager_password_form_manager_unittest.cc
@@ -14,7 +14,6 @@ #include "components/password_manager/core/browser/fake_form_fetcher.h" #include "components/password_manager/core/browser/stub_form_saver.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" -#include "components/password_manager/core/browser/stub_password_manager_driver.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -41,7 +40,6 @@ base::MessageLoop message_loop_; StubPasswordManagerClient client_; - StubPasswordManagerDriver driver_; DISALLOW_COPY_AND_ASSIGN(CredentialManagerPasswordFormManagerTest); }; @@ -51,9 +49,9 @@ PasswordForm observed_form; MockDelegate delegate; auto form_manager = base::MakeUnique<CredentialManagerPasswordFormManager>( - &client_, driver_.AsWeakPtr(), observed_form, - base::MakeUnique<PasswordForm>(observed_form), &delegate, - base::MakeUnique<StubFormSaver>(), base::MakeUnique<FakeFormFetcher>()); + &client_, observed_form, base::MakeUnique<PasswordForm>(observed_form), + &delegate, base::MakeUnique<StubFormSaver>(), + base::MakeUnique<FakeFormFetcher>()); form_manager->Init(nullptr); auto deleter = [&form_manager]() { form_manager.reset(); }; @@ -81,9 +79,9 @@ PasswordForm observed_form; MockDelegate delegate; auto form_manager = base::MakeUnique<CredentialManagerPasswordFormManager>( - &client_, driver_.AsWeakPtr(), observed_form, - base::MakeUnique<PasswordForm>(observed_form), &delegate, - base::MakeUnique<StubFormSaver>(), base::MakeUnique<FakeFormFetcher>()); + &client_, observed_form, base::MakeUnique<PasswordForm>(observed_form), + &delegate, base::MakeUnique<StubFormSaver>(), + base::MakeUnique<FakeFormFetcher>()); form_manager->Init(nullptr); ASSERT_EQ(metrics_util::CredentialSourceType::kCredentialManagementAPI, form_manager->GetCredentialSource());
diff --git a/components/password_manager/core/browser/password_autofill_manager.cc b/components/password_manager/core/browser/password_autofill_manager.cc index c4ae747..8008cf3 100644 --- a/components/password_manager/core/browser/password_autofill_manager.cc +++ b/components/password_manager/core/browser/password_autofill_manager.cc
@@ -263,16 +263,14 @@ if (base::FeatureList::IsEnabled( password_manager::features::kEnableManualFallbacksFilling) && (options & autofill::IS_PASSWORD_FIELD)) { - std::string all_saved_passwords_icon; #if !defined(OS_ANDROID) suggestions.push_back(autofill::Suggestion()); suggestions.back().frontend_id = autofill::POPUP_ITEM_ID_SEPARATOR; - all_saved_passwords_icon = "showAllSavedPasswords"; #endif autofill::Suggestion all_saved_passwords( l10n_util::GetStringUTF8(IDS_AUTOFILL_SHOW_ALL_SAVED_FALLBACK), - std::string(), all_saved_passwords_icon, + std::string(), std::string(), autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY); suggestions.push_back(all_saved_passwords); } @@ -311,7 +309,7 @@ std::vector<autofill::Suggestion> suggestions; autofill::Suggestion all_saved_passwords( l10n_util::GetStringUTF8(IDS_AUTOFILL_SHOW_ALL_SAVED_FALLBACK), - std::string(), "showAllSavedPasswords", + std::string(), std::string(), autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY); suggestions.push_back(all_saved_passwords); autofill_client_->ShowAutofillPopup(bounds, text_direction, suggestions,
diff --git a/components/password_manager/core/common/credential_manager_types.h b/components/password_manager/core/common/credential_manager_types.h index b9fffab..876b447 100644 --- a/components/password_manager/core/common/credential_manager_types.h +++ b/components/password_manager/core/common/credential_manager_types.h
@@ -33,6 +33,14 @@ CREDENTIAL_TYPE_LAST = CREDENTIAL_TYPE_FEDERATED }; +enum class CredentialManagerError { + SUCCESS, + DISABLED, + PENDINGREQUEST, + PASSWORDSTOREUNAVAILABLE, + UNKNOWN, +}; + enum class CredentialMediationRequirement { kSilent, kOptional, kRequired }; std::string CredentialTypeToString(CredentialType value);
diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc index 20f8b100..a18ff897 100644 --- a/components/password_manager/core/common/password_manager_features.cc +++ b/components/password_manager/core/common/password_manager_features.cc
@@ -54,13 +54,7 @@ // mobile, the desktop version of Chrome always allows users to view // passwords. const base::Feature kViewPasswords = {"view-passwords", -// TODO(crbug.com/739404): Remove this ifdef once the feature spends a couple -// of releases in stable on iOS or once it also gets enabled on Android. -#if defined(OS_IOS) base::FEATURE_ENABLED_BY_DEFAULT}; -#else - base::FEATURE_DISABLED_BY_DEFAULT}; -#endif // Enables the experiment for the password manager to only fill on account // selection, rather than autofilling on page load, with highlighting of fields.
diff --git a/components/proximity_auth/proximity_auth_local_state_pref_manager.cc b/components/proximity_auth/proximity_auth_local_state_pref_manager.cc index 6998ede..afa5bef 100644 --- a/components/proximity_auth/proximity_auth_local_state_pref_manager.cc +++ b/components/proximity_auth/proximity_auth_local_state_pref_manager.cc
@@ -31,6 +31,11 @@ registry->RegisterDictionaryPref(prefs::kEasyUnlockLocalStateUserPrefs); } +void ProximityAuthLocalStatePrefManager::SetIsEasyUnlockEnabled( + bool is_easy_unlock_enabled) const { + NOTREACHED(); +} + void ProximityAuthLocalStatePrefManager::SetActiveUser( const AccountId& active_user) { active_user_ = active_user; @@ -83,6 +88,17 @@ return pref_value; } +bool ProximityAuthLocalStatePrefManager::IsEasyUnlockEnabled() const { + bool pref_value; + const base::DictionaryValue* user_prefs = GetActiveUserPrefsDictionary(); + if (!user_prefs || !user_prefs->GetBooleanWithoutPathExpansion( + prefs::kEasyUnlockEnabled, &pref_value)) { + PA_LOG(ERROR) << "Failed to get easyunlock_enabled."; + return false; + } + return pref_value; +} + ProximityAuthLocalStatePrefManager::ProximityThreshold ProximityAuthLocalStatePrefManager::GetProximityThreshold() const { int pref_value;
diff --git a/components/proximity_auth/proximity_auth_local_state_pref_manager.h b/components/proximity_auth/proximity_auth_local_state_pref_manager.h index 5cb02e7..16fe843 100644 --- a/components/proximity_auth/proximity_auth_local_state_pref_manager.h +++ b/components/proximity_auth/proximity_auth_local_state_pref_manager.h
@@ -43,11 +43,13 @@ // ProximityAuthPrefManager: bool IsEasyUnlockAllowed() const override; + bool IsEasyUnlockEnabled() const override; ProximityThreshold GetProximityThreshold() const override; bool IsChromeOSLoginEnabled() override; private: // ProximityAuthPrefManager: + void SetIsEasyUnlockEnabled(bool is_easy_unlock_enabled) const override; void SetLastPasswordEntryTimestampMs(int64_t timestamp_ms) override; int64_t GetLastPasswordEntryTimestampMs() const override; void SetLastPromotionCheckTimestampMs(int64_t timestamp_ms) override;
diff --git a/components/proximity_auth/proximity_auth_local_state_pref_manager_unittest.cc b/components/proximity_auth/proximity_auth_local_state_pref_manager_unittest.cc index 52ead7bf..c879e092 100644 --- a/components/proximity_auth/proximity_auth_local_state_pref_manager_unittest.cc +++ b/components/proximity_auth/proximity_auth_local_state_pref_manager_unittest.cc
@@ -24,18 +24,21 @@ ProximityAuthPrefManager::ProximityThreshold::kVeryFar; const bool kIsChromeOSLoginEnabled1 = true; const bool kIsEasyUnlockAllowed1 = true; +const bool kIsEasyUnlockEnabled1 = true; const char kUser2[] = "tengs@google.com"; const ProximityAuthPrefManager::ProximityThreshold kProximityThreshold2 = ProximityAuthPrefManager::ProximityThreshold::kVeryClose; const bool kIsChromeOSLoginEnabled2 = false; const bool kIsEasyUnlockAllowed2 = false; +const bool kIsEasyUnlockEnabled2 = false; const char kUnknownUser[] = "tengs@chromium.org"; const ProximityAuthPrefManager::ProximityThreshold kProximityThresholdDefault = ProximityAuthPrefManager::ProximityThreshold::kClose; const bool kIsChromeOSLoginEnabledDefault = false; const bool kIsEasyUnlockAllowedDefault = true; +const bool kIsEasyUnlockEnabledDefault = false; } // namespace @@ -62,6 +65,8 @@ base::Value(kIsChromeOSLoginEnabled1)); user1_prefs->SetKey(proximity_auth::prefs::kEasyUnlockAllowed, base::Value(kIsEasyUnlockAllowed1)); + user1_prefs->SetKey(proximity_auth::prefs::kEasyUnlockEnabled, + base::Value(kIsEasyUnlockEnabled1)); DictionaryPrefUpdate update1(&local_state_, prefs::kEasyUnlockLocalStateUserPrefs); update1->SetWithoutPathExpansion(user1_.GetUserEmail(), @@ -76,6 +81,8 @@ base::Value(kIsChromeOSLoginEnabled2)); user2_prefs->SetKey(proximity_auth::prefs::kEasyUnlockAllowed, base::Value(kIsEasyUnlockAllowed2)); + user2_prefs->SetKey(proximity_auth::prefs::kEasyUnlockEnabled, + base::Value(kIsEasyUnlockEnabled2)); DictionaryPrefUpdate update2(&local_state_, prefs::kEasyUnlockLocalStateUserPrefs); @@ -114,6 +121,23 @@ EXPECT_EQ(kIsEasyUnlockAllowed2, pref_manager.IsEasyUnlockAllowed()); } +TEST_F(ProximityAuthLocalStatePrefManagerTest, IsEasyUnlockEnabled) { + ProximityAuthLocalStatePrefManager pref_manager(&local_state_); + + // If no active user is set, return the default value. + EXPECT_EQ(kIsEasyUnlockEnabledDefault, pref_manager.IsEasyUnlockEnabled()); + + // Unknown users should return the default value. + pref_manager.SetActiveUser(unknown_user_); + EXPECT_EQ(kIsEasyUnlockEnabledDefault, pref_manager.IsEasyUnlockEnabled()); + + // Test users with set values. + pref_manager.SetActiveUser(user1_); + EXPECT_EQ(kIsEasyUnlockEnabled1, pref_manager.IsEasyUnlockEnabled()); + pref_manager.SetActiveUser(user2_); + EXPECT_EQ(kIsEasyUnlockEnabled2, pref_manager.IsEasyUnlockEnabled()); +} + TEST_F(ProximityAuthLocalStatePrefManagerTest, GetProximityThreshold) { ProximityAuthLocalStatePrefManager pref_manager(&local_state_);
diff --git a/components/proximity_auth/proximity_auth_pref_manager.h b/components/proximity_auth/proximity_auth_pref_manager.h index a8e196ad..c5e42cc 100644 --- a/components/proximity_auth/proximity_auth_pref_manager.h +++ b/components/proximity_auth/proximity_auth_pref_manager.h
@@ -21,9 +21,17 @@ virtual ~ProximityAuthPrefManager() {} // Returns true if EasyUnlock is allowed. Note: there is no corresponding - // setter because this pref is pushed through an enterprise policy. + // setter because this pref is pushed through an enterprise policy. Note that + // this pref completely disables EasyUnlock, hiding even the UI. See + // IsEasyUnlockEnabled() for comparison. virtual bool IsEasyUnlockAllowed() const = 0; + // Returns true if EasyUnlock is enabled, i.e. the user has gone through the + // setup flow and has at least one phone as an unlock key. Compare to + // IsEasyUnlockAllowed(), which completely removes the feature from existence. + virtual void SetIsEasyUnlockEnabled(bool is_easy_unlock_enabled) const = 0; + virtual bool IsEasyUnlockEnabled() const = 0; + // Setter and getter for the timestamp of the last password entry. This // preference is used to enforce reauthing with the password after a given // time period has elapsed.
diff --git a/components/proximity_auth/proximity_auth_pref_names.cc b/components/proximity_auth/proximity_auth_pref_names.cc index 36d1b9d..d18fc37 100644 --- a/components/proximity_auth/proximity_auth_pref_names.cc +++ b/components/proximity_auth/proximity_auth_pref_names.cc
@@ -11,6 +11,10 @@ // through an enterprise policy. const char kEasyUnlockAllowed[] = "easy_unlock.allowed"; +// Whether or not EasyUnlock has been enabled by the user (i.e. they went +// through the setup flow and there is at least one unlock key). +const char kEasyUnlockEnabled[] = "easy_unlock.enabled"; + // How close the remote and the local device should be in order to use Easy // Unlock. const char kEasyUnlockProximityThreshold[] = "easy_unlock.proximity_threshold";
diff --git a/components/proximity_auth/proximity_auth_pref_names.h b/components/proximity_auth/proximity_auth_pref_names.h index 5b9e3d4..d4852e1 100644 --- a/components/proximity_auth/proximity_auth_pref_names.h +++ b/components/proximity_auth/proximity_auth_pref_names.h
@@ -9,6 +9,7 @@ namespace prefs { extern const char kEasyUnlockAllowed[]; +extern const char kEasyUnlockEnabled[]; extern const char kEasyUnlockProximityThreshold[]; extern const char kEasyUnlockLocalStateUserPrefs[]; extern const char kProximityAuthLastPasswordEntryTimestampMs[];
diff --git a/components/proximity_auth/proximity_auth_profile_pref_manager.cc b/components/proximity_auth/proximity_auth_profile_pref_manager.cc index b2a139b..1e99abed 100644 --- a/components/proximity_auth/proximity_auth_profile_pref_manager.cc +++ b/components/proximity_auth/proximity_auth_profile_pref_manager.cc
@@ -30,6 +30,7 @@ void ProximityAuthProfilePrefManager::RegisterPrefs( user_prefs::PrefRegistrySyncable* registry) { registry->RegisterBooleanPref(prefs::kEasyUnlockAllowed, true); + registry->RegisterBooleanPref(prefs::kEasyUnlockEnabled, false); registry->RegisterInt64Pref(prefs::kProximityAuthLastPasswordEntryTimestampMs, 0L); registry->RegisterInt64Pref( @@ -67,6 +68,7 @@ registrar_.Init(pref_service_); registrar_.Add(prefs::kEasyUnlockAllowed, on_pref_changed_callback); + registrar_.Add(prefs::kEasyUnlockEnabled, on_pref_changed_callback); registrar_.Add(proximity_auth::prefs::kEasyUnlockProximityThreshold, on_pref_changed_callback); registrar_.Add(proximity_auth::prefs::kProximityAuthIsChromeOSLoginEnabled, @@ -81,6 +83,8 @@ user_prefs_dict->SetKey(prefs::kEasyUnlockAllowed, base::Value(IsEasyUnlockAllowed())); + user_prefs_dict->SetKey(prefs::kEasyUnlockEnabled, + base::Value(IsEasyUnlockEnabled())); user_prefs_dict->SetKey(prefs::kEasyUnlockProximityThreshold, base::Value(GetProximityThreshold())); user_prefs_dict->SetKey(prefs::kProximityAuthIsChromeOSLoginEnabled, @@ -96,6 +100,15 @@ return pref_service_->GetBoolean(prefs::kEasyUnlockAllowed); } +void ProximityAuthProfilePrefManager::SetIsEasyUnlockEnabled( + bool is_easy_unlock_enabled) const { + pref_service_->SetBoolean(prefs::kEasyUnlockEnabled, is_easy_unlock_enabled); +} + +bool ProximityAuthProfilePrefManager::IsEasyUnlockEnabled() const { + return pref_service_->GetBoolean(prefs::kEasyUnlockEnabled); +} + void ProximityAuthProfilePrefManager::SetLastPasswordEntryTimestampMs( int64_t timestamp_ms) { pref_service_->SetInt64(prefs::kProximityAuthLastPasswordEntryTimestampMs,
diff --git a/components/proximity_auth/proximity_auth_profile_pref_manager.h b/components/proximity_auth/proximity_auth_profile_pref_manager.h index 3377649e..6b3538f6 100644 --- a/components/proximity_auth/proximity_auth_profile_pref_manager.h +++ b/components/proximity_auth/proximity_auth_profile_pref_manager.h
@@ -48,6 +48,8 @@ // ProximityAuthPrefManager: bool IsEasyUnlockAllowed() const override; + void SetIsEasyUnlockEnabled(bool is_easy_unlock_enabled) const override; + bool IsEasyUnlockEnabled() const override; void SetLastPasswordEntryTimestampMs(int64_t timestamp_ms) override; int64_t GetLastPasswordEntryTimestampMs() const override; void SetLastPromotionCheckTimestampMs(int64_t timestamp_ms) override;
diff --git a/components/proximity_auth/proximity_auth_profile_pref_manager_unittest.cc b/components/proximity_auth/proximity_auth_profile_pref_manager_unittest.cc index 8198a00..e23f325 100644 --- a/components/proximity_auth/proximity_auth_profile_pref_manager_unittest.cc +++ b/components/proximity_auth/proximity_auth_profile_pref_manager_unittest.cc
@@ -58,6 +58,17 @@ EXPECT_FALSE(pref_manager.IsEasyUnlockAllowed()); } +TEST_F(ProximityAuthProfilePrefManagerTest, IsEasyUnlockEnabled) { + ProximityAuthProfilePrefManager pref_manager(&pref_service_); + EXPECT_FALSE(pref_manager.IsEasyUnlockEnabled()); + + pref_manager.SetIsEasyUnlockEnabled(true); + EXPECT_TRUE(pref_manager.IsEasyUnlockEnabled()); + + pref_manager.SetIsEasyUnlockEnabled(false); + EXPECT_FALSE(pref_manager.IsEasyUnlockEnabled()); +} + TEST_F(ProximityAuthProfilePrefManagerTest, LastPasswordEntryTimestamp) { ProximityAuthProfilePrefManager pref_manager(&pref_service_); EXPECT_EQ(0L, pref_manager.GetLastPasswordEntryTimestampMs()); @@ -122,13 +133,17 @@ local_pref_manager.SetActiveUser(account_id); profile_pref_manager.SetIsChromeOSLoginEnabled(true); + profile_pref_manager.SetIsEasyUnlockEnabled(true); profile_pref_manager.SetProximityThreshold(kProximityThreshold1); EXPECT_TRUE(local_pref_manager.IsChromeOSLoginEnabled()); + EXPECT_TRUE(local_pref_manager.IsEasyUnlockEnabled()); EXPECT_EQ(kProximityThreshold1, local_pref_manager.GetProximityThreshold()); profile_pref_manager.SetIsChromeOSLoginEnabled(false); + profile_pref_manager.SetIsEasyUnlockEnabled(false); profile_pref_manager.SetProximityThreshold(kProximityThreshold2); EXPECT_FALSE(local_pref_manager.IsChromeOSLoginEnabled()); + EXPECT_FALSE(local_pref_manager.IsEasyUnlockEnabled()); EXPECT_EQ(kProximityThreshold2, local_pref_manager.GetProximityThreshold()); // Test changing the kEasyUnlockAllowed pref value directly (e.g. through
diff --git a/components/renderer_context_menu/context_menu_content_type.cc b/components/renderer_context_menu/context_menu_content_type.cc index d62e040..95dae07 100644 --- a/components/renderer_context_menu/context_menu_content_type.cc +++ b/components/renderer_context_menu/context_menu_content_type.cc
@@ -77,6 +77,8 @@ bool ContextMenuContentType::SupportsGroupInternal(int group) { const bool has_link = !params_.unfiltered_link_url.is_empty(); const bool has_selection = !params_.selection_text.empty(); + const bool is_password = + params_.input_field_type == WebContextMenuData::kInputFieldTypePassword; switch (group) { case ITEM_GROUP_CUSTOM: @@ -136,7 +138,7 @@ return !params_.is_editable && has_selection; case ITEM_GROUP_SEARCH_PROVIDER: - return has_selection; + return has_selection && !is_password; case ITEM_GROUP_PRINT: { // Image menu items also imply print items.
diff --git a/components/safe_browsing/base_resource_throttle.cc b/components/safe_browsing/base_resource_throttle.cc index 8de2554..cac7fac6 100644 --- a/components/safe_browsing/base_resource_throttle.cc +++ b/components/safe_browsing/base_resource_throttle.cc
@@ -284,31 +284,6 @@ StartDisplayingBlockingPageHelper(resource); } -void BaseResourceThrottle::StartDisplayingBlockingPageHelper( - security_interstitials::UnsafeResource resource) { - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&BaseResourceThrottle::StartDisplayingBlockingPage, - AsWeakPtr(), ui_manager_, resource)); -} - -// Static -void BaseResourceThrottle::StartDisplayingBlockingPage( - const base::WeakPtr<BaseResourceThrottle>& throttle, - scoped_refptr<BaseUIManager> ui_manager, - const security_interstitials::UnsafeResource& resource) { - content::WebContents* web_contents = resource.web_contents_getter.Run(); - if (web_contents) { - ui_manager->DisplayBlockingPage(resource); - return; - } - - // Tab is gone or it's being prerendered. - content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, - base::Bind(&BaseResourceThrottle::Cancel, throttle)); -} - void BaseResourceThrottle::OnBlockingPageComplete(bool proceed) { CHECK_EQ(state_, STATE_DISPLAYING_BLOCKING_PAGE); state_ = STATE_NONE;
diff --git a/components/safe_browsing/base_resource_throttle.h b/components/safe_browsing/base_resource_throttle.h index 38de36f5..00b27dc 100644 --- a/components/safe_browsing/base_resource_throttle.h +++ b/components/safe_browsing/base_resource_throttle.h
@@ -93,20 +93,13 @@ // Posts a task for StartDisplayingBlockingPage virtual void StartDisplayingBlockingPageHelper( - security_interstitials::UnsafeResource resource); + security_interstitials::UnsafeResource resource) = 0; // Called by OnBlockingPageComplete when proceed == false. This removes the // blocking page. This calls ResourceThrottle::Cancel() to show the previous // page, but may be overridden in a subclass. virtual void CancelResourceLoad(); - // Starts displaying the safe browsing interstitial page. Called on the UI - // thread. - static void StartDisplayingBlockingPage( - const base::WeakPtr<BaseResourceThrottle>& throttle, - scoped_refptr<BaseUIManager> ui_manager, - const security_interstitials::UnsafeResource& resource); - // Starts running |url| through the safe browsing check. Returns true if the // URL is safe to visit. Otherwise returns false and will call // OnBrowseUrlResult() when the check has completed.
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc index 53de2638..99f3be3 100644 --- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc +++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
@@ -1002,8 +1002,9 @@ tester().ExpectTotalCount(kSafeBrowsingCheckTime, 2); } +// Disabled due to flaky failures: https://crbug.com/753669. TEST_P(SubresourceFilterSafeBrowsingActivationThrottleParamTest, - ListMatchedOnStartWithRedirect_NoActivation) { + DISABLED_ListMatchedOnStartWithRedirect_NoActivation) { const GURL url(kURL); const GURL redirect_url(kRedirectURL); ConfigureForMatchParam(url);
diff --git a/components/ui_devtools/BUILD.gn b/components/ui_devtools/BUILD.gn index bb1d83b..d7d038ea 100644 --- a/components/ui_devtools/BUILD.gn +++ b/components/ui_devtools/BUILD.gn
@@ -11,6 +11,8 @@ "DOM.cpp", "DOM.h", "Forward.h", + "Overlay.cpp", + "Overlay.h", "Protocol.cpp", "Protocol.h", ]
diff --git a/components/ui_devtools/protocol.json b/components/ui_devtools/protocol.json index e69dd13..db337d1 100644 --- a/components/ui_devtools/protocol.json +++ b/components/ui_devtools/protocol.json
@@ -23,29 +23,52 @@ }, { "name": "highlightNode", - "parameters": [ - { - "name": "highlightConfig", - "$ref": "HighlightConfig", - "description": "A descriptor for the highlight appearance." - }, - { - "description": "Identifier of the node to highlight.", - "optional": true, - "name": "nodeId", - "$ref": "NodeId" - } - ], - "description": "Highlights DOM node with given id or with the given JavaScript object wrapper. Either nodeId or objectId must be specified." + "description": "Highlights DOM node.", + "redirect": "Overlay" }, { "name": "hideHighlight", "description": "Hides DOM node highlight." + }, + { + "name": "pushNodesByBackendIdsToFrontend", + "parameters": [ + { + "name": "backendNodeIds", + "type": "array", + "items": { + "$ref": "BackendNodeId" + }, + "description": "The array of backend node ids." + } + ], + "returns": [ + { + "name": "nodeIds", + "type": "array", + "items": { + "$ref": "NodeId" + }, + "description": "The array of ids of pushed nodes that correspond to the backend ids specified in backendNodeIds." + } + ], + "description": "Requests that a batch of nodes is sent to the caller given their backend node ids.", + "experimental": true } - ], "events": [ { + "name": "nodeHighlightRequested", + "parameters": [ + { + "name": "nodeId", + "$ref": "NodeId", + "description": "Identifier of the node to highlight in DOM tree." + } + ], + "description": "In DOM tree, highlights DOM node with given id." + }, + { "name": "childNodeInserted", "parameters": [ { @@ -54,7 +77,6 @@ "$ref": "NodeId" }, { - "description": "Id of the previous sibling (0 if this is at the beginning of the list).", "name": "previousNodeId", "$ref": "NodeId" @@ -92,6 +114,11 @@ "type": "integer" }, { + "id": "BackendNodeId", + "type": "integer", + "description": "Unique DOM node identifier used to reference a node that may not have been pushed to the front-end." + }, + { "description": "DOM interaction is implemented in terms of mirror objects that represent the actual DOM nodes. DOMNode is a base node mirror type.", "id": "Node", "properties": [ @@ -101,6 +128,11 @@ "name": "nodeId" }, { + "name": "backendNodeId", + "$ref": "BackendNodeId", + "description": "The BackendNodeId for this node." + }, + { "description": "<code>Node</code>'s nodeType.", "name": "nodeType", "type": "integer" @@ -153,49 +185,113 @@ "id": "RGBA", "type": "object", "properties": [ - { + { "name": "r", "type": "integer", "description": "The red component, in the [0-255] range." }, - { - "name": "g", - "type": "integer", - "description": "The green component, in the [0-255] range." + { + "name": "g", + "type": "integer", + "description": "The green component, in the [0-255] range." }, { - "name": "b", - "type": "integer", - "description": "The blue component, in the [0-255] range." + "name": "b", + "type": "integer", + "description": "The blue component, in the [0-255] range." }, - { - "name": "a", - "type": "number", - "optional": true, - "description": "The alpha component, in the [0-1] range (default: 1)." + { + "name": "a", + "type": "number", + "optional": true, + "description": "The alpha component, in the [0-1] range (default: 1)." } ], "description": "A structure holding an RGBA color." }, { + "id": "Mode", + "type": "string", + "description": "Enable or Disable the highlighting inspector." + }, + { "id": "HighlightConfig", "type": "object", "properties": [ - { - "name": "contentColor", - "$ref": "RGBA", - "optional": true, - "description": "The content box highlight fill color (default: transparent)." + { + "name": "showInfo", + "type": "boolean", + "optional": true, + "description": "Whether the node info tooltip should be shown (default: false)." }, - { - "name": "borderColor", - "$ref": "RGBA", - "optional": true, - "description": "The border highlight fill color (default: transparent)." + { + "name": "showRulers", + "type": "boolean", + "optional": true, + "description": "Whether the rulers should be shown (default: false)." + }, + { + "name": "showExtensionLines", + "type": "boolean", + "optional": true, + "description": "Whether the extension lines from node to the rulers should be shown (default: false)." + }, + { + "name": "displayAsMaterial", + "type": "boolean", + "optional": true + }, + { + "name": "contentColor", + "$ref": "DOM.RGBA", + "optional": true, + "description": "The content box highlight fill color (default: transparent)." + }, + { + "name": "paddingColor", + "$ref": "DOM.RGBA", + "optional": true, + "description": "The padding highlight fill color (default: transparent)." + }, + { + "name": "borderColor", + "$ref": "DOM.RGBA", + "optional": true, + "description": "The border highlight fill color (default: transparent)." + }, + { + "name": "marginColor", + "$ref": "DOM.RGBA", + "optional": true, + "description": "The margin highlight fill color (default: transparent)." + }, + { + "name": "eventTargetColor", + "$ref": "DOM.RGBA", + "optional": true, + "description": "The event target element highlight fill color (default: transparent)." + }, + { + "name": "shapeColor", + "$ref": "DOM.RGBA", + "optional": true, + "description": "The shape outside fill color (default: transparent)." + }, + { + "name": "shapeMarginColor", + "$ref": "DOM.RGBA", + "optional": true, + "description": "The shape margin fill color (default: transparent)." + }, + { + "name": "selectorList", + "type": "string", + "optional": true, + "description": "Selectors to highlight relevant nodes." } ], "description": "Configuration data for the highlighting of page elements." - } + } ] }, { @@ -224,7 +320,6 @@ "name": "inlineStyle", "optional": true } - ] }, { @@ -326,11 +421,11 @@ "name": "value", "type": "string" }, - { - "name": "range", - "$ref": "SourceRange", - "optional": true, - "description": "The entire property range in the enclosing style declaration (if available)." + { + "name": "range", + "$ref": "SourceRange", + "optional": true, + "description": "The entire property range in the enclosing style declaration (if available)." } ], "type": "object" @@ -371,6 +466,174 @@ "type": "object" } ] + }, + { + "commands": [ + { + "description": "Enables Overlay agent for the given page.", + "name": "enable" + }, + { + "description": "Disables Overlay agent for the given page.", + "name": "disable" + }, + { + "name": "highlightNode", + "description": "Highlights DOM node with given id.", + "parameters": [ + { + "name": "highlightConfig", + "$ref": "HighlightConfig", + "description": "A descriptor for the highlight appearance." + }, + { + "name": "nodeId", + "$ref": "DOM.NodeId", + "optional":true, + "description": "Identifier of the node to highlight." + } + ] + }, + { + "name": "hideHighlight", + "description": "Hides DOM node highlight." + }, + { + "name": "setInspectMode", + "parameters": [ + { + "description": "Set an inspection mode.", + "name": "mode", + "$ref": "InspectMode" + }, + { + "description": "A descriptor for the highlight appearance of hovered-over nodes. May be omitted if <code>enabled == false</code>.", + "optional":true, + "name": "highlightConfig", + "$ref": "HighlightConfig" + } + ], + "description": "Enters the 'inspect' mode. In this mode, elements that user is hovering over are highlighted. Backend then generates 'inspectNodeRequested' event upon element selection." + } + ], + "description": "This domain provides various functionality related to drawing atop the inspected page.", + "domain": "Overlay", + "dependencies": [ + "DOM" + ], + "experimental":true, + "events": [ + { + "name": "nodeHighlightRequested", + "description": "Fired when the node should be highlighted. This happens after call to <code>setInspectMode</code>.", + "parameters": [ + { + "name": "nodeId", + "$ref": "DOM.NodeId" + } + ] + }, + { + "name": "inspectNodeRequested", + "description": "Fired when the node should be inspected. This happens after call to <code>setInspectMode</code> or when user manually inspects an element.", + "parameters": [ + { + "name": "backendNodeId", + "$ref": "DOM.BackendNodeId", + "description": "Id of the node to inspect." + } + ] + } + ], + "types": [ + { + "id": "HighlightConfig", + "type": "object", + "properties": [ + { + "name": "showInfo", + "type": "boolean", + "optional":true, + "description": "Whether the node info tooltip should be shown (default: false)." + }, + { + "name": "showRulers", + "type": "boolean", + "optional":true, + "description": "Whether the rulers should be shown (default: false)." + }, + { + "name": "showExtensionLines", + "type": "boolean", + "optional":true, + "description": "Whether the extension lines from node to the rulers should be shown (default: false)." + }, + { + "name": "displayAsMaterial", + "type": "boolean", + "optional":true + }, + { + "name": "contentColor", + "$ref": "DOM.RGBA", + "optional":true, + "description": "The content box highlight fill color (default: transparent)." + }, + { + "name": "paddingColor", + "$ref": "DOM.RGBA", + "optional":true, + "description": "The padding highlight fill color (default: transparent)." + }, + { + "name": "borderColor", + "$ref": "DOM.RGBA", + "optional":true, + "description": "The border highlight fill color (default: transparent)." + }, + { + "name": "marginColor", + "$ref": "DOM.RGBA", + "optional":true, + "description": "The margin highlight fill color (default: transparent)." + }, + { + "name": "eventTargetColor", + "$ref": "DOM.RGBA", + "optional":true, + "description": "The event target element highlight fill color (default: transparent)." + }, + { + "name": "shapeColor", + "$ref": "DOM.RGBA", + "optional":true, + "description": "The shape outside fill color (default: transparent)." + }, + { + "name": "shapeMarginColor", + "$ref": "DOM.RGBA", + "optional":true, + "description": "The shape margin fill color (default: transparent)." + }, + { + "name": "selectorList", + "type": "string", + "optional":true, + "description": "Selectors to highlight relevant nodes." + } + ], + "description": "Configuration data for the highlighting of page elements." + }, + { + "id": "InspectMode", + "type": "string", + "enum": [ + "searchForNode", + "searchForUAShadowDOM", + "none" + ] + } + ] } ], "version": {
diff --git a/components/ui_devtools/views/BUILD.gn b/components/ui_devtools/views/BUILD.gn index 514fadf..6329d23f 100644 --- a/components/ui_devtools/views/BUILD.gn +++ b/components/ui_devtools/views/BUILD.gn
@@ -15,6 +15,8 @@ "ui_devtools_css_agent.h", "ui_devtools_dom_agent.cc", "ui_devtools_dom_agent.h", + "ui_devtools_overlay_agent.cc", + "ui_devtools_overlay_agent.h", "ui_element.cc", "ui_element.h", "ui_element_delegate.h", @@ -53,6 +55,7 @@ "//skia", "//testing/gtest", "//ui/aura", + "//ui/events:test_support", "//ui/views", "//ui/views:test_support", "//ui/wm:wm",
diff --git a/components/ui_devtools/views/ui_devtools_css_agent.cc b/components/ui_devtools/views/ui_devtools_css_agent.cc index 62a4be2..12109d1 100644 --- a/components/ui_devtools/views/ui_devtools_css_agent.cc +++ b/components/ui_devtools/views/ui_devtools_css_agent.cc
@@ -7,7 +7,6 @@ #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "components/ui_devtools/views/ui_element.h" -#include "ui/aura/window.h" namespace ui_devtools { namespace {
diff --git a/components/ui_devtools/views/ui_devtools_css_agent.h b/components/ui_devtools/views/ui_devtools_css_agent.h index ef88dccc..741e635 100644 --- a/components/ui_devtools/views/ui_devtools_css_agent.h +++ b/components/ui_devtools/views/ui_devtools_css_agent.h
@@ -43,7 +43,7 @@ bool SetPropertiesForNodeId(int node_id, const gfx::Rect& bounds, bool visible); - UIDevToolsDOMAgent* dom_agent_; + UIDevToolsDOMAgent* const dom_agent_; DISALLOW_COPY_AND_ASSIGN(UIDevToolsCSSAgent); };
diff --git a/components/ui_devtools/views/ui_devtools_dom_agent.cc b/components/ui_devtools/views/ui_devtools_dom_agent.cc index 1e7638b..295679fa 100644 --- a/components/ui_devtools/views/ui_devtools_dom_agent.cc +++ b/components/ui_devtools/views/ui_devtools_dom_agent.cc
@@ -6,6 +6,7 @@ #include "base/memory/ptr_util.h" #include "components/ui_devtools/devtools_server.h" +#include "components/ui_devtools/views/ui_devtools_overlay_agent.h" #include "components/ui_devtools/views/ui_element.h" #include "components/ui_devtools/views/view_element.h" #include "components/ui_devtools/views/widget_element.h" @@ -37,6 +38,7 @@ constexpr int kDomElementNodeType = 1; std::unique_ptr<DOM::Node> node = DOM::Node::create() .setNodeId(node_ids) + .setBackendNodeId(node_ids) .setNodeName(name) .setNodeType(kDomElementNodeType) .setAttributes(std::move(attributes)) @@ -103,16 +105,8 @@ for (auto* it : root->children()) children->addItem(BuildDomNodeFromUIElement(it)); - constexpr int kDomElementNodeType = 1; - std::unique_ptr<DOM::Node> node = DOM::Node::create() - .setNodeId(root->node_id()) - .setNodeName(root->GetTypeName()) - .setNodeType(kDomElementNodeType) - .setAttributes(GetAttributes(root)) - .build(); - node->setChildNodeCount(static_cast<int>(children->length())); - node->setChildren(std::move(children)); - return node; + return BuildNode(root->GetTypeName(), GetAttributes(root), + std::move(children), root->node_id()); } } // namespace @@ -137,19 +131,22 @@ return ui_devtools::protocol::Response::OK(); } -ui_devtools::protocol::Response UIDevToolsDOMAgent::highlightNode( - std::unique_ptr<ui_devtools::protocol::DOM::HighlightConfig> - highlight_config, - ui_devtools::protocol::Maybe<int> node_id) { - return HighlightNode(std::move(highlight_config), node_id.fromJust()); -} - ui_devtools::protocol::Response UIDevToolsDOMAgent::hideHighlight() { if (layer_for_highlighting_ && layer_for_highlighting_->visible()) layer_for_highlighting_->SetVisible(false); return ui_devtools::protocol::Response::OK(); } +ui_devtools::protocol::Response +UIDevToolsDOMAgent::pushNodesByBackendIdsToFrontend( + std::unique_ptr<protocol::Array<int>> backend_node_ids, + std::unique_ptr<protocol::Array<int>>* result) { + *result = protocol::Array<int>::create(); + for (size_t index = 0; index < backend_node_ids->length(); ++index) + (*result)->addItem(backend_node_ids->get(index)); + return ui_devtools::protocol::Response::OK(); +} + void UIDevToolsDOMAgent::OnUIElementAdded(UIElement* parent, UIElement* child) { // When parent is null, only need to update |node_id_to_ui_element_|. if (!parent) { @@ -206,6 +203,60 @@ return node_id_to_ui_element_[node_id]; } +ui_devtools::protocol::Response UIDevToolsDOMAgent::HighlightNode( + std::unique_ptr<ui_devtools::protocol::Overlay::HighlightConfig> + highlight_config, + int node_id) { + if (!layer_for_highlighting_) { + layer_for_highlighting_.reset( + new ui::Layer(ui::LayerType::LAYER_SOLID_COLOR)); + layer_for_highlighting_->set_name("HighlightingLayer"); + } + std::pair<aura::Window*, gfx::Rect> window_and_bounds = + node_id_to_ui_element_.count(node_id) + ? node_id_to_ui_element_[node_id]->GetNodeWindowAndBounds() + : std::make_pair<aura::Window*, gfx::Rect>(nullptr, gfx::Rect()); + + if (!window_and_bounds.first) + return ui_devtools::protocol::Response::Error("No node found with that id"); + + SkColor content_color = + RGBAToSkColor(highlight_config->getContentColor(nullptr)); + UpdateHighlight(window_and_bounds, content_color); + + if (!layer_for_highlighting_->visible()) + layer_for_highlighting_->SetVisible(true); + + return ui_devtools::protocol::Response::OK(); +} + +int UIDevToolsDOMAgent::FindElementIdTargetedByPoint( + const gfx::Point& p, + aura::Window* root_window) const { + aura::Window* targeted_window = root_window->GetEventHandlerForPoint(p); + if (!targeted_window) + return 0; + + views::Widget* targeted_widget = + views::Widget::GetWidgetForNativeWindow(targeted_window); + if (!targeted_widget) { + return window_element_root_->FindUIElementIdForBackendElement<aura::Window>( + targeted_window); + } + + views::View* root_view = targeted_widget->GetRootView(); + DCHECK(root_view); + + gfx::Point point_in_targeted_window(p); + aura::Window::ConvertPointToTarget(root_window, targeted_window, + &point_in_targeted_window); + views::View* targeted_view = + root_view->GetEventHandlerForPoint(point_in_targeted_window); + DCHECK(targeted_view); + return window_element_root_->FindUIElementIdForBackendElement<views::View>( + targeted_view); +} + void UIDevToolsDOMAgent::OnHostInitialized(aura::WindowTreeHost* host) { root_windows_.push_back(host->window()); } @@ -354,32 +405,4 @@ layer_for_highlighting_->SetBounds(bounds); } -ui_devtools::protocol::Response UIDevToolsDOMAgent::HighlightNode( - std::unique_ptr<ui_devtools::protocol::DOM::HighlightConfig> - highlight_config, - int node_id) { - if (!layer_for_highlighting_) { - layer_for_highlighting_.reset( - new ui::Layer(ui::LayerType::LAYER_SOLID_COLOR)); - layer_for_highlighting_->set_name("HighlightingLayer"); - } - - std::pair<aura::Window*, gfx::Rect> window_and_bounds = - node_id_to_ui_element_.count(node_id) - ? node_id_to_ui_element_[node_id]->GetNodeWindowAndBounds() - : std::make_pair<aura::Window*, gfx::Rect>(nullptr, gfx::Rect()); - - if (!window_and_bounds.first) { - return ui_devtools::protocol::Response::Error("No node found with that id"); - } - SkColor content_color = - RGBAToSkColor(highlight_config->getContentColor(nullptr)); - UpdateHighlight(window_and_bounds, content_color); - - if (!layer_for_highlighting_->visible()) - layer_for_highlighting_->SetVisible(true); - - return ui_devtools::protocol::Response::OK(); -} - } // namespace ui_devtools
diff --git a/components/ui_devtools/views/ui_devtools_dom_agent.h b/components/ui_devtools/views/ui_devtools_dom_agent.h index cdd2382..638b5c5a 100644 --- a/components/ui_devtools/views/ui_devtools_dom_agent.h +++ b/components/ui_devtools/views/ui_devtools_dom_agent.h
@@ -6,6 +6,7 @@ #define COMPONENTS_UI_DEVTOOLS_VIEWS_UI_DEVTOOLS_DOM_AGENT_H_ #include "components/ui_devtools/DOM.h" +#include "components/ui_devtools/Overlay.h" #include "components/ui_devtools/devtools_base_agent.h" #include "components/ui_devtools/views/ui_element_delegate.h" #include "ui/aura/env_observer.h" @@ -38,11 +39,10 @@ ui_devtools::protocol::Response disable() override; ui_devtools::protocol::Response getDocument( std::unique_ptr<ui_devtools::protocol::DOM::Node>* out_root) override; - ui_devtools::protocol::Response highlightNode( - std::unique_ptr<ui_devtools::protocol::DOM::HighlightConfig> - highlight_config, - ui_devtools::protocol::Maybe<int> node_id) override; ui_devtools::protocol::Response hideHighlight() override; + ui_devtools::protocol::Response pushNodesByBackendIdsToFrontend( + std::unique_ptr<protocol::Array<int>> backend_node_ids, + std::unique_ptr<protocol::Array<int>>* result) override; // UIElementDelegate: void OnUIElementAdded(UIElement* parent, UIElement* child) override; @@ -57,6 +57,18 @@ const std::vector<aura::Window*>& root_windows() const { return root_windows_; }; + ui_devtools::protocol::Response HighlightNode( + std::unique_ptr<ui_devtools::protocol::Overlay::HighlightConfig> + highlight_config, + int node_id); + + // Return the id of the UI element targeted by an event located at |p|, where + // |p| is in the local coodinate space of |root_window|. The function + // first searches for the targeted window, then the targeted widget (if one + // exists), then the targeted view (if one exists). Return 0 if no valid + // target is found. + int FindElementIdTargetedByPoint(const gfx::Point& p, + aura::Window* root_window) const; private: // aura::EnvObserver: @@ -78,18 +90,16 @@ views::View* view); void RemoveDomNode(UIElement* ui_element); void Reset(); - void InitializeHighlightingWidget(); void UpdateHighlight( const std::pair<aura::Window*, gfx::Rect>& window_and_bounds, SkColor background); - ui_devtools::protocol::Response HighlightNode( - std::unique_ptr<ui_devtools::protocol::DOM::HighlightConfig> - highlight_config, - int node_id); bool is_building_tree_; std::unique_ptr<UIElement> window_element_root_; std::unordered_map<int, UIElement*> node_id_to_ui_element_; + + // TODO(thanhph): |layer_for_highlighting_| should be owned by the overlay + // agent. std::unique_ptr<ui::Layer> layer_for_highlighting_; std::vector<aura::Window*> root_windows_; base::ObserverList<UIDevToolsDOMAgentObserver> observers_;
diff --git a/components/ui_devtools/views/ui_devtools_overlay_agent.cc b/components/ui_devtools/views/ui_devtools_overlay_agent.cc new file mode 100644 index 0000000..706637a --- /dev/null +++ b/components/ui_devtools/views/ui_devtools_overlay_agent.cc
@@ -0,0 +1,61 @@ +// 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 "components/ui_devtools/views/ui_devtools_overlay_agent.h" + +#include "ui/aura/env.h" + +namespace ui_devtools { + +UIDevToolsOverlayAgent::UIDevToolsOverlayAgent(UIDevToolsDOMAgent* dom_agent) + : dom_agent_(dom_agent) { + DCHECK(dom_agent_); +} + +UIDevToolsOverlayAgent::~UIDevToolsOverlayAgent() {} + +ui_devtools::protocol::Response UIDevToolsOverlayAgent::setInspectMode( + const String& in_mode, + protocol::Maybe<protocol::Overlay::HighlightConfig> in_highlightConfig) { + if (in_mode.compare("searchForNode") == 0) + aura::Env::GetInstance()->PrependPreTargetHandler(this); + else if (in_mode.compare("none") == 0) + aura::Env::GetInstance()->RemovePreTargetHandler(this); + return ui_devtools::protocol::Response::OK(); +} + +ui_devtools::protocol::Response UIDevToolsOverlayAgent::highlightNode( + std::unique_ptr<ui_devtools::protocol::Overlay::HighlightConfig> + highlight_config, + ui_devtools::protocol::Maybe<int> node_id) { + return dom_agent_->HighlightNode(std::move(highlight_config), + node_id.fromJust()); +} + +ui_devtools::protocol::Response UIDevToolsOverlayAgent::hideHighlight() { + return dom_agent_->hideHighlight(); +} + +void UIDevToolsOverlayAgent::OnMouseEvent(ui::MouseEvent* event) { + // Make sure the element tree has been populated before processing + // mouse events. + if (!dom_agent_->window_element_root()) + return; + + // Find node id of element whose bounds contain the mouse pointer location. + aura::Window* target = static_cast<aura::Window*>(event->target()); + int element_id = dom_agent_->FindElementIdTargetedByPoint( + event->root_location(), target->GetRootWindow()); + + if (event->type() == ui::ET_MOUSE_PRESSED) { + event->SetHandled(); + aura::Env::GetInstance()->RemovePreTargetHandler(this); + if (element_id) + frontend()->inspectNodeRequested(element_id); + } else if (element_id) { + frontend()->nodeHighlightRequested(element_id); + } +} + +} // namespace ui_devtools
diff --git a/components/ui_devtools/views/ui_devtools_overlay_agent.h b/components/ui_devtools/views/ui_devtools_overlay_agent.h new file mode 100644 index 0000000..4554f7d8 --- /dev/null +++ b/components/ui_devtools/views/ui_devtools_overlay_agent.h
@@ -0,0 +1,43 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_UI_DEVTOOLS_VIEWS_UI_DEVTOOLS_OVERLAY_AGENT_H_ +#define COMPONENTS_UI_DEVTOOLS_VIEWS_UI_DEVTOOLS_OVERLAY_AGENT_H_ + +#include "components/ui_devtools/Overlay.h" +#include "components/ui_devtools/views/ui_devtools_dom_agent.h" +#include "ui/events/event_handler.h" + +namespace ui_devtools { + +class UIDevToolsOverlayAgent : public ui_devtools::UiDevToolsBaseAgent< + ui_devtools::protocol::Overlay::Metainfo>, + public ui::EventHandler { + public: + explicit UIDevToolsOverlayAgent(UIDevToolsDOMAgent* dom_agent); + ~UIDevToolsOverlayAgent() override; + + // Overlay::Backend: + ui_devtools::protocol::Response setInspectMode( + const String& in_mode, + protocol::Maybe<protocol::Overlay::HighlightConfig> in_highlightConfig) + override; + ui_devtools::protocol::Response highlightNode( + std::unique_ptr<ui_devtools::protocol::Overlay::HighlightConfig> + highlight_config, + ui_devtools::protocol::Maybe<int> node_id) override; + ui_devtools::protocol::Response hideHighlight() override; + + private: + // ui:EventHandler: + void OnMouseEvent(ui::MouseEvent* event) override; + + UIDevToolsDOMAgent* const dom_agent_; + + DISALLOW_COPY_AND_ASSIGN(UIDevToolsOverlayAgent); +}; + +} // namespace ui_devtools + +#endif // COMPONENTS_UI_DEVTOOLS_VIEWS_UI_DEVTOOLS_OVERLAY_AGENT_H_
diff --git a/components/ui_devtools/views/ui_devtools_unittest.cc b/components/ui_devtools/views/ui_devtools_unittest.cc index 9ebf91f5..d2d1303 100644 --- a/components/ui_devtools/views/ui_devtools_unittest.cc +++ b/components/ui_devtools/views/ui_devtools_unittest.cc
@@ -6,6 +6,7 @@ #include "base/strings/stringprintf.h" #include "components/ui_devtools/views/ui_devtools_css_agent.h" #include "components/ui_devtools/views/ui_devtools_dom_agent.h" +#include "components/ui_devtools/views/ui_devtools_overlay_agent.h" #include "components/ui_devtools/views/ui_element.h" #include "components/ui_devtools/views/view_element.h" #include "components/ui_devtools/views/widget_element.h" @@ -13,6 +14,7 @@ #include "ui/aura/client/window_parenting_client.h" #include "ui/aura/window_tree_host.h" #include "ui/display/display.h" +#include "ui/events/test/event_generator.h" #include "ui/views/background.h" #include "ui/views/test/views_test_base.h" #include "ui/views/widget/native_widget_private.h" @@ -59,7 +61,7 @@ protocol_notification_messages_.end(), message); } - // FrontendChannel + // FrontendChannel: void sendProtocolResponse(int callId, std::unique_ptr<Serializable> message) override {} void flushProtocolNotifications() override {} @@ -157,10 +159,10 @@ .build(); } -std::unique_ptr<DOM::HighlightConfig> CreateHighlightConfig( +std::unique_ptr<Overlay::HighlightConfig> CreateHighlightConfig( const SkColor& background_color, const SkColor& border_color) { - return DOM::HighlightConfig::create() + return Overlay::HighlightConfig::create() .setContentColor(SkColorToRGBA(background_color)) .setBorderColor(SkColorToRGBA(border_color)) .build(); @@ -223,6 +225,10 @@ base::MakeUnique<ui_devtools::UIDevToolsCSSAgent>(dom_agent_.get()); css_agent_->Init(uber_dispatcher_.get()); css_agent_->enable(); + overlay_agent_ = + base::MakeUnique<ui_devtools::UIDevToolsOverlayAgent>(dom_agent_.get()); + overlay_agent_->Init(uber_dispatcher_.get()); + overlay_agent_->enable(); // We need to create |dom_agent| first to observe creation of // WindowTreeHosts in ViewTestBase::SetUp(). @@ -239,6 +245,7 @@ top_default_container_window.reset(); top_window.reset(); css_agent_.reset(); + overlay_agent_.reset(); dom_agent_.reset(); uber_dispatcher_.reset(); fake_frontend_channel_.reset(); @@ -268,6 +275,22 @@ node_id)); } + int GetOverlayNodeHighlightRequestedCount(int node_id) { + return frontend_channel()->CountProtocolNotificationMessage( + base::StringPrintf( + "{\"method\":\"Overlay.nodeHighlightRequested\",\"params\":{" + "\"nodeId\":%d}}", + node_id)); + } + + int GetOverlayInspectNodeRequestedCount(int node_id) { + return frontend_channel()->CountProtocolNotificationMessage( + base::StringPrintf( + "{\"method\":\"Overlay.inspectNodeRequested\",\"params\":{" + "\"backendNodeId\":%d}}", + node_id)); + } + void CompareNodeBounds(DOM::Node* node, const gfx::Rect& bounds) { Maybe<CSS::CSSStyle> styles; css_agent_->getMatchedStylesForNode(node->getNodeId(), &styles); @@ -299,7 +322,7 @@ } void HighlightNode(int node_id) { - dom_agent_->highlightNode( + overlay_agent_->highlightNode( CreateHighlightConfig(kBackgroundColor, kBorderColor), node_id); } @@ -324,6 +347,9 @@ ui_devtools::UIDevToolsCSSAgent* css_agent() { return css_agent_.get(); } ui_devtools::UIDevToolsDOMAgent* dom_agent() { return dom_agent_.get(); } + ui_devtools::UIDevToolsOverlayAgent* overlay_agent() { + return overlay_agent_.get(); + } std::unique_ptr<aura::Window> top_overlay_window; std::unique_ptr<aura::Window> top_window; @@ -334,10 +360,69 @@ std::unique_ptr<FakeFrontendChannel> fake_frontend_channel_; std::unique_ptr<ui_devtools::UIDevToolsDOMAgent> dom_agent_; std::unique_ptr<ui_devtools::UIDevToolsCSSAgent> css_agent_; + std::unique_ptr<ui_devtools::UIDevToolsOverlayAgent> overlay_agent_; DISALLOW_COPY_AND_ASSIGN(UIDevToolsTest); }; +// Tests that FindElementIdTargetedByPoint() returns a non-zero id when a UI +// element target exists. +TEST_F(UIDevToolsTest, FindElementIdTargetedByPoint) { + std::unique_ptr<views::Widget> widget( + CreateTestWidget(gfx::Rect(1, 1, 1, 1))); + std::unique_ptr<ui_devtools::protocol::DOM::Node> root; + dom_agent()->getDocument(&root); + EXPECT_NE(0, dom_agent()->FindElementIdTargetedByPoint( + gfx::Point(1, 1), GetPrimaryRootWindow())); +} + +// Tests that the correct Overlay events are dispatched to the frontend when +// hovering and clicking over a UI element in inspect mode. +TEST_F(UIDevToolsTest, MouseEventsGenerateFEEventsInInspectMode) { + std::unique_ptr<views::Widget> widget( + CreateTestWidget(gfx::Rect(1, 1, 1, 1))); + + std::unique_ptr<ui_devtools::protocol::DOM::Node> root; + dom_agent()->getDocument(&root); + + gfx::Point p(1, 1); + int node_id = + dom_agent()->FindElementIdTargetedByPoint(p, GetPrimaryRootWindow()); + + EXPECT_EQ(0, GetOverlayInspectNodeRequestedCount(node_id)); + EXPECT_EQ(0, GetOverlayNodeHighlightRequestedCount(node_id)); + overlay_agent()->setInspectMode( + "searchForNode", protocol::Maybe<protocol::Overlay::HighlightConfig>()); + + // Moving the mouse cursor over the widget bounds should request a node + // highlight. + ui::test::EventGenerator generator(widget->GetNativeWindow()); + generator.MoveMouseBy(p.x(), p.y()); + + // 2 mouse events ET_MOUSE_ENTERED and ET_MOUSE_MOVED are generated. + EXPECT_EQ(2, GetOverlayNodeHighlightRequestedCount(node_id)); + + EXPECT_EQ(0, GetOverlayInspectNodeRequestedCount(node_id)); + + // Clicking on the widget should request that element be inspected. + generator.PressLeftButton(); + int highlight_notification_count = + GetOverlayNodeHighlightRequestedCount(node_id); + int inspect_node_notification_count = + GetOverlayInspectNodeRequestedCount(node_id); + + EXPECT_EQ(1, GetOverlayInspectNodeRequestedCount(node_id)); + + // Since the last event dispatched to the widget was a click, a subsequent + // mouse event should generate neither a nodeHighlightRequested nor a + // inspectNodeRequested event. + generator.MoveMouseBy(p.x(), p.y()); + EXPECT_EQ(highlight_notification_count, + GetOverlayNodeHighlightRequestedCount(node_id)); + EXPECT_EQ(inspect_node_notification_count, + GetOverlayInspectNodeRequestedCount(node_id)); +} + TEST_F(UIDevToolsTest, GetDocumentWithWindowWidgetView) { std::unique_ptr<views::Widget> widget( CreateTestWidget(gfx::Rect(1, 1, 1, 1)));
diff --git a/components/ui_devtools/views/ui_element.cc b/components/ui_devtools/views/ui_element.cc index a44ff16..0d4a3e0 100644 --- a/components/ui_devtools/views/ui_element.cc +++ b/components/ui_devtools/views/ui_element.cc
@@ -68,6 +68,43 @@ delegate()->OnUIElementReordered(child->parent(), child); } +template <class T> +int UIElement::FindUIElementIdForBackendElement(T* element) const { + NOTREACHED(); + return 0; +} + +template <> +int UIElement::FindUIElementIdForBackendElement<aura::Window>( + aura::Window* element) const { + if (type_ == UIElementType::WINDOW && + UIElement::GetBackingElement<aura::Window, WindowElement>(this) == + element) { + return node_id_; + } + for (auto* child : children_) { + int ui_element_id = child->FindUIElementIdForBackendElement(element); + if (ui_element_id) + return ui_element_id; + } + return 0; +} + +template <> +int UIElement::FindUIElementIdForBackendElement<views::View>( + views::View* element) const { + if (type_ == UIElementType::VIEW && + UIElement::GetBackingElement<views::View, ViewElement>(this) == element) { + return node_id_; + } + for (auto* child : children_) { + int ui_element_id = child->FindUIElementIdForBackendElement(element); + if (ui_element_id) + return ui_element_id; + } + return 0; +} + UIElement::UIElement(const UIElementType type, UIElementDelegate* delegate, UIElement* parent)
diff --git a/components/ui_devtools/views/ui_element.h b/components/ui_devtools/views/ui_element.h index dcd614a0..2ed0a9b1 100644 --- a/components/ui_devtools/views/ui_element.h +++ b/components/ui_devtools/views/ui_element.h
@@ -40,6 +40,9 @@ // Move |child| to position new_index in |children_|. void ReorderChild(UIElement* child, int new_index); + template <class T> + int FindUIElementIdForBackendElement(T* element) const; + virtual void GetBounds(gfx::Rect* bounds) const = 0; virtual void SetBounds(const gfx::Rect& bounds) = 0; virtual void GetVisible(bool* visible) const = 0; @@ -51,7 +54,7 @@ const = 0; template <typename BackingT, typename T> - static BackingT* GetBackingElement(UIElement* element) { + static BackingT* GetBackingElement(const UIElement* element) { return T::From(element); };
diff --git a/components/ui_devtools/views/view_element.cc b/components/ui_devtools/views/view_element.cc index e7080110..5ee0c262 100644 --- a/components/ui_devtools/views/view_element.cc +++ b/components/ui_devtools/views/view_element.cc
@@ -79,9 +79,9 @@ } // static -views::View* ViewElement::From(UIElement* element) { +views::View* ViewElement::From(const UIElement* element) { DCHECK_EQ(UIElementType::VIEW, element->type()); - return static_cast<ViewElement*>(element)->view_; + return static_cast<const ViewElement*>(element)->view_; } } // namespace ui_devtools
diff --git a/components/ui_devtools/views/view_element.h b/components/ui_devtools/views/view_element.h index 37e46cc..fe30ec9 100644 --- a/components/ui_devtools/views/view_element.h +++ b/components/ui_devtools/views/view_element.h
@@ -36,7 +36,7 @@ void GetVisible(bool* visible) const override; void SetVisible(bool visible) override; std::pair<aura::Window*, gfx::Rect> GetNodeWindowAndBounds() const override; - static views::View* From(UIElement* element); + static views::View* From(const UIElement* element); private: views::View* view_;
diff --git a/components/ui_devtools/views/widget_element.cc b/components/ui_devtools/views/widget_element.cc index 7f87219b..4c93b81 100644 --- a/components/ui_devtools/views/widget_element.cc +++ b/components/ui_devtools/views/widget_element.cc
@@ -63,9 +63,9 @@ } // static -views::Widget* WidgetElement::From(UIElement* element) { +views::Widget* WidgetElement::From(const UIElement* element) { DCHECK_EQ(UIElementType::WIDGET, element->type()); - return static_cast<WidgetElement*>(element)->widget_; + return static_cast<const WidgetElement*>(element)->widget_; } } // namespace ui_devtools
diff --git a/components/ui_devtools/views/widget_element.h b/components/ui_devtools/views/widget_element.h index 9acc5eb..f208254b 100644 --- a/components/ui_devtools/views/widget_element.h +++ b/components/ui_devtools/views/widget_element.h
@@ -41,7 +41,7 @@ void SetVisible(bool visible) override; std::pair<aura::Window*, gfx::Rect> GetNodeWindowAndBounds() const override; - static views::Widget* From(UIElement* element); + static views::Widget* From(const UIElement* element); private: views::Widget* widget_;
diff --git a/components/ui_devtools/views/window_element.cc b/components/ui_devtools/views/window_element.cc index 951d137..1901eee 100644 --- a/components/ui_devtools/views/window_element.cc +++ b/components/ui_devtools/views/window_element.cc
@@ -88,9 +88,9 @@ } // static -aura::Window* WindowElement::From(UIElement* element) { +aura::Window* WindowElement::From(const UIElement* element) { DCHECK_EQ(UIElementType::WINDOW, element->type()); - return static_cast<WindowElement*>(element)->window_; + return static_cast<const WindowElement*>(element)->window_; } } // namespace ui_devtools
diff --git a/components/ui_devtools/views/window_element.h b/components/ui_devtools/views/window_element.h index 2574eff..645e0e4e 100644 --- a/components/ui_devtools/views/window_element.h +++ b/components/ui_devtools/views/window_element.h
@@ -38,7 +38,7 @@ void SetVisible(bool visible) override; std::pair<aura::Window*, gfx::Rect> GetNodeWindowAndBounds() const override; - static aura::Window* From(UIElement* element); + static aura::Window* From(const UIElement* element); private: aura::Window* window_;
diff --git a/components/viz/host/host_frame_sink_manager.cc b/components/viz/host/host_frame_sink_manager.cc index cc5fa91..df4e5d7 100644 --- a/components/viz/host/host_frame_sink_manager.cc +++ b/components/viz/host/host_frame_sink_manager.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/sequenced_task_runner.h" +#include "base/stl_util.h" #include "components/viz/common/surfaces/surface_info.h" #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h" #include "components/viz/service/frame_sinks/compositor_frame_sink_support_client.h" @@ -44,7 +45,9 @@ HostFrameSinkClient* client) { DCHECK(frame_sink_id.is_valid()); DCHECK(client); + FrameSinkData& data = frame_sink_data_map_[frame_sink_id]; + DCHECK(!data.IsFrameSinkRegistered()); DCHECK(!data.HasCompositorFrameSinkData()); data.client = client; frame_sink_manager_->RegisterFrameSinkId(frame_sink_id); @@ -53,10 +56,36 @@ void HostFrameSinkManager::InvalidateFrameSinkId( const FrameSinkId& frame_sink_id) { DCHECK(frame_sink_id.is_valid()); - auto it = frame_sink_data_map_.find(frame_sink_id); - DCHECK(it != frame_sink_data_map_.end()); - frame_sink_data_map_.erase(it); + + FrameSinkData& data = frame_sink_data_map_[frame_sink_id]; + DCHECK(data.IsFrameSinkRegistered()); + + // This will destroy |frame_sink_id| if using mojom::CompositorFrameSink. frame_sink_manager_->InvalidateFrameSinkId(frame_sink_id); + data.has_created_compositor_frame_sink = false; + data.client = nullptr; + + // There may be frame sink hierarchy information left in FrameSinkData. + if (data.IsEmpty()) + frame_sink_data_map_.erase(frame_sink_id); +} + +void HostFrameSinkManager::CreateRootCompositorFrameSink( + const FrameSinkId& frame_sink_id, + gpu::SurfaceHandle surface_handle, + const RendererSettings& renderer_settings, + mojom::CompositorFrameSinkAssociatedRequest request, + mojom::CompositorFrameSinkClientPtr client, + mojom::DisplayPrivateAssociatedRequest display_private_request) { + FrameSinkData& data = frame_sink_data_map_[frame_sink_id]; + DCHECK(!data.HasCompositorFrameSinkData()); + + data.is_root = true; + data.has_created_compositor_frame_sink = true; + + frame_sink_manager_->CreateRootCompositorFrameSink( + frame_sink_id, surface_handle, renderer_settings, std::move(request), + std::move(client), std::move(display_private_request)); } void HostFrameSinkManager::CreateCompositorFrameSink( @@ -80,25 +109,34 @@ frame_sink_manager_->RegisterFrameSinkHierarchy(parent_frame_sink_id, child_frame_sink_id); - frame_sink_data_map_[child_frame_sink_id].parent = parent_frame_sink_id; + FrameSinkData& child_data = frame_sink_data_map_[child_frame_sink_id]; + DCHECK(!base::ContainsValue(child_data.parents, parent_frame_sink_id)); + child_data.parents.push_back(parent_frame_sink_id); + + FrameSinkData& parent_data = frame_sink_data_map_[parent_frame_sink_id]; + DCHECK(!base::ContainsValue(parent_data.children, child_frame_sink_id)); + parent_data.children.push_back(child_frame_sink_id); } void HostFrameSinkManager::UnregisterFrameSinkHierarchy( const FrameSinkId& parent_frame_sink_id, const FrameSinkId& child_frame_sink_id) { - auto iter = frame_sink_data_map_.find(child_frame_sink_id); - DCHECK(iter != frame_sink_data_map_.end()); - - FrameSinkData& data = iter->second; - DCHECK_EQ(data.parent.value(), parent_frame_sink_id); - data.parent.reset(); - // Unregister and clear the stored parent. + FrameSinkData& child_data = frame_sink_data_map_[child_frame_sink_id]; + DCHECK(base::ContainsValue(child_data.parents, parent_frame_sink_id)); + base::Erase(child_data.parents, parent_frame_sink_id); + + FrameSinkData& parent_data = frame_sink_data_map_[parent_frame_sink_id]; + DCHECK(base::ContainsValue(parent_data.children, child_frame_sink_id)); + base::Erase(parent_data.children, child_frame_sink_id); + frame_sink_manager_->UnregisterFrameSinkHierarchy(parent_frame_sink_id, child_frame_sink_id); - if (data.IsEmpty()) - frame_sink_data_map_.erase(iter); + if (child_data.IsEmpty()) + frame_sink_data_map_.erase(child_frame_sink_id); + if (parent_data.IsEmpty()) + frame_sink_data_map_.erase(parent_frame_sink_id); } std::unique_ptr<CompositorFrameSinkSupport> @@ -116,7 +154,7 @@ client, frame_sink_manager_impl_, frame_sink_id, is_root, needs_sync_points); support->SetDestructionCallback( - base::BindOnce(&HostFrameSinkManager::DestroyCompositorFrameSink, + base::BindOnce(&HostFrameSinkManager::CompositorFrameSinkSupportDestroyed, weak_ptr_factory_.GetWeakPtr(), frame_sink_id)); data.support = support.get(); @@ -125,20 +163,13 @@ return support; } -void HostFrameSinkManager::DestroyCompositorFrameSink( +void HostFrameSinkManager::CompositorFrameSinkSupportDestroyed( const FrameSinkId& frame_sink_id) { auto iter = frame_sink_data_map_.find(frame_sink_id); DCHECK(iter != frame_sink_data_map_.end()); - FrameSinkData& data = iter->second; - DCHECK(data.HasCompositorFrameSinkData()); - if (data.has_created_compositor_frame_sink) { - data.has_created_compositor_frame_sink = false; - } else { - data.support = nullptr; - } - - if (data.IsEmpty()) + iter->second.support = nullptr; + if (iter->second.IsEmpty()) frame_sink_data_map_.erase(iter); } @@ -154,12 +185,27 @@ if (data.is_root) return; - if (data.parent.has_value()) { - frame_sink_manager_impl_->AssignTemporaryReference(surface_id, - data.parent.value()); + // If the frame sink has already been invalidated then we just drop the + // temporary reference. + if (!data.IsFrameSinkRegistered()) { + frame_sink_manager_->DropTemporaryReference(surface_id); return; } + // Find the oldest non-invalidated parent. + for (const FrameSinkId& parent_id : data.parents) { + const FrameSinkData& parent_data = frame_sink_data_map_[parent_id]; + if (parent_data.IsFrameSinkRegistered()) { + frame_sink_manager_impl_->AssignTemporaryReference(surface_id, parent_id); + return; + } + } + // TODO(kylechar): We might need to handle the case where there are multiple + // embedders better, so that the owner doesn't remove a surface reference + // until the other embedder has added a surface reference. Maybe just letting + // the client know what is the owner is sufficient, so the client can handle + // this. + // We don't have any hierarchy information for what will embed the new // surface, drop the temporary reference. frame_sink_manager_->DropTemporaryReference(surface_id);
diff --git a/components/viz/host/host_frame_sink_manager.h b/components/viz/host/host_frame_sink_manager.h index 1c8fbe5..aebd032 100644 --- a/components/viz/host/host_frame_sink_manager.h +++ b/components/viz/host/host_frame_sink_manager.h
@@ -6,6 +6,7 @@ #define COMPONENTS_VIZ_HOST_HOST_FRAME_SINK_MANAGER_H_ #include <memory> +#include <vector> #include "base/compiler_specific.h" #include "base/containers/flat_map.h" @@ -68,6 +69,18 @@ // message pipe to the client will be closed. void InvalidateFrameSinkId(const FrameSinkId& frame_sink_id); + // Creates a connection for a display root to viz. Provides the same + // interfaces as CreateCompositorFramesink() plus the priviledged + // DisplayPrivate interface. When no longer needed, call + // InvalidateFrameSinkId(). + void CreateRootCompositorFrameSink( + const FrameSinkId& frame_sink_id, + gpu::SurfaceHandle surface_handle, + const RendererSettings& renderer_settings, + mojom::CompositorFrameSinkAssociatedRequest request, + mojom::CompositorFrameSinkClientPtr client, + mojom::DisplayPrivateAssociatedRequest display_private_request); + // Creates a connection between client to viz, using |request| and |client|, // that allows the client to submit CompositorFrames. When no longer needed, // call InvalidateFrameSinkId(). @@ -75,12 +88,11 @@ mojom::CompositorFrameSinkRequest request, mojom::CompositorFrameSinkClientPtr client); - // Registers FrameSink hierarchy. Clients can call this multiple times to - // reparent without calling UnregisterFrameSinkHierarchy(). + // Registers frame sink hierarchy. A frame sink can have multiple parents. void RegisterFrameSinkHierarchy(const FrameSinkId& parent_frame_sink_id, const FrameSinkId& child_frame_sink_id); - // Unregisters FrameSink hierarchy. Client must have registered FrameSink + // Unregisters FrameSink hierarchy. Client must have registered frame sink // hierarchy before unregistering. void UnregisterFrameSinkHierarchy(const FrameSinkId& parent_frame_sink_id, const FrameSinkId& child_frame_sink_id); @@ -101,13 +113,16 @@ ~FrameSinkData(); FrameSinkData& operator=(FrameSinkData&& other); + bool IsFrameSinkRegistered() const { return client != nullptr; } + bool HasCompositorFrameSinkData() const { return has_created_compositor_frame_sink || support; } // Returns true if there is nothing in FrameSinkData and it can be deleted. bool IsEmpty() const { - return !HasCompositorFrameSinkData() && !parent.has_value() && !client; + return !IsFrameSinkRegistered() && !HasCompositorFrameSinkData() && + parents.empty() && children.empty(); } // The client to be notified of changes to this FrameSink. @@ -116,9 +131,6 @@ // If the frame sink is a root that corresponds to a Display. bool is_root = false; - // The FrameSinkId registered as the parent in the BeginFrame hierarchy. - base::Optional<FrameSinkId> parent; - // If a mojom::CompositorFrameSink was created for this FrameSinkId. This // will always be false if not using Mojo. bool has_created_compositor_frame_sink = false; @@ -126,13 +138,17 @@ // This will be null if using Mojo. CompositorFrameSinkSupport* support = nullptr; + // Track frame sink hierarchy in both directions. + std::vector<FrameSinkId> parents; + std::vector<FrameSinkId> children; + private: DISALLOW_COPY_AND_ASSIGN(FrameSinkData); }; - // Destroys a client connection. Will call UnregisterFrameSinkHierarchy() with - // the registered parent if there is one. - void DestroyCompositorFrameSink(const FrameSinkId& frame_sink_id); + // Provided as a callback to clear state when a CompositorFrameSinkSupport is + // destroyed. + void CompositorFrameSinkSupportDestroyed(const FrameSinkId& frame_sink_id); // Assigns the temporary reference to the frame sink that is expected to // embeded |surface_id|, otherwise drops the temporary reference.
diff --git a/components/viz/host/host_frame_sink_manager_unittests.cc b/components/viz/host/host_frame_sink_manager_unittests.cc index ba9d3df..bd89d4f3 100644 --- a/components/viz/host/host_frame_sink_manager_unittests.cc +++ b/components/viz/host/host_frame_sink_manager_unittests.cc
@@ -210,6 +210,10 @@ } TEST_F(HostFrameSinkManagerTest, AssignTemporaryReference) { + FakeHostFrameSinkClient client; + host_manager().RegisterFrameSinkId(kParentFrameSinkId, &client); + host_manager().RegisterFrameSinkId(kClientFrameSinkId, &client); + const SurfaceId surface_id = MakeSurfaceId(kClientFrameSinkId, 1); auto support = CreateCompositorFrameSinkSupport(surface_id.frame_sink_id(), false /* is_root */); @@ -237,6 +241,8 @@ MakeSurfaceInfo(surface_id)); } +// Verify that we drop the temporary reference to a new surface if the frame +// sink that corresponds to the new surface has been invalidated. TEST_F(HostFrameSinkManagerTest, DropTemporaryReferenceForStaleClient) { FakeHostFrameSinkClient client; host_manager().RegisterFrameSinkId(kClientFrameSinkId, &client); @@ -258,7 +264,8 @@ const SurfaceId client_surface_id = MakeSurfaceId(kClientFrameSinkId, 1); EXPECT_CALL(manager_impl(), DropTemporaryReference(client_surface_id)) .Times(0); - EXPECT_CALL(manager_impl(), AssignTemporaryReference(client_surface_id, _)) + EXPECT_CALL(manager_impl(), + AssignTemporaryReference(client_surface_id, kParentFrameSinkId)) .Times(1); GetFrameSinkManagerClient()->OnFirstSurfaceActivation( MakeSurfaceInfo(client_surface_id)); @@ -271,6 +278,8 @@ const SurfaceId client_surface_id2 = MakeSurfaceId(kClientFrameSinkId, 2); EXPECT_CALL(manager_impl(), DropTemporaryReference(client_surface_id2)) .Times(1); + EXPECT_CALL(manager_impl(), AssignTemporaryReference(client_surface_id2, _)) + .Times(0); GetFrameSinkManagerClient()->OnFirstSurfaceActivation( MakeSurfaceInfo(client_surface_id2)); @@ -278,6 +287,53 @@ host_manager().InvalidateFrameSinkId(kParentFrameSinkId); } +// Verify that we drop the temporary reference to a new surface if the only +// frame sink registered as an embedder has been invalidated. +TEST_F(HostFrameSinkManagerTest, DropTemporaryReferenceForInvalidatedParent) { + FakeHostFrameSinkClient client; + host_manager().RegisterFrameSinkId(kClientFrameSinkId, &client); + auto support_client = + CreateCompositorFrameSinkSupport(kClientFrameSinkId, false /* is_root */); + EXPECT_TRUE(FrameSinkDataExists(kClientFrameSinkId)); + + host_manager().RegisterFrameSinkId(kParentFrameSinkId, &client); + auto support_parent = + CreateCompositorFrameSinkSupport(kParentFrameSinkId, true /* is_root */); + EXPECT_TRUE(FrameSinkDataExists(kParentFrameSinkId)); + + // Register should call through to FrameSinkManagerImpl. + EXPECT_CALL(manager_impl(), RegisterFrameSinkHierarchy(kParentFrameSinkId, + kClientFrameSinkId)); + host_manager().RegisterFrameSinkHierarchy(kParentFrameSinkId, + kClientFrameSinkId); + + const SurfaceId client_surface_id = MakeSurfaceId(kClientFrameSinkId, 1); + EXPECT_CALL(manager_impl(), DropTemporaryReference(client_surface_id)) + .Times(0); + EXPECT_CALL(manager_impl(), + AssignTemporaryReference(client_surface_id, kParentFrameSinkId)) + .Times(1); + GetFrameSinkManagerClient()->OnFirstSurfaceActivation( + MakeSurfaceInfo(client_surface_id)); + testing::Mock::VerifyAndClearExpectations(&manager_impl()); + + // Invaidating the parent should cause the next SurfaceId to be dropped + // because there is no registered frame sink as the parent. + support_parent.reset(); + host_manager().InvalidateFrameSinkId(kParentFrameSinkId); + + const SurfaceId client_surface_id2 = MakeSurfaceId(kClientFrameSinkId, 2); + EXPECT_CALL(manager_impl(), DropTemporaryReference(client_surface_id2)) + .Times(1); + EXPECT_CALL(manager_impl(), AssignTemporaryReference(client_surface_id2, _)) + .Times(0); + GetFrameSinkManagerClient()->OnFirstSurfaceActivation( + MakeSurfaceInfo(client_surface_id2)); + + support_client.reset(); + host_manager().InvalidateFrameSinkId(kClientFrameSinkId); +} + TEST_F(HostFrameSinkManagerTest, DisplayRootTemporaryReference) { const SurfaceId surface_id = MakeSurfaceId(kParentFrameSinkId, 1); auto support = CreateCompositorFrameSinkSupport(surface_id.frame_sink_id(),
diff --git a/content/browser/accessibility/accessibility_tree_formatter_mac.mm b/content/browser/accessibility/accessibility_tree_formatter_mac.mm index 6ef7033d..8dce0b0 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_mac.mm +++ b/content/browser/accessibility/accessibility_tree_formatter_mac.mm
@@ -173,10 +173,12 @@ NSAccessibilityColumnIndexRangeAttribute, @"AXDOMIdentifier", @"AXDropEffects", + @"AXEditableAncestor", NSAccessibilityEnabledAttribute, NSAccessibilityExpandedAttribute, NSAccessibilityFocusedAttribute, @"AXGrabbed", + @"AXHighestEditableAncestor", NSAccessibilityIndexAttribute, @"AXLoaded", @"AXLoadingProcess",
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc index e51f201..e59d532c 100644 --- a/content/browser/accessibility/browser_accessibility_android.cc +++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -1088,6 +1088,9 @@ return i; } +// TODO(nektar): Merge this function with +// |BrowserAccessibilityCocoa::computeTextEdit|. +// // static size_t BrowserAccessibilityAndroid::CommonEndLengths( const base::string16 a,
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.h b/content/browser/accessibility/browser_accessibility_cocoa.h index 39d89e1..e774370 100644 --- a/content/browser/accessibility/browser_accessibility_cocoa.h +++ b/content/browser/accessibility/browser_accessibility_cocoa.h
@@ -8,9 +8,27 @@ #import <Cocoa/Cocoa.h> #import "base/mac/scoped_nsobject.h" +#include "base/strings/string16.h" #include "content/browser/accessibility/browser_accessibility.h" #include "content/browser/accessibility/browser_accessibility_manager.h" +namespace content { + +// Used to store changes in edit fields, required by VoiceOver in order to +// support character echo and other announcements during editing. +struct AXTextEdit { + AXTextEdit() = default; + AXTextEdit(base::string16 inserted_text, base::string16 deleted_text) + : inserted_text(inserted_text), deleted_text(deleted_text) {} + + bool IsEmpty() const { return inserted_text.empty() && deleted_text.empty(); } + + base::string16 inserted_text; + base::string16 deleted_text; +}; + +} // namespace content + // BrowserAccessibilityCocoa is a cocoa wrapper around the BrowserAccessibility // object. The renderer converts webkit's accessibility tree into a // WebAccessibility tree and passes it to the browser process over IPC. @@ -19,6 +37,8 @@ @private content::BrowserAccessibility* browserAccessibility_; base::scoped_nsobject<NSMutableArray> children_; + // Stores the previous value of an edit field. + base::string16 oldValue_; } // This creates a cocoa browser accessibility object around @@ -37,10 +57,6 @@ // from browserAccessibility_. - (ui::AXRole)internalRole; -// Convenience method to determine if this object should expose its -// accessible name in AXValue (as opposed to AXTitle/AXDescription). -- (BOOL)shouldExposeNameInAXValue; - // Convenience method to get the BrowserAccessibilityDelegate from // the manager. - (content::BrowserAccessibilityDelegate*)delegate; @@ -48,6 +64,9 @@ // Get the BrowserAccessibility that this object wraps. - (content::BrowserAccessibility*)browserAccessibility; +// Computes the text that was added or deleted in a text field after an edit. +- (content::AXTextEdit)computeTextEdit; + // Determines if this object is alive, i.e. it hasn't been detached. - (BOOL)instanceActive; @@ -84,6 +103,8 @@ @property(nonatomic, readonly) NSNumber* disclosureLevel; @property(nonatomic, readonly) id disclosedRows; @property(nonatomic, readonly) NSString* dropEffects; +// Returns the object at the root of the current edit field, if any. +@property(nonatomic, readonly) id editableAncestor; @property(nonatomic, readonly) NSNumber* enabled; // Returns a text marker that points to the last character in the document that // can be selected with Voiceover.
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm index 3516706f..051fcb1 100644 --- a/content/browser/accessibility/browser_accessibility_cocoa.mm +++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -16,7 +16,7 @@ #include "base/mac/availability.h" #include "base/mac/foundation_util.h" #include "base/mac/scoped_cftyperef.h" -#include "base/strings/string16.h" +#include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "content/app/strings/grit/content_strings.h" @@ -65,7 +65,11 @@ NSString* const NSAccessibilityAccessKeyAttribute = @"AXAccessKey"; NSString* const NSAccessibilityDOMIdentifierAttribute = @"AXDOMIdentifier"; NSString* const NSAccessibilityDropEffectsAttribute = @"AXDropEffects"; +NSString* const NSAccessibilityEditableAncestorAttribute = + @"AXEditableAncestor"; NSString* const NSAccessibilityGrabbedAttribute = @"AXGrabbed"; +NSString* const NSAccessibilityHighestEditableAncestorAttribute = + @"AXHighestEditableAncestor"; NSString* const NSAccessibilityInvalidAttribute = @"AXInvalid"; NSString* const NSAccessibilityIsMultiSelectableAttribute = @"AXIsMultiSelectable"; @@ -563,6 +567,7 @@ {NSAccessibilityDisclosedRowsAttribute, @"disclosedRows"}, {NSAccessibilityDropEffectsAttribute, @"dropEffects"}, {NSAccessibilityDOMIdentifierAttribute, @"domIdentifier"}, + {NSAccessibilityEditableAncestorAttribute, @"editableAncestor"}, {NSAccessibilityEnabledAttribute, @"enabled"}, {NSAccessibilityEndTextMarkerAttribute, @"endTextMarker"}, {NSAccessibilityExpandedAttribute, @"expanded"}, @@ -570,6 +575,8 @@ {NSAccessibilityGrabbedAttribute, @"grabbed"}, {NSAccessibilityHeaderAttribute, @"header"}, {NSAccessibilityHelpAttribute, @"help"}, + {NSAccessibilityHighestEditableAncestorAttribute, + @"highestEditableAncestor"}, {NSAccessibilityIndexAttribute, @"index"}, {NSAccessibilityInsertionPointLineNumberAttribute, @"insertionPointLineNumber"}, @@ -841,7 +848,7 @@ return nil; // Mac OS X wants static text exposed in AXValue. - if ([self shouldExposeNameInAXValue]) + if (ui::IsNameExposedInAXValueForRole([self internalRole])) return @""; // If we're exposing the title in TitleUIElement, don't also redundantly @@ -968,6 +975,23 @@ return nil; } +- (id)editableAncestor { + if (![self instanceActive]) + return nil; + + BrowserAccessibilityCocoa* editableRoot = self; + while (![editableRoot browserAccessibility]->GetBoolAttribute( + ui::AX_ATTR_EDITABLE_ROOT)) { + BrowserAccessibilityCocoa* parent = [editableRoot parent]; + if (!parent || ![parent isKindOfClass:[self class]] || + ![parent instanceActive]) { + return nil; + } + editableRoot = parent; + } + return editableRoot; +} + - (NSNumber*)enabled { if (![self instanceActive]) return nil; @@ -1046,6 +1070,26 @@ browserAccessibility_, ui::AX_ATTR_DESCRIPTION); } +- (id)highestEditableAncestor { + if (![self instanceActive]) + return nil; + + BrowserAccessibilityCocoa* highestEditableAncestor = [self editableAncestor]; + while (highestEditableAncestor) { + BrowserAccessibilityCocoa* ancestorParent = + [highestEditableAncestor parent]; + if (!ancestorParent || ![ancestorParent isKindOfClass:[self class]]) { + break; + } + BrowserAccessibilityCocoa* higherAncestor = + [ancestorParent editableAncestor]; + if (!higherAncestor) + break; + highestEditableAncestor = higherAncestor; + } + return highestEditableAncestor; +} + - (NSNumber*)index { if (![self instanceActive]) return nil; @@ -1290,20 +1334,6 @@ return static_cast<ui::AXRole>(browserAccessibility_->GetRole()); } -// Returns true if this should expose its accessible name in AXValue. -// internal -- (BOOL)shouldExposeNameInAXValue { - switch ([self internalRole]) { - case ui::AX_ROLE_LIST_BOX_OPTION: - case ui::AX_ROLE_LIST_MARKER: - case ui::AX_ROLE_MENU_LIST_OPTION: - case ui::AX_ROLE_STATIC_TEXT: - return true; - default: - return false; - } -} - // Returns true if this object should expose its accessible name using // AXTitleUIElement rather than AXTitle or AXDescription. We only do // this if it's a control, if there's a single label, and the label has @@ -1343,6 +1373,45 @@ return browserAccessibility_; } +// Assumes that there is at most one insertion, deletion or replacement at once. +// TODO(nektar): Merge this method with +// |BrowserAccessibilityAndroid::CommonEndLengths|. +- (content::AXTextEdit)computeTextEdit { + // Starting from macOS 10.11, if the user has edited some text we need to + // dispatch the actual text that changed on the value changed notification. + // We run this code on all macOS versions to get the highest test coverage. + base::string16 oldValue = oldValue_; + base::string16 newValue = browserAccessibility_->GetValue(); + oldValue_ = newValue; + if (oldValue.empty() && newValue.empty()) + return content::AXTextEdit(); + + size_t i; + size_t j; + // Sometimes Blink doesn't use the same UTF16 characters to represent + // whitespace. + for (i = 0; + i < oldValue.length() && i < newValue.length() && + (oldValue[i] == newValue[i] || (base::IsUnicodeWhitespace(oldValue[i]) && + base::IsUnicodeWhitespace(newValue[i]))); + ++i) { + } + for (j = 0; + (i + j) < oldValue.length() && (i + j) < newValue.length() && + (oldValue[oldValue.length() - j - 1] == + newValue[newValue.length() - j - 1] || + (base::IsUnicodeWhitespace(oldValue[oldValue.length() - j - 1]) && + base::IsUnicodeWhitespace(newValue[newValue.length() - j - 1]))); + ++j) { + } + DCHECK_LE(i + j, oldValue.length()); + DCHECK_LE(i + j, newValue.length()); + + base::string16 deletedText = oldValue.substr(i, oldValue.length() - i - j); + base::string16 insertedText = newValue.substr(i, newValue.length() - i - j); + return content::AXTextEdit(insertedText, deletedText); +} + - (BOOL)instanceActive { return browserAccessibility_ && browserAccessibility_->instance_active(); } @@ -1797,7 +1866,7 @@ if (![self instanceActive]) return nil; // Mac OS X wants static text exposed in AXValue. - if ([self shouldExposeNameInAXValue]) + if (ui::IsNameExposedInAXValueForRole([self internalRole])) return @""; // If we're exposing the title in TitleUIElement, don't also redundantly @@ -1859,11 +1928,12 @@ - (id)value { if (![self instanceActive]) return nil; + + if (ui::IsNameExposedInAXValueForRole([self internalRole])) + return NSStringForStringAttribute(browserAccessibility_, ui::AX_ATTR_NAME); + NSString* role = [self role]; - if ([self shouldExposeNameInAXValue]) { - return NSStringForStringAttribute( - browserAccessibility_, ui::AX_ATTR_NAME); - } else if ([role isEqualToString:@"AXHeading"]) { + if ([role isEqualToString:@"AXHeading"]) { int level = 0; if (browserAccessibility_->GetIntAttribute( ui::AX_ATTR_HIERARCHICAL_LEVEL, &level)) { @@ -2180,7 +2250,8 @@ CreatePositionFromTextMarker(parameter); if (position->IsNullPosition()) return nil; - return CreateTextMarker(position->CreateNextCharacterPosition()); + return CreateTextMarker(position->CreateNextCharacterPosition( + ui::AXBoundaryBehavior::CrossBoundary)); } if ([attribute isEqualToString:@"AXPreviousTextMarkerForTextMarker"]) { @@ -2188,7 +2259,8 @@ CreatePositionFromTextMarker(parameter); if (position->IsNullPosition()) return nil; - return CreateTextMarker(position->CreatePreviousCharacterPosition()); + return CreateTextMarker(position->CreatePreviousCharacterPosition( + ui::AXBoundaryBehavior::CrossBoundary)); } if ([attribute isEqualToString:@"AXLeftWordTextMarkerRangeForTextMarker"]) { @@ -2198,9 +2270,11 @@ return nil; AXPlatformPositionInstance startWordPosition = - endPosition->CreatePreviousWordStartPosition(); + endPosition->CreatePreviousWordStartPosition( + ui::AXBoundaryBehavior::StopAtAnchorBoundary); AXPlatformPositionInstance endWordPosition = - endPosition->CreatePreviousWordEndPosition(); + endPosition->CreatePreviousWordEndPosition( + ui::AXBoundaryBehavior::StopAtAnchorBoundary); AXPlatformPositionInstance startPosition = *startWordPosition <= *endWordPosition ? std::move(endWordPosition) : std::move(startWordPosition); @@ -2215,9 +2289,11 @@ return nil; AXPlatformPositionInstance endWordPosition = - startPosition->CreateNextWordEndPosition(); + startPosition->CreateNextWordEndPosition( + ui::AXBoundaryBehavior::StopAtAnchorBoundary); AXPlatformPositionInstance startWordPosition = - startPosition->CreateNextWordStartPosition(); + startPosition->CreateNextWordStartPosition( + ui::AXBoundaryBehavior::StopAtAnchorBoundary); AXPlatformPositionInstance endPosition = *startWordPosition <= *endWordPosition ? std::move(startWordPosition) : std::move(endWordPosition); @@ -2230,7 +2306,8 @@ CreatePositionFromTextMarker(parameter); if (position->IsNullPosition()) return nil; - return CreateTextMarker(position->CreateNextWordEndPosition()); + return CreateTextMarker(position->CreateNextWordEndPosition( + ui::AXBoundaryBehavior::CrossBoundary)); } if ([attribute @@ -2239,7 +2316,8 @@ CreatePositionFromTextMarker(parameter); if (position->IsNullPosition()) return nil; - return CreateTextMarker(position->CreatePreviousWordStartPosition()); + return CreateTextMarker(position->CreatePreviousWordStartPosition( + ui::AXBoundaryBehavior::CrossBoundary)); } if ([attribute isEqualToString:@"AXTextMarkerRangeForLine"]) { @@ -2249,9 +2327,11 @@ return nil; AXPlatformPositionInstance startPosition = - position->CreatePreviousLineStartPosition(); + position->CreatePreviousLineStartPosition( + ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary); AXPlatformPositionInstance endPosition = - position->CreateNextLineEndPosition(); + position->CreateNextLineEndPosition( + ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary); AXPlatformRange range(std::move(startPosition), std::move(endPosition)); return CreateTextMarkerRange(std::move(range)); } @@ -2263,9 +2343,11 @@ return nil; AXPlatformPositionInstance startLinePosition = - endPosition->CreatePreviousLineStartPosition(); + endPosition->CreatePreviousLineStartPosition( + ui::AXBoundaryBehavior::CrossBoundary); AXPlatformPositionInstance endLinePosition = - endPosition->CreatePreviousLineEndPosition(); + endPosition->CreatePreviousLineEndPosition( + ui::AXBoundaryBehavior::CrossBoundary); AXPlatformPositionInstance startPosition = *startLinePosition <= *endLinePosition ? std::move(endLinePosition) : std::move(startLinePosition); @@ -2280,9 +2362,11 @@ return nil; AXPlatformPositionInstance startLinePosition = - startPosition->CreateNextLineStartPosition(); + startPosition->CreateNextLineStartPosition( + ui::AXBoundaryBehavior::CrossBoundary); AXPlatformPositionInstance endLinePosition = - startPosition->CreateNextLineEndPosition(); + startPosition->CreateNextLineEndPosition( + ui::AXBoundaryBehavior::CrossBoundary); AXPlatformPositionInstance endPosition = *startLinePosition <= *endLinePosition ? std::move(startLinePosition) : std::move(endLinePosition); @@ -2295,7 +2379,8 @@ CreatePositionFromTextMarker(parameter); if (position->IsNullPosition()) return nil; - return CreateTextMarker(position->CreateNextLineEndPosition()); + return CreateTextMarker(position->CreateNextLineEndPosition( + ui::AXBoundaryBehavior::CrossBoundary)); } if ([attribute @@ -2304,7 +2389,8 @@ CreatePositionFromTextMarker(parameter); if (position->IsNullPosition()) return nil; - return CreateTextMarker(position->CreatePreviousLineStartPosition()); + return CreateTextMarker(position->CreatePreviousLineStartPosition( + ui::AXBoundaryBehavior::CrossBoundary)); } if ([attribute isEqualToString:@"AXLengthForTextMarkerRange"]) { @@ -2355,8 +2441,10 @@ if (position->IsNullPosition()) return nil; - AXPlatformRange range(position->CreatePreviousLineStartPosition(), - position->CreateNextLineEndPosition()); + AXPlatformRange range(position->CreatePreviousLineStartPosition( + ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary), + position->CreateNextLineEndPosition( + ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary)); return CreateTextMarkerRange(std::move(range)); } @@ -2581,10 +2669,12 @@ NSAccessibilityChildrenAttribute, NSAccessibilityDescriptionAttribute, NSAccessibilityDOMIdentifierAttribute, + NSAccessibilityEditableAncestorAttribute, NSAccessibilityEnabledAttribute, NSAccessibilityEndTextMarkerAttribute, NSAccessibilityFocusedAttribute, NSAccessibilityHelpAttribute, + NSAccessibilityHighestEditableAncestorAttribute, NSAccessibilityInvalidAttribute, NSAccessibilityLinkedUIElementsAttribute, NSAccessibilityParentAttribute,
diff --git a/content/browser/accessibility/browser_accessibility_com_win.cc b/content/browser/accessibility/browser_accessibility_com_win.cc index 05bf8393..f5200c1 100644 --- a/content/browser/accessibility/browser_accessibility_com_win.cc +++ b/content/browser/accessibility/browser_accessibility_com_win.cc
@@ -3245,22 +3245,16 @@ AXPlatformPositionInstance position = owner()->CreatePositionAt(static_cast<int>(start_offset), affinity); AXPlatformPositionInstance next_word = - position->CreateNextWordStartPosition(); - if (next_word->anchor_id() != owner()->GetId()) - next_word = position->CreatePositionAtEndOfAnchor(); + position->CreateNextWordStartPosition( + ui::AXBoundaryBehavior::StopAtAnchorBoundary); return next_word->text_offset(); } case ui::BACKWARDS_DIRECTION: { AXPlatformPositionInstance position = owner()->CreatePositionAt(static_cast<int>(start_offset), affinity); - AXPlatformPositionInstance previous_word; - if (!position->AtStartOfWord()) { - previous_word = position->CreatePreviousWordStartPosition(); - if (previous_word->anchor_id() != owner()->GetId()) - previous_word = position->CreatePositionAtStartOfAnchor(); - } else { - previous_word = std::move(position); - } + AXPlatformPositionInstance previous_word = + position->CreatePreviousWordStartPosition( + ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary); return previous_word->text_offset(); } } @@ -3272,22 +3266,16 @@ AXPlatformPositionInstance position = owner()->CreatePositionAt(static_cast<int>(start_offset), affinity); AXPlatformPositionInstance next_line = - position->CreateNextLineStartPosition(); - if (next_line->anchor_id() != owner()->GetId()) - next_line = position->CreatePositionAtEndOfAnchor(); + position->CreateNextLineStartPosition( + ui::AXBoundaryBehavior::StopAtAnchorBoundary); return next_line->text_offset(); } case ui::BACKWARDS_DIRECTION: { AXPlatformPositionInstance position = owner()->CreatePositionAt(static_cast<int>(start_offset), affinity); - AXPlatformPositionInstance previous_line; - if (!position->AtStartOfLine()) { - previous_line = position->CreatePreviousLineStartPosition(); - if (previous_line->anchor_id() != owner()->GetId()) - previous_line = position->CreatePositionAtStartOfAnchor(); - } else { - previous_line = std::move(position); - } + AXPlatformPositionInstance previous_line = + position->CreatePreviousLineStartPosition( + ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary); return previous_line->text_offset(); } }
diff --git a/content/browser/accessibility/browser_accessibility_mac_unittest.mm b/content/browser/accessibility/browser_accessibility_mac_unittest.mm index dac10fe..c7bf8a19 100644 --- a/content/browser/accessibility/browser_accessibility_mac_unittest.mm +++ b/content/browser/accessibility/browser_accessibility_mac_unittest.mm
@@ -7,14 +7,18 @@ #import <Cocoa/Cocoa.h> #include <memory> +#include <string> +#include <vector> #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "content/browser/accessibility/browser_accessibility_cocoa.h" #include "content/browser/accessibility/browser_accessibility_manager.h" #include "content/browser/accessibility/browser_accessibility_manager_mac.h" +#include "content/public/browser/ax_event_notification_details.h" #include "testing/gtest/include/gtest/gtest.h" #import "testing/gtest_mac.h" +#include "ui/accessibility/ax_tree_update.h" #import "ui/gfx/test/ui_cocoa_test_helper.h" namespace content { @@ -28,14 +32,16 @@ protected: void RebuildAccessibilityTree() { - ui::AXNodeData root; - root.id = 1000; - root.location.set_width(500); - root.location.set_height(100); - root.role = ui::AX_ROLE_ROOT_WEB_AREA; - root.AddStringAttribute(ui::AX_ATTR_DESCRIPTION, "HelpText"); - root.child_ids.push_back(1001); - root.child_ids.push_back(1002); + // Clean out the existing root data in case this method is called multiple + // times in a test. + root_ = ui::AXNodeData(); + root_.id = 1000; + root_.location.set_width(500); + root_.location.set_height(100); + root_.role = ui::AX_ROLE_ROOT_WEB_AREA; + root_.AddStringAttribute(ui::AX_ATTR_DESCRIPTION, "HelpText"); + root_.child_ids.push_back(1001); + root_.child_ids.push_back(1002); ui::AXNodeData child1; child1.id = 1001; @@ -51,14 +57,26 @@ child2.location.set_height(100); child2.role = ui::AX_ROLE_HEADING; - manager_.reset( - new BrowserAccessibilityManagerMac( - MakeAXTreeUpdate(root, child1, child2), - NULL)); + manager_.reset(new BrowserAccessibilityManagerMac( + MakeAXTreeUpdate(root_, child1, child2), nullptr)); accessibility_.reset([ToBrowserAccessibilityCocoa(manager_->GetRoot()) retain]); } + void SetRootValue(std::string value) { + if (!manager_) + return; + root_.SetValue(value); + ui::AXTreeUpdate update; + update.nodes.push_back(root_); + AXEventNotificationDetails param; + param.event_type = ui::AX_EVENT_VALUE_CHANGED; + param.id = root_.id; + std::vector<AXEventNotificationDetails> events{param}; + manager_->OnAccessibilityEvents(update, events); + } + + ui::AXNodeData root_; base::scoped_nsobject<BrowserAccessibilityCocoa> accessibility_; std::unique_ptr<BrowserAccessibilityManager> manager_; }; @@ -126,4 +144,72 @@ [retainedFirstChild release]; } +TEST_F(BrowserAccessibilityTest, TestComputeTextEdit) { + BrowserAccessibility* wrapper = [accessibility_ browserAccessibility]; + ASSERT_NE(nullptr, wrapper); + + // Insertion but no deletion. + + SetRootValue("text"); + AXTextEdit text_edit = [accessibility_ computeTextEdit]; + EXPECT_EQ(base::UTF8ToUTF16("text"), text_edit.inserted_text); + EXPECT_TRUE(text_edit.deleted_text.empty()); + + SetRootValue("new text"); + text_edit = [accessibility_ computeTextEdit]; + EXPECT_EQ(base::UTF8ToUTF16("new "), text_edit.inserted_text); + EXPECT_TRUE(text_edit.deleted_text.empty()); + + SetRootValue("new text hello"); + text_edit = [accessibility_ computeTextEdit]; + EXPECT_EQ(base::UTF8ToUTF16(" hello"), text_edit.inserted_text); + EXPECT_TRUE(text_edit.deleted_text.empty()); + + SetRootValue("newer text hello"); + text_edit = [accessibility_ computeTextEdit]; + EXPECT_EQ(base::UTF8ToUTF16("er"), text_edit.inserted_text); + EXPECT_TRUE(text_edit.deleted_text.empty()); + + // Deletion but no insertion. + + SetRootValue("new text hello"); + text_edit = [accessibility_ computeTextEdit]; + EXPECT_EQ(base::UTF8ToUTF16("er"), text_edit.deleted_text); + EXPECT_TRUE(text_edit.inserted_text.empty()); + + SetRootValue("new text"); + text_edit = [accessibility_ computeTextEdit]; + EXPECT_EQ(base::UTF8ToUTF16(" hello"), text_edit.deleted_text); + EXPECT_TRUE(text_edit.inserted_text.empty()); + + SetRootValue("text"); + text_edit = [accessibility_ computeTextEdit]; + EXPECT_EQ(base::UTF8ToUTF16("new "), text_edit.deleted_text); + EXPECT_TRUE(text_edit.inserted_text.empty()); + + SetRootValue(""); + text_edit = [accessibility_ computeTextEdit]; + EXPECT_EQ(base::UTF8ToUTF16("text"), text_edit.deleted_text); + EXPECT_TRUE(text_edit.inserted_text.empty()); + + // Both insertion and deletion. + + SetRootValue("new text hello"); + text_edit = [accessibility_ computeTextEdit]; + SetRootValue("new word hello"); + text_edit = [accessibility_ computeTextEdit]; + EXPECT_EQ(base::UTF8ToUTF16("text"), text_edit.deleted_text); + EXPECT_EQ(base::UTF8ToUTF16("word"), text_edit.inserted_text); + + SetRootValue("new word there"); + text_edit = [accessibility_ computeTextEdit]; + EXPECT_EQ(base::UTF8ToUTF16("hello"), text_edit.deleted_text); + EXPECT_EQ(base::UTF8ToUTF16("there"), text_edit.inserted_text); + + SetRootValue("old word there"); + text_edit = [accessibility_ computeTextEdit]; + EXPECT_EQ(base::UTF8ToUTF16("new"), text_edit.deleted_text); + EXPECT_EQ(base::UTF8ToUTF16("old"), text_edit.inserted_text); +} + } // namespace content
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.h b/content/browser/accessibility/browser_accessibility_manager_mac.h index 7fe004e..36f8d23 100644 --- a/content/browser/accessibility/browser_accessibility_manager_mac.h +++ b/content/browser/accessibility/browser_accessibility_manager_mac.h
@@ -50,9 +50,6 @@ void OnTreeDataChanged(ui::AXTree* tree, const ui::AXTreeData& old_tree_data, const ui::AXTreeData& new_tree_data) override; - void OnNodeDataWillChange(ui::AXTree* tree, - const ui::AXNodeData& old_node_data, - const ui::AXNodeData& new_node_data) override; void OnStateChanged(ui::AXTree* tree, ui::AXNode* node, ui::AXState state, @@ -85,15 +82,15 @@ const base::string16& deleted_text, const base::string16& inserted_text) const; + // Keeps track of any edits that have been made by the user during a tree + // update. Used by NSAccessibilityValueChangedNotification. + // Maps AXNode IDs to value attribute changes. + std::map<int32_t, AXTextEdit> text_edits_; + // This gives BrowserAccessibilityManager::Create access to the class // constructor. friend class BrowserAccessibilityManager; - // Keeps track of any edits that have been made by the user during a tree - // update. Used by NSAccessibilityValueChangedNotification. - // Maps AXNode IDs to name or value attribute changes. - std::map<int32_t, base::string16> text_edits_; - DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManagerMac); };
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.mm b/content/browser/accessibility/browser_accessibility_manager_mac.mm index 8666d82f..2afab5c274 100644 --- a/content/browser/accessibility/browser_accessibility_manager_mac.mm +++ b/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -251,15 +251,17 @@ break; case ui::AX_EVENT_VALUE_CHANGED: mac_notification = NSAccessibilityValueChangedNotification; - if (base::mac::IsAtLeastOS10_11() && text_edits_.size()) { - // It seems that we don't need to distinguish between deleted and - // inserted text for now. + if (base::mac::IsAtLeastOS10_11() && !text_edits_.empty()) { base::string16 deleted_text; base::string16 inserted_text; int32_t id = node->GetId(); const auto iterator = text_edits_.find(id); - if (iterator != text_edits_.end()) - inserted_text = iterator->second; + if (iterator != text_edits_.end()) { + AXTextEdit text_edit = iterator->second; + deleted_text = text_edit.deleted_text; + inserted_text = text_edit.inserted_text; + } + NSDictionary* user_info = GetUserInfoForValueChangedNotification( native_node, deleted_text, inserted_text); @@ -383,55 +385,6 @@ } } -void BrowserAccessibilityManagerMac::OnNodeDataWillChange( - ui::AXTree* tree, - const ui::AXNodeData& old_node_data, - const ui::AXNodeData& new_node_data) { - BrowserAccessibilityManager::OnNodeDataWillChange(tree, old_node_data, - new_node_data); - - // Starting from OS X 10.11, if the user has edited some text we need to - // dispatch the actual text that changed on the value changed notification. - // We run this code on all OS X versions to get the highest test coverage. - base::string16 old_text, new_text; - ui::AXRole role = new_node_data.role; - if (role == ui::AX_ROLE_COMBO_BOX || role == ui::AX_ROLE_SEARCH_BOX || - role == ui::AX_ROLE_TEXT_FIELD) { - old_text = old_node_data.GetString16Attribute(ui::AX_ATTR_VALUE); - new_text = new_node_data.GetString16Attribute(ui::AX_ATTR_VALUE); - } else if (new_node_data.HasState(ui::AX_STATE_EDITABLE)) { - old_text = old_node_data.GetString16Attribute(ui::AX_ATTR_NAME); - new_text = new_node_data.GetString16Attribute(ui::AX_ATTR_NAME); - } - - if ((old_text.empty() && new_text.empty()) || - old_text.length() == new_text.length()) { - return; - } - - if (old_text.length() < new_text.length()) { - // Insertion. - size_t i = 0; - while (i < old_text.length() && i < new_text.length() && - old_text[i] == new_text[i]) { - ++i; - } - size_t length = (new_text.length() - i) - (old_text.length() - i); - base::string16 inserted_text = new_text.substr(i, length); - text_edits_[new_node_data.id] = inserted_text; - } else { - // Deletion. - size_t i = 0; - while (i < old_text.length() && i < new_text.length() && - old_text[i] == new_text[i]) { - ++i; - } - size_t length = (old_text.length() - i) - (new_text.length() - i); - base::string16 deleted_text = old_text.substr(i, length); - text_edits_[new_node_data.id] = deleted_text; - } -} - void BrowserAccessibilityManagerMac::OnStateChanged(ui::AXTree* tree, ui::AXNode* node, ui::AXState state, @@ -528,7 +481,17 @@ const std::vector<Change>& changes) { BrowserAccessibilityManager::OnAtomicUpdateFinished(tree, root_changed, changes); + + std::set<const BrowserAccessibilityCocoa*> changed_editable_roots; for (const auto& change : changes) { + const BrowserAccessibility* obj = GetFromAXNode(change.node); + if (obj && obj->IsNative() && obj->HasState(ui::AX_STATE_EDITABLE)) { + const BrowserAccessibilityCocoa* editable_root = + [ToBrowserAccessibilityCocoa(obj) editableAncestor]; + if (editable_root && [editable_root instanceActive]) + changed_editable_roots.insert(editable_root); + } + if ((change.type == NODE_CREATED || change.type == SUBTREE_CREATED) && change.node->data().HasStringAttribute(ui::AX_ATTR_LIVE_STATUS)) { if (change.node->data().role == ui::AX_ROLE_ALERT) @@ -549,6 +512,13 @@ } } + for (const BrowserAccessibilityCocoa* obj : changed_editable_roots) { + DCHECK(obj); + const AXTextEdit text_edit = [obj computeTextEdit]; + if (!text_edit.IsEmpty()) + text_edits_[[obj browserAccessibility]->GetId()] = text_edit; + } + if (root_changed && tree->data().loaded) tree_events_[tree->root()->id()].insert(ui::AX_EVENT_LOAD_COMPLETE); } @@ -598,14 +568,16 @@ NSMutableArray* changes = [[[NSMutableArray alloc] init] autorelease]; if (!deleted_text.empty()) { [changes addObject:@{ - NSAccessibilityTextEditType : @(AXTextEditTypeUnknown), + NSAccessibilityTextEditType : @(AXTextEditTypeDelete), NSAccessibilityTextChangeValueLength : @(deleted_text.length()), NSAccessibilityTextChangeValue : base::SysUTF16ToNSString(deleted_text) }]; } if (!inserted_text.empty()) { + // TODO(nektar): Figure out if this is a paste operation instead of typing. + // Changes to Blink would be required. [changes addObject:@{ - NSAccessibilityTextEditType : @(AXTextEditTypeUnknown), + NSAccessibilityTextEditType : @(AXTextEditTypeTyping), NSAccessibilityTextChangeValueLength : @(inserted_text.length()), NSAccessibilityTextChangeValue : base::SysUTF16ToNSString(inserted_text) }];
diff --git a/content/browser/appcache/appcache_manifest_parser.cc b/content/browser/appcache/appcache_manifest_parser.cc index ca4cb7a..a8b9321 100644 --- a/content/browser/appcache/appcache_manifest_parser.cc +++ b/content/browser/appcache/appcache_manifest_parser.cc
@@ -60,7 +60,7 @@ bool ScopeMatches(const GURL& manifest_url, const GURL& namespace_url) { return base::StartsWith(namespace_url.spec(), - manifest_url.Resolve(".").spec(), + manifest_url.GetWithoutFilename().spec(), base::CompareCase::SENSITIVE); }
diff --git a/content/browser/appcache/appcache_manifest_parser_unittest.cc b/content/browser/appcache/appcache_manifest_parser_unittest.cc index bd34ef19..caa0264b 100644 --- a/content/browser/appcache/appcache_manifest_parser_unittest.cc +++ b/content/browser/appcache/appcache_manifest_parser_unittest.cc
@@ -564,7 +564,8 @@ "http://foo.com/out_of_scope/ fallback_url\r"); // Scope matching depends on resolving "." as a relative url. - EXPECT_EQ(kUrl.Resolve(".").spec(), std::string("http://foo.com/scope/")); + EXPECT_EQ(kUrl.GetWithoutFilename().spec(), + std::string("http://foo.com/scope/")); AppCacheManifest manifest; EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
diff --git a/content/browser/appcache/appcache_service_impl.h b/content/browser/appcache/appcache_service_impl.h index 372e96e8..f42e72a 100644 --- a/content/browser/appcache/appcache_service_impl.h +++ b/content/browser/appcache/appcache_service_impl.h
@@ -16,6 +16,7 @@ #include "base/observer_list.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "content/browser/url_loader_factory_getter.h" #include "content/common/appcache_interfaces.h" #include "content/common/content_export.h" #include "content/public/browser/appcache_service.h" @@ -182,6 +183,18 @@ void set_force_keep_session_state() { force_keep_session_state_ = true; } bool force_keep_session_state() const { return force_keep_session_state_; } + // The following two functions are invoked in the network service world to + // set/get a pointer to the URLLoaderFactoryGetter instance which is used to + // get to the network URL loader factory. + void set_url_loader_factory_getter( + URLLoaderFactoryGetter* loader_factory_getter) { + url_loader_factory_getter_ = loader_factory_getter; + } + + URLLoaderFactoryGetter* url_loader_factory_getter() const { + return url_loader_factory_getter_.get(); + } + protected: friend class content::AppCacheServiceImplTest; friend class content::AppCacheStorageImplTest; @@ -220,6 +233,11 @@ base::OneShotTimer reinit_timer_; base::ObserverList<Observer> observers_; + // In the network service world contains the pointer to the + // URLLoaderFactoryGetter instance which is used to get to the network + // URL loader factory. + scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter_; + private: base::WeakPtrFactory<AppCacheServiceImpl> weak_factory_;
diff --git a/content/browser/appcache/appcache_update_job.cc b/content/browser/appcache/appcache_update_job.cc index 60482b5..385d41f 100644 --- a/content/browser/appcache/appcache_update_job.cc +++ b/content/browser/appcache/appcache_update_job.cc
@@ -485,7 +485,7 @@ DCHECK(internal_state_ == DOWNLOADING); UpdateRequestBase* request = fetcher->request(); - const GURL& url = request->GetOriginalURL(); + const GURL& url = request->GetURL(); pending_url_fetches_.erase(url); NotifyAllProgress(url); ++url_fetches_completed_; @@ -586,7 +586,7 @@ // be called in CACHE_FAILURE state. UpdateRequestBase* request = fetcher->request(); - const GURL& url = request->GetOriginalURL(); + const GURL& url = request->GetURL(); master_entry_fetches_.erase(url); ++master_entries_completed_;
diff --git a/content/browser/appcache/appcache_update_request_base.cc b/content/browser/appcache/appcache_update_request_base.cc index 0256ff5..30dcd0d 100644 --- a/content/browser/appcache/appcache_update_request_base.cc +++ b/content/browser/appcache/appcache_update_request_base.cc
@@ -3,23 +3,69 @@ // found in the LICENSE file. #include "content/browser/appcache/appcache_update_request_base.h" +#include "content/browser/appcache/appcache_update_url_loader_request.h" #include "content/browser/appcache/appcache_update_url_request.h" +#include "content/public/common/content_features.h" #include "net/url_request/url_request_context.h" namespace content { +namespace { +constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation = + net::DefineNetworkTrafficAnnotation("appcache_update_job", R"( + semantics { + sender: "HTML5 AppCache System" + description: + "Web pages can include a link to a manifest file which lists " + "resources to be cached for offline access. The AppCache system" + "retrieves those resources in the background." + trigger: + "User visits a web page containing a <html manifest=manifestUrl> " + "tag, or navigates to a document retrieved from an existing appcache " + "and some resource should be updated." + data: "None" + destination: WEBSITE + } + policy { + cookies_allowed: YES + cookies_store: "user" + setting: + "Users can control this feature via the 'Cookies' setting under " + "'Privacy, Content settings'. If cookies are disabled for a single " + "site, appcaches are disabled for the site only. If they are totally " + "disabled, all appcache requests will be stopped." + chrome_policy { + DefaultCookiesSetting { + DefaultCookiesSetting: 2 + } + } + })"); +} + AppCacheUpdateJob::UpdateRequestBase::~UpdateRequestBase() {} // static std::unique_ptr<AppCacheUpdateJob::UpdateRequestBase> AppCacheUpdateJob::UpdateRequestBase::Create( - net::URLRequestContext* request_context, + AppCacheServiceImpl* appcache_service, const GURL& url, + int buffer_size, URLFetcher* fetcher) { - return std::unique_ptr<UpdateRequestBase>( - new UpdateURLRequest(request_context, url, fetcher)); + if (!base::FeatureList::IsEnabled(features::kNetworkService)) { + return std::unique_ptr<UpdateRequestBase>(new UpdateURLRequest( + appcache_service->request_context(), url, buffer_size, fetcher)); + } else { + return std::unique_ptr<UpdateRequestBase>(new UpdateURLLoaderRequest( + appcache_service->url_loader_factory_getter(), url, buffer_size, + fetcher)); + } } AppCacheUpdateJob::UpdateRequestBase::UpdateRequestBase() {} +net::NetworkTrafficAnnotationTag +AppCacheUpdateJob::UpdateRequestBase::GetTrafficAnnotation() const { + return kTrafficAnnotation; +} + } // namespace content
diff --git a/content/browser/appcache/appcache_update_request_base.h b/content/browser/appcache/appcache_update_request_base.h index 76ce098a..0c3f787 100644 --- a/content/browser/appcache/appcache_update_request_base.h +++ b/content/browser/appcache/appcache_update_request_base.h
@@ -20,10 +20,6 @@ #include "url/gurl.h" #include "url/origin.h" -namespace net { -class URLRequestContext; -} - namespace content { class AppCacheUpdateJob::UpdateRequestBase { @@ -32,8 +28,9 @@ // Creates an instance of the AppCacheUpdateRequestBase subclass. static std::unique_ptr<UpdateRequestBase> Create( - net::URLRequestContext* request_context, + AppCacheServiceImpl* appcache_service, const GURL& url, + int buffer_size, URLFetcher* fetcher); // This method is called to start the request. @@ -48,11 +45,6 @@ // Returns the request URL. virtual GURL GetURL() const = 0; - // Returns the original URL of the request. The original url is the url used - // to initialize the request, and it may differ from the url if the request - // was redirected. - virtual GURL GetOriginalURL() const = 0; - // Sets flags which control the request load. e.g. if it can be loaded // from cache, etc. virtual void SetLoadFlags(int flags) = 0; @@ -80,14 +72,11 @@ virtual int GetResponseCode() const = 0; // Get the HTTP response info in its entirety. - virtual net::HttpResponseInfo GetResponseInfo() const = 0; + virtual const net::HttpResponseInfo& GetResponseInfo() const = 0; - // Used to specify the context (cookie store, cache) for this request. - virtual const net::URLRequestContext* GetRequestContext() const = 0; - - // Initiates an asynchronous read. Could return net::ERR_IO_PENDING or the - // number of bytes read. - virtual int Read(net::IOBuffer* buf, int max_bytes) = 0; + // Initiates an asynchronous read. Multiple concurrent reads are not + // supported. + virtual void Read() = 0; // This method may be called at any time after Start() has been called to // cancel the request. @@ -96,6 +85,10 @@ protected: UpdateRequestBase(); + + // Returns the traffic annotation information to be used for the outgoing + // request. + net::NetworkTrafficAnnotationTag GetTrafficAnnotation() const; }; } // namespace content
diff --git a/content/browser/appcache/appcache_update_url_fetcher.cc b/content/browser/appcache/appcache_update_url_fetcher.cc index 891e143e..2e9634eb 100644 --- a/content/browser/appcache/appcache_update_url_fetcher.cc +++ b/content/browser/appcache/appcache_update_url_fetcher.cc
@@ -4,10 +4,13 @@ #include "content/browser/appcache/appcache_update_url_fetcher.h" +#include "base/command_line.h" +#include "base/threading/thread_task_runner_handle.h" +#include "components/network_session_configurator/common/network_switches.h" #include "content/browser/appcache/appcache_update_request_base.h" +#include "net/base/load_flags.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" -#include "net/url_request/url_request_context.h" namespace content { @@ -28,10 +31,8 @@ job_(job), fetch_type_(fetch_type), retry_503_attempts_(0), - buffer_(new net::IOBuffer(buffer_size)), - request_(UpdateRequestBase::Create(job->service_->request_context(), - url, - this)), + request_( + UpdateRequestBase::Create(job->service_, url, buffer_size, this)), result_(AppCacheUpdateJob::UPDATE_OK), redirect_response_code_(-1), buffer_size_(buffer_size) {} @@ -87,13 +88,10 @@ // requested on the whatwg list. // See http://code.google.com/p/chromium/issues/detail?id=69594 // TODO(michaeln): Consider doing this for cross-origin HTTP too. - const net::HttpNetworkSession::Params* session_params = - request_->GetRequestContext()->GetNetworkSessionParams(); - bool ignore_cert_errors = - session_params && session_params->ignore_certificate_errors; if ((net::IsCertStatusError( request_->GetResponseInfo().ssl_info.cert_status) && - !ignore_cert_errors) || + !base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kIgnoreCertificateErrors)) || (url_.GetOrigin() != job_->manifest_url_.GetOrigin() && request_->GetResponseHeaders()->HasHeaderValue("cache-control", "no-store"))) { @@ -120,29 +118,19 @@ } } -void AppCacheUpdateJob::URLFetcher::OnReadCompleted(int bytes_read) { +void AppCacheUpdateJob::URLFetcher::OnReadCompleted(net::IOBuffer* buffer, + int bytes_read) { DCHECK(request_); DCHECK_NE(net::ERR_IO_PENDING, bytes_read); - bool data_consumed = true; - if (bytes_read > 0) { - job_->MadeProgress(); - data_consumed = ConsumeResponseData(bytes_read); - if (data_consumed) { - while (true) { - bytes_read = request_->Read(buffer_.get(), buffer_size_); - if (bytes_read <= 0) - break; - data_consumed = ConsumeResponseData(bytes_read); - if (!data_consumed) - break; - } - } + + if (bytes_read <= 0) { + OnResponseCompleted(bytes_read); + return; } - if (data_consumed && bytes_read != net::ERR_IO_PENDING) { - DCHECK_EQ(AppCacheUpdateJob::UPDATE_OK, result_); - OnResponseCompleted(bytes_read); - } + job_->MadeProgress(); + if (ConsumeResponseData(buffer, bytes_read)) + request_->Read(); } void AppCacheUpdateJob::URLFetcher::AddConditionalHeaders( @@ -188,26 +176,25 @@ state == AppCacheUpdateJob::COMPLETED) { return; } - int bytes_read = request_->Read(buffer_.get(), buffer_size_); - if (bytes_read != net::ERR_IO_PENDING) - OnReadCompleted(bytes_read); + request_->Read(); } // Returns false if response data is processed asynchronously, in which // case ReadResponseData will be invoked when it is safe to continue // reading more response data from the request. -bool AppCacheUpdateJob::URLFetcher::ConsumeResponseData(int bytes_read) { +bool AppCacheUpdateJob::URLFetcher::ConsumeResponseData(net::IOBuffer* buffer, + int bytes_read) { DCHECK_GT(bytes_read, 0); switch (fetch_type_) { case MANIFEST_FETCH: case MANIFEST_REFETCH: - manifest_data_.append(buffer_->data(), bytes_read); + manifest_data_.append(buffer->data(), bytes_read); break; case URL_FETCH: case MASTER_ENTRY_FETCH: DCHECK(response_writer_.get()); response_writer_->WriteData( - buffer_.get(), bytes_read, + buffer, bytes_read, base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this))); return false; // wait for async write completion to continue reading default: @@ -217,8 +204,11 @@ } void AppCacheUpdateJob::URLFetcher::OnResponseCompleted(int net_error) { - if (net_error == net::OK) + if (net_error == net::OK) { job_->MadeProgress(); + } else if (result_ == AppCacheUpdateJob::UPDATE_OK) { + result_ = AppCacheUpdateJob::NETWORK_ERROR; + } // Retry for 503s where retry-after is 0. if (net_error == net::OK && request_->GetResponseCode() == 503 && @@ -254,7 +244,7 @@ ++retry_503_attempts_; result_ = AppCacheUpdateJob::UPDATE_OK; request_ = - UpdateRequestBase::Create(job_->service_->request_context(), url_, this); + UpdateRequestBase::Create(job_->service_, url_, buffer_size_, this); Start(); return true; }
diff --git a/content/browser/appcache/appcache_update_url_fetcher.h b/content/browser/appcache/appcache_update_url_fetcher.h index fce8910..a3d3d93 100644 --- a/content/browser/appcache/appcache_update_url_fetcher.h +++ b/content/browser/appcache/appcache_update_url_fetcher.h
@@ -51,12 +51,12 @@ private: void OnReceivedRedirect(const net::RedirectInfo& redirect_info); void OnResponseStarted(int net_error); - void OnReadCompleted(int bytes_read); + void OnReadCompleted(net::IOBuffer* buffer, int bytes_read); void AddConditionalHeaders(const net::HttpResponseHeaders* headers); void OnWriteComplete(int result); void ReadResponseData(); - bool ConsumeResponseData(int bytes_read); + bool ConsumeResponseData(net::IOBuffer* buffer, int bytes_read); void OnResponseCompleted(int net_error); bool MaybeRetryRequest(); @@ -67,7 +67,6 @@ AppCacheUpdateJob* job_; FetchType fetch_type_; int retry_503_attempts_; - scoped_refptr<net::IOBuffer> buffer_; std::unique_ptr<UpdateRequestBase> request_; AppCacheEntry existing_entry_; scoped_refptr<net::HttpResponseHeaders> existing_response_headers_;
diff --git a/content/browser/appcache/appcache_update_url_loader_request.cc b/content/browser/appcache/appcache_update_url_loader_request.cc index 3acfd1a..284e1cd 100644 --- a/content/browser/appcache/appcache_update_url_loader_request.cc +++ b/content/browser/appcache/appcache_update_url_loader_request.cc
@@ -3,7 +3,9 @@ // found in the LICENSE file. #include "content/browser/appcache/appcache_update_url_loader_request.h" + #include "content/browser/appcache/appcache_update_url_fetcher.h" +#include "net/http/http_response_info.h" #include "net/url_request/url_request_context.h" namespace content { @@ -11,79 +13,78 @@ AppCacheUpdateJob::UpdateURLLoaderRequest::~UpdateURLLoaderRequest() {} void AppCacheUpdateJob::UpdateURLLoaderRequest::Start() { - NOTIMPLEMENTED(); + mojom::URLLoaderClientPtr client; + client_binding_.Bind(mojo::MakeRequest(&client)); + + loader_factory_getter_->GetNetworkFactory()->get()->CreateLoaderAndStart( + mojo::MakeRequest(&url_loader_), -1, -1, mojom::kURLLoadOptionNone, + request_, std::move(client), + net::MutableNetworkTrafficAnnotationTag(GetTrafficAnnotation())); } void AppCacheUpdateJob::UpdateURLLoaderRequest::SetExtraRequestHeaders( const net::HttpRequestHeaders& headers) { - NOTIMPLEMENTED(); + request_.headers = headers.ToString(); } GURL AppCacheUpdateJob::UpdateURLLoaderRequest::GetURL() const { - NOTIMPLEMENTED(); - return GURL(); -} - -GURL AppCacheUpdateJob::UpdateURLLoaderRequest::GetOriginalURL() const { - NOTIMPLEMENTED(); - return GURL(); + return request_.url; } void AppCacheUpdateJob::UpdateURLLoaderRequest::SetLoadFlags(int flags) { - NOTIMPLEMENTED(); + request_.load_flags = flags; } int AppCacheUpdateJob::UpdateURLLoaderRequest::GetLoadFlags() const { - NOTIMPLEMENTED(); - return 0; + return request_.load_flags; } std::string AppCacheUpdateJob::UpdateURLLoaderRequest::GetMimeType() const { - NOTIMPLEMENTED(); - return std::string(); + return response_->mime_type; } void AppCacheUpdateJob::UpdateURLLoaderRequest::SetFirstPartyForCookies( const GURL& first_party_for_cookies) { - NOTIMPLEMENTED(); + request_.first_party_for_cookies = first_party_for_cookies; } void AppCacheUpdateJob::UpdateURLLoaderRequest::SetInitiator( const base::Optional<url::Origin>& initiator) { - NOTIMPLEMENTED(); + request_.request_initiator = initiator; } net::HttpResponseHeaders* AppCacheUpdateJob::UpdateURLLoaderRequest::GetResponseHeaders() const { - NOTIMPLEMENTED(); - return nullptr; + return response_->headers.get(); } int AppCacheUpdateJob::UpdateURLLoaderRequest::GetResponseCode() const { - NOTIMPLEMENTED(); + if (response_->headers) + return response_->headers->response_code(); return 0; } -net::HttpResponseInfo +const net::HttpResponseInfo& AppCacheUpdateJob::UpdateURLLoaderRequest::GetResponseInfo() const { - NOTIMPLEMENTED(); - return net::HttpResponseInfo(); + return *http_response_info_; } -const net::URLRequestContext* -AppCacheUpdateJob::UpdateURLLoaderRequest::GetRequestContext() const { - NOTIMPLEMENTED(); - return nullptr; -} +void AppCacheUpdateJob::UpdateURLLoaderRequest::Read() { + DCHECK(!read_requested_); -int AppCacheUpdateJob::UpdateURLLoaderRequest::Read(net::IOBuffer* buf, - int max_bytes) { - NOTIMPLEMENTED(); - return 0; + read_requested_ = true; + // Initiate a read from the pipe if we have not done so. + MaybeStartReading(); } int AppCacheUpdateJob::UpdateURLLoaderRequest::Cancel() { - NOTIMPLEMENTED(); + client_binding_.Close(); + url_loader_ = nullptr; + handle_watcher_.Cancel(); + handle_.reset(); + response_.reset(nullptr); + http_response_info_.reset(nullptr); + read_requested_ = false; return 0; } @@ -91,13 +92,32 @@ const ResourceResponseHead& response_head, const base::Optional<net::SSLInfo>& ssl_info, mojom::DownloadedTempFilePtr downloaded_file) { - NOTIMPLEMENTED(); + response_.reset(new ResourceResponseHead()); + *response_ = response_head; + + // TODO(ananta/michaeln) + // Populate other fields in the HttpResponseInfo class. It would be good to + // have a helper function which populates the HttpResponseInfo structure from + // the ResourceResponseHead structure. + http_response_info_.reset(new net::HttpResponseInfo()); + if (ssl_info.has_value()) + http_response_info_->ssl_info = *ssl_info; + http_response_info_->headers = response_head.headers; + http_response_info_->was_fetched_via_spdy = + response_head.was_fetched_via_spdy; + http_response_info_->was_alpn_negotiated = response_head.was_alpn_negotiated; + http_response_info_->alpn_negotiated_protocol = + response_head.alpn_negotiated_protocol; + http_response_info_->connection_info = response_head.connection_info; + http_response_info_->socket_address = response_head.socket_address; + fetcher_->OnResponseStarted(net::OK); } void AppCacheUpdateJob::UpdateURLLoaderRequest::OnReceiveRedirect( const net::RedirectInfo& redirect_info, const ResourceResponseHead& response_head) { - NOTIMPLEMENTED(); + *response_ = response_head; + fetcher_->OnReceivedRedirect(redirect_info); } void AppCacheUpdateJob::UpdateURLLoaderRequest::OnDataDownloaded( @@ -115,7 +135,6 @@ void AppCacheUpdateJob::UpdateURLLoaderRequest::OnReceiveCachedMetadata( const std::vector<uint8_t>& data) { - NOTIMPLEMENTED(); } void AppCacheUpdateJob::UpdateURLLoaderRequest::OnTransferSizeUpdated( @@ -125,17 +144,89 @@ void AppCacheUpdateJob::UpdateURLLoaderRequest::OnStartLoadingResponseBody( mojo::ScopedDataPipeConsumerHandle body) { - NOTIMPLEMENTED(); + handle_ = std::move(body); + + handle_watcher_.Watch( + handle_.get(), MOJO_HANDLE_SIGNAL_READABLE, + base::Bind(&AppCacheUpdateJob::UpdateURLLoaderRequest::StartReading, + base::Unretained(this))); + + // Initiate a read from the pipe if we have a pending Read() request. + MaybeStartReading(); } void AppCacheUpdateJob::UpdateURLLoaderRequest::OnComplete( const ResourceRequestCompletionStatus& status) { - NOTIMPLEMENTED(); + response_status_ = status; + // We inform the URLFetcher about a failure only here. For the success case + // OnResponseCompleted() is invoked by URLFetcher::OnReadCompleted(). + if (status.error_code != net::OK) + fetcher_->OnResponseCompleted(status.error_code); } AppCacheUpdateJob::UpdateURLLoaderRequest::UpdateURLLoaderRequest( - net::URLRequestContext* request_context, + URLLoaderFactoryGetter* loader_factory_getter, const GURL& url, - URLFetcher* fetcher) {} + int buffer_size, + URLFetcher* fetcher) + : fetcher_(fetcher), + loader_factory_getter_(loader_factory_getter), + client_binding_(this), + buffer_size_(buffer_size), + handle_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL), + read_requested_(false) { + request_.url = url; + request_.method = "GET"; +} + +void AppCacheUpdateJob::UpdateURLLoaderRequest::StartReading( + MojoResult unused) { + DCHECK(read_requested_); + + // Get the handle_ from a previous read operation if we have one. + if (pending_read_) { + DCHECK(pending_read_->IsComplete()); + handle_ = pending_read_->ReleaseHandle(); + pending_read_ = nullptr; + } + + uint32_t available = 0; + MojoResult result = + MojoToNetPendingBuffer::BeginRead(&handle_, &pending_read_, &available); + DCHECK_NE(result, MOJO_RESULT_BUSY); + + if (result == MOJO_RESULT_SHOULD_WAIT) { + handle_watcher_.ArmOrNotify(); + return; + } + + read_requested_ = false; + + if (result == MOJO_RESULT_FAILED_PRECONDITION) { + DCHECK_EQ(response_status_.error_code, net::OK); + fetcher_->OnReadCompleted(nullptr, 0); + return; + } + + if (result != MOJO_RESULT_OK) { + fetcher_->OnResponseCompleted(net::ERR_FAILED); + return; + } + + int bytes_to_be_read = std::min<int>(buffer_size_, available); + + scoped_refptr<MojoToNetIOBuffer> buffer = + new MojoToNetIOBuffer(pending_read_.get(), bytes_to_be_read); + + fetcher_->OnReadCompleted(buffer.get(), bytes_to_be_read); +} + +void AppCacheUpdateJob::UpdateURLLoaderRequest::MaybeStartReading() { + if (!read_requested_) + return; + + if (handle_watcher_.IsWatching()) + handle_watcher_.ArmOrNotify(); +} } // namespace content
diff --git a/content/browser/appcache/appcache_update_url_loader_request.h b/content/browser/appcache/appcache_update_url_loader_request.h index bb6df46..50f81506 100644 --- a/content/browser/appcache/appcache_update_url_loader_request.h +++ b/content/browser/appcache/appcache_update_url_loader_request.h
@@ -7,16 +7,30 @@ #include <stddef.h> #include <stdint.h> +#include <memory> #include "base/macros.h" #include "content/browser/appcache/appcache_update_request_base.h" +#include "content/common/net_adapters.h" +#include "content/public/common/resource_request.h" #include "content/public/common/url_loader.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/system/simple_watcher.h" +#include "net/base/io_buffer.h" + +namespace net { +class HttpResponseInfo; +} namespace content { +class URLLoaderFactoryGetter; +struct ResourceRequest; +struct ResourceResponseHead; + // URLLoaderClient subclass for the UpdateRequestBase class. Provides // functionality to update the AppCache using functionality provided by the -// network URL loader +// network URL loader. class AppCacheUpdateJob::UpdateURLLoaderRequest : public AppCacheUpdateJob::UpdateRequestBase, public mojom::URLLoaderClient { @@ -27,7 +41,6 @@ void Start() override; void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override; GURL GetURL() const override; - GURL GetOriginalURL() const override; void SetLoadFlags(int flags) override; int GetLoadFlags() const override; std::string GetMimeType() const override; @@ -35,9 +48,8 @@ void SetInitiator(const base::Optional<url::Origin>& initiator) override; net::HttpResponseHeaders* GetResponseHeaders() const override; int GetResponseCode() const override; - net::HttpResponseInfo GetResponseInfo() const override; - const net::URLRequestContext* GetRequestContext() const override; - int Read(net::IOBuffer* buf, int max_bytes) override; + const net::HttpResponseInfo& GetResponseInfo() const override; + void Read() override; int Cancel() override; // mojom::URLLoaderClient implementation. @@ -58,13 +70,51 @@ void OnComplete(const ResourceRequestCompletionStatus& status) override; private: - UpdateURLLoaderRequest(net::URLRequestContext* request_context, + UpdateURLLoaderRequest(URLLoaderFactoryGetter* loader_factory_getter, const GURL& url, + int buffer_size, URLFetcher* fetcher); + // Helper function to initiate an asynchronous read on the data pipe. + void StartReading(MojoResult unused); + + // Helper function to setup the data pipe watcher to start reading from + // the pipe. We need to do this when the data pipe is available and there is + // a pending read. + void MaybeStartReading(); + friend class AppCacheUpdateJob::UpdateRequestBase; URLFetcher* fetcher_; + // Used to retrieve the network URLLoader interface to issue network + // requests + scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_; + + ResourceRequest request_; + std::unique_ptr<ResourceResponseHead> response_; + ResourceRequestCompletionStatus response_status_; + // Response details. + std::unique_ptr<net::HttpResponseInfo> http_response_info_; + // Binds the URLLoaderClient interface to the channel. + mojo::Binding<mojom::URLLoaderClient> client_binding_; + // The network URL loader. + mojom::URLLoaderPtr url_loader_; + // Caller buffer size. + int buffer_size_; + // The mojo data pipe. + mojo::ScopedDataPipeConsumerHandle handle_; + // Used to watch the data pipe to initiate reads. + mojo::SimpleWatcher handle_watcher_; + // Set to true when the caller issues a read request. We set it to false in + // the StartReading() function when the mojo BeginReadData API returns a + // value indicating one of the following: + // 1. Data is available. + // 2. End of data has been reached. + // 3. Error. + // Please look at the StartReading() function for details. + bool read_requested_; + // Adapter for transferring data from a mojo data pipe to net. + scoped_refptr<MojoToNetPendingBuffer> pending_read_; DISALLOW_COPY_AND_ASSIGN(UpdateURLLoaderRequest); };
diff --git a/content/browser/appcache/appcache_update_url_request.cc b/content/browser/appcache/appcache_update_url_request.cc index 45b489cf..4fdfed0 100644 --- a/content/browser/appcache/appcache_update_url_request.cc +++ b/content/browser/appcache/appcache_update_url_request.cc
@@ -3,43 +3,13 @@ // found in the LICENSE file. #include "content/browser/appcache/appcache_update_url_request.h" + +#include "base/threading/thread_task_runner_handle.h" #include "content/browser/appcache/appcache_update_url_fetcher.h" #include "net/url_request/url_request_context.h" namespace content { -namespace { -constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation = - net::DefineNetworkTrafficAnnotation("appcache_update_job", R"( - semantics { - sender: "HTML5 AppCache System" - description: - "Web pages can include a link to a manifest file which lists " - "resources to be cached for offline access. The AppCache system" - "retrieves those resources in the background." - trigger: - "User visits a web page containing a <html manifest=manifestUrl> " - "tag, or navigates to a document retrieved from an existing appcache " - "and some resource should be updated." - data: "None" - destination: WEBSITE - } - policy { - cookies_allowed: YES - cookies_store: "user" - setting: - "Users can control this feature via the 'Cookies' setting under " - "'Privacy, Content settings'. If cookies are disabled for a single " - "site, appcaches are disabled for the site only. If they are totally " - "disabled, all appcache requests will be stopped." - chrome_policy { - DefaultCookiesSetting { - DefaultCookiesSetting: 2 - } - } - })"); -} - AppCacheUpdateJob::UpdateURLRequest::~UpdateURLRequest() { // To defend against URLRequest calling delegate methods during // destruction, we test for a !request_ in those methods. @@ -59,10 +29,6 @@ return request_->url(); } -GURL AppCacheUpdateJob::UpdateURLRequest::GetOriginalURL() const { - return request_->original_url(); -} - void AppCacheUpdateJob::UpdateURLRequest::SetLoadFlags(int flags) { request_->SetLoadFlags(flags); } @@ -96,19 +62,19 @@ return request_->GetResponseCode(); } -net::HttpResponseInfo AppCacheUpdateJob::UpdateURLRequest::GetResponseInfo() - const { +const net::HttpResponseInfo& +AppCacheUpdateJob::UpdateURLRequest::GetResponseInfo() const { return request_->response_info(); } -const net::URLRequestContext* -AppCacheUpdateJob::UpdateURLRequest::GetRequestContext() const { - return request_->context(); -} - -int AppCacheUpdateJob::UpdateURLRequest::Read(net::IOBuffer* buf, - int max_bytes) { - return request_->Read(buf, max_bytes); +void AppCacheUpdateJob::UpdateURLRequest::Read() { + int bytes_read = request_->Read(buffer_.get(), buffer_size_); + if (bytes_read != net::ERR_IO_PENDING) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&AppCacheUpdateJob::UpdateURLRequest::OnReadCompleted, + weak_factory_.GetWeakPtr(), request_.get(), bytes_read)); + } } int AppCacheUpdateJob::UpdateURLRequest::Cancel() { @@ -140,17 +106,21 @@ if (!request_) return; DCHECK_EQ(request_.get(), request); - fetcher_->OnReadCompleted(bytes_read); + fetcher_->OnReadCompleted(buffer_.get(), bytes_read); } AppCacheUpdateJob::UpdateURLRequest::UpdateURLRequest( net::URLRequestContext* request_context, const GURL& url, + int buffer_size, URLFetcher* fetcher) : request_(request_context->CreateRequest(url, net::DEFAULT_PRIORITY, this, - kTrafficAnnotation)), - fetcher_(fetcher) {} + GetTrafficAnnotation())), + fetcher_(fetcher), + buffer_(new net::IOBuffer(buffer_size)), + buffer_size_(buffer_size), + weak_factory_(this) {} } // namespace content
diff --git a/content/browser/appcache/appcache_update_url_request.h b/content/browser/appcache/appcache_update_url_request.h index 43e46ec..cba0cbd94 100644 --- a/content/browser/appcache/appcache_update_url_request.h +++ b/content/browser/appcache/appcache_update_url_request.h
@@ -9,7 +9,9 @@ #include <stdint.h> #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "content/browser/appcache/appcache_update_request_base.h" +#include "net/base/io_buffer.h" #include "net/url_request/url_request.h" namespace content { @@ -26,7 +28,6 @@ void Start() override; void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override; GURL GetURL() const override; - GURL GetOriginalURL() const override; void SetLoadFlags(int flags) override; int GetLoadFlags() const override; std::string GetMimeType() const override; @@ -34,9 +35,8 @@ void SetInitiator(const base::Optional<url::Origin>& initiator) override; net::HttpResponseHeaders* GetResponseHeaders() const override; int GetResponseCode() const override; - net::HttpResponseInfo GetResponseInfo() const override; - const net::URLRequestContext* GetRequestContext() const override; - int Read(net::IOBuffer* buf, int max_bytes) override; + const net::HttpResponseInfo& GetResponseInfo() const override; + void Read() override; int Cancel() override; // URLRequest::Delegate overrides @@ -49,12 +49,17 @@ private: UpdateURLRequest(net::URLRequestContext* request_context, const GURL& url, + int buffer_size, URLFetcher* fetcher); friend class AppCacheUpdateJob::UpdateRequestBase; std::unique_ptr<net::URLRequest> request_; URLFetcher* fetcher_; + scoped_refptr<net::IOBuffer> buffer_; + int buffer_size_; + + base::WeakPtrFactory<AppCacheUpdateJob::UpdateURLRequest> weak_factory_; DISALLOW_COPY_AND_ASSIGN(UpdateURLRequest); };
diff --git a/content/browser/background_fetch/background_fetch_context.cc b/content/browser/background_fetch/background_fetch_context.cc index 45d3d15..675bd895 100644 --- a/content/browser/background_fetch/background_fetch_context.cc +++ b/content/browser/background_fetch/background_fetch_context.cc
@@ -94,7 +94,7 @@ // Create the BackgroundFetchRegistration the renderer process will receive, // which enables it to resolve the promise telling the developer it worked. BackgroundFetchRegistration registration; - registration.tag = registration_id.tag(); + registration.id = registration_id.id(); registration.icons = options.icons; registration.title = options.title; registration.total_download_size = options.total_download_size; @@ -104,25 +104,25 @@ } std::vector<std::string> -BackgroundFetchContext::GetActiveTagsForServiceWorkerRegistration( +BackgroundFetchContext::GetActiveIdsForServiceWorkerRegistration( int64_t service_worker_registration_id, const url::Origin& origin) const { DCHECK_CURRENTLY_ON(BrowserThread::IO); - std::vector<std::string> tags; + std::vector<std::string> ids; for (const auto& pair : active_fetches_) { const BackgroundFetchRegistrationId& registration_id = pair.second->registration_id(); - // Only return the tags when the origin and SW registration id match. + // Only return the ids when the origin and SW registration id match. if (registration_id.origin() == origin && registration_id.service_worker_registration_id() == service_worker_registration_id) { - tags.push_back(pair.second->registration_id().tag()); + ids.push_back(pair.second->registration_id().id()); } } - return tags; + return ids; } BackgroundFetchJobController* BackgroundFetchContext::GetActiveFetch(
diff --git a/content/browser/background_fetch/background_fetch_context.h b/content/browser/background_fetch/background_fetch_context.h index a625340..be613c4 100644 --- a/content/browser/background_fetch/background_fetch_context.h +++ b/content/browser/background_fetch/background_fetch_context.h
@@ -64,9 +64,9 @@ const BackgroundFetchOptions& options, blink::mojom::BackgroundFetchService::FetchCallback callback); - // Returns a vector with the tags of the active fetches for the given |origin| + // Returns a vector with the ids of the active fetches for the given |origin| // and |service_worker_registration_id|. - std::vector<std::string> GetActiveTagsForServiceWorkerRegistration( + std::vector<std::string> GetActiveIdsForServiceWorkerRegistration( int64_t service_worker_registration_id, const url::Origin& origin) const;
diff --git a/content/browser/background_fetch/background_fetch_data_manager.cc b/content/browser/background_fetch/background_fetch_data_manager.cc index 61779b4..8aaed60 100644 --- a/content/browser/background_fetch/background_fetch_data_manager.cc +++ b/content/browser/background_fetch/background_fetch_data_manager.cc
@@ -150,7 +150,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (registrations_.find(registration_id) != registrations_.end()) { - std::move(callback).Run(blink::mojom::BackgroundFetchError::DUPLICATED_TAG); + std::move(callback).Run(blink::mojom::BackgroundFetchError::DUPLICATED_ID); return; } @@ -293,7 +293,7 @@ auto iter = registrations_.find(registration_id); if (iter == registrations_.end()) { - std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_TAG); + std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_ID); return; }
diff --git a/content/browser/background_fetch/background_fetch_data_manager_unittest.cc b/content/browser/background_fetch/background_fetch_data_manager_unittest.cc index 9a9e71a..f531f09 100644 --- a/content/browser/background_fetch/background_fetch_data_manager_unittest.cc +++ b/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
@@ -18,7 +18,7 @@ namespace content { namespace { -const char kExampleTag[] = "my-example-tag"; +const char kExampleId[] = "my-example-id"; } // namespace @@ -87,7 +87,7 @@ // registration that's already known to the system. BackgroundFetchRegistrationId registration_id; - ASSERT_TRUE(CreateRegistrationId(kExampleTag, ®istration_id)); + ASSERT_TRUE(CreateRegistrationId(kExampleId, ®istration_id)); std::vector<ServiceWorkerFetchRequest> requests; BackgroundFetchOptions options; @@ -96,7 +96,7 @@ // Deleting the not-yet-created registration should fail. ASSERT_NO_FATAL_FAILURE(DeleteRegistration(registration_id, &error)); - EXPECT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_TAG); + EXPECT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ID); // Creating the initial registration should succeed. ASSERT_NO_FATAL_FAILURE( @@ -106,7 +106,7 @@ // Attempting to create it again should yield an error. ASSERT_NO_FATAL_FAILURE( CreateRegistration(registration_id, requests, options, &error)); - EXPECT_EQ(error, blink::mojom::BackgroundFetchError::DUPLICATED_TAG); + EXPECT_EQ(error, blink::mojom::BackgroundFetchError::DUPLICATED_ID); // Deleting the registration should succeed. ASSERT_NO_FATAL_FAILURE(DeleteRegistration(registration_id, &error));
diff --git a/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc b/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc index e5d4b165..7542a75 100644 --- a/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc +++ b/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc
@@ -20,10 +20,10 @@ ~BackgroundFetchEmbeddedWorkerTestHelper() = default; void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent( - const std::string& tag, + const std::string& id, mojom::ServiceWorkerEventDispatcher:: DispatchBackgroundFetchAbortEventCallback callback) { - last_tag_ = tag; + last_id_ = id; if (fail_abort_event_) { std::move(callback).Run(SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED, @@ -37,11 +37,11 @@ } void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchClickEvent( - const std::string& tag, + const std::string& id, mojom::BackgroundFetchState state, mojom::ServiceWorkerEventDispatcher:: DispatchBackgroundFetchClickEventCallback callback) { - last_tag_ = tag; + last_id_ = id; last_state_ = state; if (fail_click_event_) { @@ -56,11 +56,11 @@ } void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchFailEvent( - const std::string& tag, + const std::string& id, const std::vector<BackgroundFetchSettledFetch>& fetches, mojom::ServiceWorkerEventDispatcher:: DispatchBackgroundFetchFailEventCallback callback) { - last_tag_ = tag; + last_id_ = id; last_fetches_ = fetches; if (fail_fetch_fail_event_) { @@ -75,11 +75,11 @@ } void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchedEvent( - const std::string& tag, + const std::string& id, const std::vector<BackgroundFetchSettledFetch>& fetches, mojom::ServiceWorkerEventDispatcher::DispatchBackgroundFetchedEventCallback callback) { - last_tag_ = tag; + last_id_ = id; last_fetches_ = fetches; if (fail_fetched_event_) {
diff --git a/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h b/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h index 07abed7..4192f4b 100644 --- a/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h +++ b/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h
@@ -50,7 +50,7 @@ fetched_event_closure_ = closure; } - const base::Optional<std::string>& last_tag() const { return last_tag_; } + const base::Optional<std::string>& last_id() const { return last_id_; } const base::Optional<mojom::BackgroundFetchState>& last_state() const { return last_state_; } @@ -62,21 +62,21 @@ protected: // EmbeddedWorkerTestHelper overrides: void OnBackgroundFetchAbortEvent( - const std::string& tag, + const std::string& id, mojom::ServiceWorkerEventDispatcher:: DispatchBackgroundFetchAbortEventCallback callback) override; void OnBackgroundFetchClickEvent( - const std::string& tag, + const std::string& id, mojom::BackgroundFetchState state, mojom::ServiceWorkerEventDispatcher:: DispatchBackgroundFetchClickEventCallback callback) override; void OnBackgroundFetchFailEvent( - const std::string& tag, + const std::string& id, const std::vector<BackgroundFetchSettledFetch>& fetches, mojom::ServiceWorkerEventDispatcher:: DispatchBackgroundFetchFailEventCallback callback) override; void OnBackgroundFetchedEvent( - const std::string& tag, + const std::string& id, const std::vector<BackgroundFetchSettledFetch>& fetches, mojom::ServiceWorkerEventDispatcher:: DispatchBackgroundFetchedEventCallback callback) override; @@ -92,7 +92,7 @@ base::Closure fetch_fail_event_closure_; base::Closure fetched_event_closure_; - base::Optional<std::string> last_tag_; + base::Optional<std::string> last_id_; base::Optional<mojom::BackgroundFetchState> last_state_; base::Optional<std::vector<BackgroundFetchSettledFetch>> last_fetches_;
diff --git a/content/browser/background_fetch/background_fetch_event_dispatcher.cc b/content/browser/background_fetch/background_fetch_event_dispatcher.cc index 1de7fef..3dafa3d7 100644 --- a/content/browser/background_fetch/background_fetch_event_dispatcher.cc +++ b/content/browser/background_fetch/background_fetch_event_dispatcher.cc
@@ -83,16 +83,16 @@ std::move(finished_closure), base::Bind( &BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchAbortEvent, - registration_id.tag())); + registration_id.id())); } void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchAbortEvent( - const std::string& tag, + const std::string& id, scoped_refptr<ServiceWorkerVersion> service_worker_version, int request_id) { DCHECK(service_worker_version); service_worker_version->event_dispatcher()->DispatchBackgroundFetchAbortEvent( - tag, service_worker_version->CreateSimpleEventCallback(request_id)); + id, service_worker_version->CreateSimpleEventCallback(request_id)); } void BackgroundFetchEventDispatcher::DispatchBackgroundFetchClickEvent( @@ -105,18 +105,17 @@ std::move(finished_closure), base::Bind( &BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchClickEvent, - registration_id.tag(), state)); + registration_id.id(), state)); } void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchClickEvent( - const std::string& tag, + const std::string& id, mojom::BackgroundFetchState state, scoped_refptr<ServiceWorkerVersion> service_worker_version, int request_id) { DCHECK(service_worker_version); service_worker_version->event_dispatcher()->DispatchBackgroundFetchClickEvent( - tag, state, - service_worker_version->CreateSimpleEventCallback(request_id)); + id, state, service_worker_version->CreateSimpleEventCallback(request_id)); } void BackgroundFetchEventDispatcher::DispatchBackgroundFetchFailEvent( @@ -129,17 +128,17 @@ std::move(finished_closure), base::Bind( &BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchFailEvent, - registration_id.tag(), fetches)); + registration_id.id(), fetches)); } void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchFailEvent( - const std::string& tag, + const std::string& id, const std::vector<BackgroundFetchSettledFetch>& fetches, scoped_refptr<ServiceWorkerVersion> service_worker_version, int request_id) { DCHECK(service_worker_version); service_worker_version->event_dispatcher()->DispatchBackgroundFetchFailEvent( - tag, fetches, + id, fetches, service_worker_version->CreateSimpleEventCallback(request_id)); } @@ -153,17 +152,17 @@ std::move(finished_closure), base::Bind( &BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchedEvent, - registration_id.tag(), fetches)); + registration_id.id(), fetches)); } void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchedEvent( - const std::string& tag, + const std::string& id, const std::vector<BackgroundFetchSettledFetch>& fetches, scoped_refptr<ServiceWorkerVersion> service_worker_version, int request_id) { DCHECK(service_worker_version); service_worker_version->event_dispatcher()->DispatchBackgroundFetchedEvent( - tag, fetches, + id, fetches, service_worker_version->CreateSimpleEventCallback(request_id)); }
diff --git a/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc b/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc index 222dd93..b7c2128c 100644 --- a/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc +++ b/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc
@@ -19,8 +19,8 @@ namespace content { namespace { -const char kExampleTag[] = "my-tag"; -const char kExampleTag2[] = "my-second-tag"; +const char kExampleId[] = "my-id"; +const char kExampleId2[] = "my-second-id"; class BackgroundFetchEventDispatcherTest : public BackgroundFetchTestBase { public: @@ -37,7 +37,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchInvalidRegistration) { BackgroundFetchRegistrationId invalid_registration_id( - 9042 /* random invalid id */, origin(), kExampleTag); + 9042 /* random invalid id */, origin(), kExampleId); base::RunLoop run_loop; event_dispatcher_.DispatchBackgroundFetchAbortEvent(invalid_registration_id, @@ -55,7 +55,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchAbortEvent) { BackgroundFetchRegistrationId registration_id; - ASSERT_TRUE(CreateRegistrationId(kExampleTag, ®istration_id)); + ASSERT_TRUE(CreateRegistrationId(kExampleId, ®istration_id)); { base::RunLoop run_loop; @@ -65,8 +65,8 @@ run_loop.Run(); } - ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value()); - EXPECT_EQ(kExampleTag, embedded_worker_test_helper()->last_tag().value()); + ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value()); + EXPECT_EQ(kExampleId, embedded_worker_test_helper()->last_id().value()); histogram_tester_.ExpectUniqueSample( "BackgroundFetch.EventDispatchResult.AbortEvent", @@ -76,7 +76,7 @@ BackgroundFetchRegistrationId second_registration_id( registration_id.service_worker_registration_id(), - registration_id.origin(), kExampleTag2); + registration_id.origin(), kExampleId2); { base::RunLoop run_loop; @@ -86,8 +86,8 @@ run_loop.Run(); } - ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value()); - EXPECT_EQ(kExampleTag2, embedded_worker_test_helper()->last_tag().value()); + ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value()); + EXPECT_EQ(kExampleId2, embedded_worker_test_helper()->last_id().value()); histogram_tester_.ExpectBucketCount( "BackgroundFetch.EventDispatchResult.AbortEvent", @@ -102,7 +102,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchClickEvent) { BackgroundFetchRegistrationId registration_id; - ASSERT_TRUE(CreateRegistrationId(kExampleTag, ®istration_id)); + ASSERT_TRUE(CreateRegistrationId(kExampleId, ®istration_id)); { base::RunLoop run_loop; @@ -113,8 +113,8 @@ run_loop.Run(); } - ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value()); - EXPECT_EQ(kExampleTag, embedded_worker_test_helper()->last_tag().value()); + ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value()); + EXPECT_EQ(kExampleId, embedded_worker_test_helper()->last_id().value()); ASSERT_TRUE(embedded_worker_test_helper()->last_state().has_value()); EXPECT_EQ(mojom::BackgroundFetchState::PENDING, @@ -128,7 +128,7 @@ BackgroundFetchRegistrationId second_registration_id( registration_id.service_worker_registration_id(), - registration_id.origin(), kExampleTag2); + registration_id.origin(), kExampleId2); { base::RunLoop run_loop; @@ -139,8 +139,8 @@ run_loop.Run(); } - ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value()); - EXPECT_EQ(kExampleTag2, embedded_worker_test_helper()->last_tag().value()); + ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value()); + EXPECT_EQ(kExampleId2, embedded_worker_test_helper()->last_id().value()); ASSERT_TRUE(embedded_worker_test_helper()->last_state().has_value()); EXPECT_EQ(mojom::BackgroundFetchState::SUCCEEDED, @@ -159,7 +159,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFailEvent) { BackgroundFetchRegistrationId registration_id; - ASSERT_TRUE(CreateRegistrationId(kExampleTag, ®istration_id)); + ASSERT_TRUE(CreateRegistrationId(kExampleId, ®istration_id)); std::vector<BackgroundFetchSettledFetch> fetches; fetches.push_back(BackgroundFetchSettledFetch()); @@ -172,8 +172,8 @@ run_loop.Run(); } - ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value()); - EXPECT_EQ(kExampleTag, embedded_worker_test_helper()->last_tag().value()); + ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value()); + EXPECT_EQ(kExampleId, embedded_worker_test_helper()->last_id().value()); ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value()); EXPECT_EQ(fetches.size(), @@ -189,7 +189,7 @@ BackgroundFetchRegistrationId second_registration_id( registration_id.service_worker_registration_id(), - registration_id.origin(), kExampleTag2); + registration_id.origin(), kExampleId2); { base::RunLoop run_loop; @@ -199,8 +199,8 @@ run_loop.Run(); } - ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value()); - EXPECT_EQ(kExampleTag2, embedded_worker_test_helper()->last_tag().value()); + ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value()); + EXPECT_EQ(kExampleId2, embedded_worker_test_helper()->last_id().value()); ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value()); EXPECT_EQ(fetches.size(), @@ -219,7 +219,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFetchedEvent) { BackgroundFetchRegistrationId registration_id; - ASSERT_TRUE(CreateRegistrationId(kExampleTag, ®istration_id)); + ASSERT_TRUE(CreateRegistrationId(kExampleId, ®istration_id)); std::vector<BackgroundFetchSettledFetch> fetches; fetches.push_back(BackgroundFetchSettledFetch()); @@ -232,8 +232,8 @@ run_loop.Run(); } - ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value()); - EXPECT_EQ(kExampleTag, embedded_worker_test_helper()->last_tag().value()); + ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value()); + EXPECT_EQ(kExampleId, embedded_worker_test_helper()->last_id().value()); ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value()); EXPECT_EQ(fetches.size(), @@ -249,7 +249,7 @@ BackgroundFetchRegistrationId second_registration_id( registration_id.service_worker_registration_id(), - registration_id.origin(), kExampleTag2); + registration_id.origin(), kExampleId2); { base::RunLoop run_loop; @@ -259,8 +259,8 @@ run_loop.Run(); } - ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value()); - EXPECT_EQ(kExampleTag2, embedded_worker_test_helper()->last_tag().value()); + ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value()); + EXPECT_EQ(kExampleId2, embedded_worker_test_helper()->last_id().value()); ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value()); EXPECT_EQ(fetches.size(),
diff --git a/content/browser/background_fetch/background_fetch_registration_id.cc b/content/browser/background_fetch/background_fetch_registration_id.cc index db7653b..02d5a6e 100644 --- a/content/browser/background_fetch/background_fetch_registration_id.cc +++ b/content/browser/background_fetch/background_fetch_registration_id.cc
@@ -16,10 +16,10 @@ BackgroundFetchRegistrationId::BackgroundFetchRegistrationId( int64_t service_worker_registration_id, const url::Origin& origin, - const std::string& tag) + const std::string& id) : service_worker_registration_id_(service_worker_registration_id), origin_(origin), - tag_(tag) {} + id_(id) {} BackgroundFetchRegistrationId::BackgroundFetchRegistrationId( const BackgroundFetchRegistrationId& other) = default; @@ -36,7 +36,7 @@ const BackgroundFetchRegistrationId& other) const { return other.service_worker_registration_id_ == service_worker_registration_id_ && - other.origin_ == origin_ && other.tag_ == tag_; + other.origin_ == origin_ && other.id_ == id_; } bool BackgroundFetchRegistrationId::operator!=( @@ -46,9 +46,9 @@ bool BackgroundFetchRegistrationId::operator<( const BackgroundFetchRegistrationId& other) const { - return std::tie(service_worker_registration_id_, origin_, tag_) < + return std::tie(service_worker_registration_id_, origin_, id_) < std::tie(other.service_worker_registration_id_, other.origin_, - other.tag_); + other.id_); } bool BackgroundFetchRegistrationId::is_null() const {
diff --git a/content/browser/background_fetch/background_fetch_registration_id.h b/content/browser/background_fetch/background_fetch_registration_id.h index 32fb5da..7552f204b9 100644 --- a/content/browser/background_fetch/background_fetch_registration_id.h +++ b/content/browser/background_fetch/background_fetch_registration_id.h
@@ -20,7 +20,7 @@ BackgroundFetchRegistrationId(); BackgroundFetchRegistrationId(int64_t service_worker_registration_id, const url::Origin& origin, - const std::string& tag); + const std::string& id); BackgroundFetchRegistrationId(const BackgroundFetchRegistrationId& other); BackgroundFetchRegistrationId(BackgroundFetchRegistrationId&& other); ~BackgroundFetchRegistrationId(); @@ -43,12 +43,12 @@ return service_worker_registration_id_; } const url::Origin& origin() const { return origin_; } - const std::string& tag() const { return tag_; } + const std::string& id() const { return id_; } private: int64_t service_worker_registration_id_; url::Origin origin_; - std::string tag_; + std::string id_; }; } // namespace content
diff --git a/content/browser/background_fetch/background_fetch_service_impl.cc b/content/browser/background_fetch/background_fetch_service_impl.cc index e3c5337..a65b82d9e 100644 --- a/content/browser/background_fetch/background_fetch_service_impl.cc +++ b/content/browser/background_fetch/background_fetch_service_impl.cc
@@ -22,8 +22,8 @@ namespace { -// Maximum length of a developer-provided tag for a Background Fetch. -constexpr size_t kMaxTagLength = 1024 * 1024; +// Maximum length of a developer-provided id for a Background Fetch. +constexpr size_t kMaxIdLength = 1024 * 1024; // Maximum length of a developer-provided title for a Background Fetch. constexpr size_t kMaxTitleLength = 1024 * 1024; @@ -57,12 +57,12 @@ void BackgroundFetchServiceImpl::Fetch( int64_t service_worker_registration_id, const url::Origin& origin, - const std::string& tag, + const std::string& id, const std::vector<ServiceWorkerFetchRequest>& requests, const BackgroundFetchOptions& options, FetchCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (!ValidateTag(tag)) { + if (!ValidateId(id)) { std::move(callback).Run( blink::mojom::BackgroundFetchError::INVALID_ARGUMENT, base::nullopt /* registration */); @@ -77,7 +77,7 @@ } BackgroundFetchRegistrationId registration_id(service_worker_registration_id, - origin, tag); + origin, id); background_fetch_context_->StartFetch(registration_id, requests, options, std::move(callback)); @@ -86,11 +86,11 @@ void BackgroundFetchServiceImpl::UpdateUI( int64_t service_worker_registration_id, const url::Origin& origin, - const std::string& tag, + const std::string& id, const std::string& title, UpdateUICallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (!ValidateTag(tag) || !ValidateTitle(title)) { + if (!ValidateId(id) || !ValidateTitle(title)) { std::move(callback).Run( blink::mojom::BackgroundFetchError::INVALID_ARGUMENT); return; @@ -98,22 +98,22 @@ BackgroundFetchJobController* controller = background_fetch_context_->GetActiveFetch(BackgroundFetchRegistrationId( - service_worker_registration_id, origin, tag)); + service_worker_registration_id, origin, id)); if (controller) controller->UpdateUI(title); - std::move(callback).Run( - controller ? blink::mojom::BackgroundFetchError::NONE - : blink::mojom::BackgroundFetchError::INVALID_TAG); + std::move(callback).Run(controller + ? blink::mojom::BackgroundFetchError::NONE + : blink::mojom::BackgroundFetchError::INVALID_ID); } void BackgroundFetchServiceImpl::Abort(int64_t service_worker_registration_id, const url::Origin& origin, - const std::string& tag, + const std::string& id, AbortCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (!ValidateTag(tag)) { + if (!ValidateId(id)) { std::move(callback).Run( blink::mojom::BackgroundFetchError::INVALID_ARGUMENT); return; @@ -121,23 +121,23 @@ BackgroundFetchJobController* controller = background_fetch_context_->GetActiveFetch(BackgroundFetchRegistrationId( - service_worker_registration_id, origin, tag)); + service_worker_registration_id, origin, id)); if (controller) controller->Abort(); - std::move(callback).Run( - controller ? blink::mojom::BackgroundFetchError::NONE - : blink::mojom::BackgroundFetchError::INVALID_TAG); + std::move(callback).Run(controller + ? blink::mojom::BackgroundFetchError::NONE + : blink::mojom::BackgroundFetchError::INVALID_ID); } void BackgroundFetchServiceImpl::GetRegistration( int64_t service_worker_registration_id, const url::Origin& origin, - const std::string& tag, + const std::string& id, GetRegistrationCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (!ValidateTag(tag)) { + if (!ValidateId(id)) { std::move(callback).Run( blink::mojom::BackgroundFetchError::INVALID_ARGUMENT, base::nullopt /* registration */); @@ -146,10 +146,10 @@ BackgroundFetchJobController* controller = background_fetch_context_->GetActiveFetch(BackgroundFetchRegistrationId( - service_worker_registration_id, origin, tag)); + service_worker_registration_id, origin, id)); if (!controller) { - std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_TAG, + std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_ID, base::nullopt /* registration */); return; } @@ -157,7 +157,7 @@ // Compile the BackgroundFetchRegistration object that will be given to the // developer, representing the data associated with the |controller|. BackgroundFetchRegistration registration; - registration.tag = controller->registration_id().tag(); + registration.id = controller->registration_id().id(); registration.icons = controller->options().icons; registration.title = controller->options().title; registration.total_download_size = controller->options().total_download_size; @@ -166,20 +166,20 @@ registration); } -void BackgroundFetchServiceImpl::GetTags(int64_t service_worker_registration_id, - const url::Origin& origin, - GetTagsCallback callback) { +void BackgroundFetchServiceImpl::GetIds(int64_t service_worker_registration_id, + const url::Origin& origin, + GetIdsCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); std::move(callback).Run( blink::mojom::BackgroundFetchError::NONE, - background_fetch_context_->GetActiveTagsForServiceWorkerRegistration( + background_fetch_context_->GetActiveIdsForServiceWorkerRegistration( service_worker_registration_id, origin)); } -bool BackgroundFetchServiceImpl::ValidateTag(const std::string& tag) { - if (tag.empty() || tag.size() > kMaxTagLength) { +bool BackgroundFetchServiceImpl::ValidateId(const std::string& id) { + if (id.empty() || id.size() > kMaxIdLength) { bad_message::ReceivedBadMessage(render_process_id_, - bad_message::BFSI_INVALID_TAG); + bad_message::BFSI_INVALID_ID); return false; }
diff --git a/content/browser/background_fetch/background_fetch_service_impl.h b/content/browser/background_fetch/background_fetch_service_impl.h index 2fcf66a..b675c50 100644 --- a/content/browser/background_fetch/background_fetch_service_impl.h +++ b/content/browser/background_fetch/background_fetch_service_impl.h
@@ -41,31 +41,31 @@ // blink::mojom::BackgroundFetchService implementation. void Fetch(int64_t service_worker_registration_id, const url::Origin& origin, - const std::string& tag, + const std::string& id, const std::vector<ServiceWorkerFetchRequest>& requests, const BackgroundFetchOptions& options, FetchCallback callback) override; void UpdateUI(int64_t service_worker_registration_id, const url::Origin& origin, - const std::string& tag, + const std::string& id, const std::string& title, UpdateUICallback callback) override; void Abort(int64_t service_worker_registration_id, const url::Origin& origin, - const std::string& tag, + const std::string& id, AbortCallback callback) override; void GetRegistration(int64_t service_worker_registration_id, const url::Origin& origin, - const std::string& tag, + const std::string& id, GetRegistrationCallback callback) override; - void GetTags(int64_t service_worker_registration_id, - const url::Origin& origin, - GetTagsCallback callback) override; + void GetIds(int64_t service_worker_registration_id, + const url::Origin& origin, + GetIdsCallback callback) override; private: - // Validates and returns whether the |tag| contains a valid value. The + // Validates and returns whether the |id| contains a valid value. The // renderer will be flagged for having send a bad message if it isn't. - bool ValidateTag(const std::string& tag) WARN_UNUSED_RESULT; + bool ValidateId(const std::string& id) WARN_UNUSED_RESULT; // Validates and returns whether |requests| contains at least a valid request. // The renderer will be flagged for having send a bad message if it isn't.
diff --git a/content/browser/background_fetch/background_fetch_service_unittest.cc b/content/browser/background_fetch/background_fetch_service_unittest.cc index 60a1507..cee2688 100644 --- a/content/browser/background_fetch/background_fetch_service_unittest.cc +++ b/content/browser/background_fetch/background_fetch_service_unittest.cc
@@ -22,8 +22,8 @@ namespace content { namespace { -const char kExampleTag[] = "my-background-fetch"; -const char kAlternativeTag[] = "my-alternative-fetch"; +const char kExampleId[] = "my-background-fetch"; +const char kAlternativeId[] = "my-alternative-fetch"; IconDefinition CreateIcon(std::string src, std::string sizes, @@ -53,7 +53,7 @@ base::RunLoop run_loop; service_->Fetch(registration_id.service_worker_registration_id(), - registration_id.origin(), registration_id.tag(), requests, + registration_id.origin(), registration_id.id(), requests, options, base::Bind(&BackgroundFetchServiceTest::DidGetRegistration, base::Unretained(this), run_loop.QuitClosure(), @@ -74,7 +74,7 @@ base::RunLoop run_loop; service_->Abort( registration_id.service_worker_registration_id(), - registration_id.origin(), registration_id.tag(), + registration_id.origin(), registration_id.id(), base::Bind(&BackgroundFetchServiceTest::DidAbort, base::Unretained(this), run_loop.QuitClosure(), out_error)); @@ -92,7 +92,7 @@ base::RunLoop run_loop; service_->GetRegistration( registration_id.service_worker_registration_id(), - registration_id.origin(), registration_id.tag(), + registration_id.origin(), registration_id.id(), base::Bind(&BackgroundFetchServiceTest::DidGetRegistration, base::Unretained(this), run_loop.QuitClosure(), out_error, out_registration)); @@ -100,19 +100,19 @@ run_loop.Run(); } - // Synchronous wrapper for BackgroundFetchServiceImpl::GetTags(). - void GetTags(const BackgroundFetchRegistrationId& registration_id, - blink::mojom::BackgroundFetchError* out_error, - std::vector<std::string>* out_tags) { + // Synchronous wrapper for BackgroundFetchServiceImpl::GetIds(). + void GetIds(const BackgroundFetchRegistrationId& registration_id, + blink::mojom::BackgroundFetchError* out_error, + std::vector<std::string>* out_ids) { DCHECK(out_error); - DCHECK(out_tags); + DCHECK(out_ids); base::RunLoop run_loop; - service_->GetTags(registration_id.service_worker_registration_id(), - registration_id.origin(), - base::Bind(&BackgroundFetchServiceTest::DidGetTags, - base::Unretained(this), run_loop.QuitClosure(), - out_error, out_tags)); + service_->GetIds(registration_id.service_worker_registration_id(), + registration_id.origin(), + base::Bind(&BackgroundFetchServiceTest::DidGetIds, + base::Unretained(this), run_loop.QuitClosure(), + out_error, out_ids)); run_loop.Run(); } @@ -171,13 +171,13 @@ quit_closure.Run(); } - void DidGetTags(base::Closure quit_closure, - blink::mojom::BackgroundFetchError* out_error, - std::vector<std::string>* out_tags, - blink::mojom::BackgroundFetchError error, - const std::vector<std::string>& tags) { + void DidGetIds(base::Closure quit_closure, + blink::mojom::BackgroundFetchError* out_error, + std::vector<std::string>* out_ids, + blink::mojom::BackgroundFetchError error, + const std::vector<std::string>& ids) { *out_error = error; - *out_tags = tags; + *out_ids = ids; quit_closure.Run(); } @@ -194,10 +194,10 @@ BackgroundFetchOptions options; - // The `tag` must be a non-empty string. + // The `id` must be a non-empty string. { BackgroundFetchRegistrationId registration_id( - 42 /* service_worker_registration_id */, origin(), "" /* tag */); + 42 /* service_worker_registration_id */, origin(), "" /* id */); std::vector<ServiceWorkerFetchRequest> requests; requests.emplace_back(); // empty, but valid @@ -213,7 +213,7 @@ // At least a single ServiceWorkerFetchRequest must be given. { BackgroundFetchRegistrationId registration_id( - 42 /* service_worker_registration_id */, origin(), kExampleTag); + 42 /* service_worker_registration_id */, origin(), kExampleId); std::vector<ServiceWorkerFetchRequest> requests; // |requests| has deliberately been left empty. @@ -230,10 +230,10 @@ TEST_F(BackgroundFetchServiceTest, FetchRegistrationProperties) { // This test starts a new Background Fetch and verifies that the returned // BackgroundFetchRegistration object matches the given options. Then gets - // the active Background Fetch with the same tag, and verifies it again. + // the active Background Fetch with the same id, and verifies it again. BackgroundFetchRegistrationId registration_id; - ASSERT_TRUE(CreateRegistrationId(kExampleTag, ®istration_id)); + ASSERT_TRUE(CreateRegistrationId(kExampleId, ®istration_id)); std::vector<ServiceWorkerFetchRequest> requests; requests.emplace_back(); // empty, but valid @@ -252,7 +252,7 @@ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE); // The |registration| should reflect the options given in |options|. - EXPECT_EQ(registration.tag, kExampleTag); + EXPECT_EQ(registration.id, kExampleId); ASSERT_EQ(registration.icons.size(), options.icons.size()); for (size_t i = 0; i < registration.icons.size(); ++i) { @@ -272,7 +272,7 @@ ASSERT_EQ(second_error, blink::mojom::BackgroundFetchError::NONE); // The |second_registration| should reflect the options given in |options|. - EXPECT_EQ(second_registration.tag, kExampleTag); + EXPECT_EQ(second_registration.id, kExampleId); ASSERT_EQ(second_registration.icons.size(), options.icons.size()); for (size_t i = 0; i < second_registration.icons.size(); ++i) { @@ -289,10 +289,10 @@ TEST_F(BackgroundFetchServiceTest, FetchDuplicatedRegistrationFailure) { // This tests starts a new Background Fetch, verifies that a registration was // successfully created, and then tries to start a second fetch for the same - // registration. This should fail with a DUPLICATED_TAG error. + // registration. This should fail with a DUPLICATED_ID error. BackgroundFetchRegistrationId registration_id; - ASSERT_TRUE(CreateRegistrationId(kExampleTag, ®istration_id)); + ASSERT_TRUE(CreateRegistrationId(kExampleId, ®istration_id)); std::vector<ServiceWorkerFetchRequest> requests; requests.emplace_back(); // empty, but valid @@ -313,7 +313,7 @@ // Create the second registration with the same data. This must fail. ASSERT_NO_FATAL_FAILURE(Fetch(registration_id, requests, options, &second_error, &second_registration)); - ASSERT_EQ(second_error, blink::mojom::BackgroundFetchError::DUPLICATED_TAG); + ASSERT_EQ(second_error, blink::mojom::BackgroundFetchError::DUPLICATED_ID); } TEST_F(BackgroundFetchServiceTest, FetchSuccessEventDispatch) { @@ -322,7 +322,7 @@ // `backgroundfetched` event will be dispatched with the expected contents. BackgroundFetchRegistrationId registration_id; - ASSERT_TRUE(CreateRegistrationId(kExampleTag, ®istration_id)); + ASSERT_TRUE(CreateRegistrationId(kExampleId, ®istration_id)); // base::RunLoop that we'll run until the event has been dispatched. If this // test times out, it means that the event could not be dispatched. @@ -377,8 +377,8 @@ // Spin the |event_dispatched_loop| to wait for the dispatched event. event_dispatched_loop.Run(); - ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value()); - EXPECT_EQ(kExampleTag, embedded_worker_test_helper()->last_tag().value()); + ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value()); + EXPECT_EQ(kExampleId, embedded_worker_test_helper()->last_id().value()); ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value()); @@ -433,7 +433,7 @@ // has a non-OK status code, or the response cannot be accessed due to CORS. BackgroundFetchRegistrationId registration_id; - ASSERT_TRUE(CreateRegistrationId(kExampleTag, ®istration_id)); + ASSERT_TRUE(CreateRegistrationId(kExampleId, ®istration_id)); // base::RunLoop that we'll run until the event has been dispatched. If this // test times out, it means that the event could not be dispatched. @@ -474,8 +474,8 @@ // Spin the |event_dispatched_loop| to wait for the dispatched event. event_dispatched_loop.Run(); - ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value()); - EXPECT_EQ(kExampleTag, embedded_worker_test_helper()->last_tag().value()); + ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value()); + EXPECT_EQ(kExampleId, embedded_worker_test_helper()->last_id().value()); ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value()); @@ -517,10 +517,10 @@ TEST_F(BackgroundFetchServiceTest, Abort) { // This test starts a new Background Fetch, completes the registration, and // then aborts the Background Fetch mid-process. Tests all of StartFetch(), - // GetActiveFetches() and GetActiveTagsForServiceWorkerRegistration(). + // GetActiveFetches() and GetActiveIdsForServiceWorkerRegistration(). BackgroundFetchRegistrationId registration_id; - ASSERT_TRUE(CreateRegistrationId(kExampleTag, ®istration_id)); + ASSERT_TRUE(CreateRegistrationId(kExampleId, ®istration_id)); std::vector<ServiceWorkerFetchRequest> requests; requests.emplace_back(); // empty, but valid @@ -550,7 +550,7 @@ // Now try to get the created registration, which is expected to fail. ASSERT_NO_FATAL_FAILURE( GetRegistration(registration_id, &second_error, &second_registration)); - ASSERT_EQ(second_error, blink::mojom::BackgroundFetchError::INVALID_TAG); + ASSERT_EQ(second_error, blink::mojom::BackgroundFetchError::INVALID_ID); } TEST_F(BackgroundFetchServiceTest, AbortInvalidArguments) { @@ -558,7 +558,7 @@ // return INVALID_ARGUMENT when invalid data is send over the Mojo channel. BackgroundFetchRegistrationId registration_id( - 42 /* service_worker_registration_id */, origin(), "" /* tag */); + 42 /* service_worker_registration_id */, origin(), "" /* id */); blink::mojom::BackgroundFetchError error; @@ -566,19 +566,19 @@ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ARGUMENT); } -TEST_F(BackgroundFetchServiceTest, AbortInvalidTag) { +TEST_F(BackgroundFetchServiceTest, AbortInvalidId) { // This test verifies that aborting a Background Fetch registration with a - // tag that does not correspond to an active fetch kindly tells us so. + // id that does not correspond to an active fetch kindly tells us so. BackgroundFetchRegistrationId registration_id; - ASSERT_TRUE(CreateRegistrationId(kExampleTag, ®istration_id)); + ASSERT_TRUE(CreateRegistrationId(kExampleId, ®istration_id)); // Deliberate do *not* create a fetch for the |registration_id|. blink::mojom::BackgroundFetchError error; ASSERT_NO_FATAL_FAILURE(Abort(registration_id, &error)); - ASSERT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_TAG); + ASSERT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ID); } TEST_F(BackgroundFetchServiceTest, AbortEventDispatch) { @@ -586,7 +586,7 @@ // Fetch registration has been aborted by either the user or developer. BackgroundFetchRegistrationId registration_id; - ASSERT_TRUE(CreateRegistrationId(kExampleTag, ®istration_id)); + ASSERT_TRUE(CreateRegistrationId(kExampleId, ®istration_id)); // base::RunLoop that we'll run until the event has been dispatched. If this // test times out, it means that the event could not be dispatched. @@ -627,34 +627,34 @@ event_dispatched_loop.Run(); - ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value()); - EXPECT_EQ(kExampleTag, embedded_worker_test_helper()->last_tag().value()); + ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value()); + EXPECT_EQ(kExampleId, embedded_worker_test_helper()->last_id().value()); } -TEST_F(BackgroundFetchServiceTest, GetTags) { - // This test verifies that the list of active tags can be retrieved from the +TEST_F(BackgroundFetchServiceTest, GetIds) { + // This test verifies that the list of active ids can be retrieved from the // service for a given Service Worker, as extracted from a registration. BackgroundFetchRegistrationId registration_id; - ASSERT_TRUE(CreateRegistrationId(kExampleTag, ®istration_id)); + ASSERT_TRUE(CreateRegistrationId(kExampleId, ®istration_id)); BackgroundFetchRegistrationId second_registration_id; - ASSERT_TRUE(CreateRegistrationId(kAlternativeTag, &second_registration_id)); + ASSERT_TRUE(CreateRegistrationId(kAlternativeId, &second_registration_id)); std::vector<ServiceWorkerFetchRequest> requests; requests.emplace_back(); // empty, but valid BackgroundFetchOptions options; - // Verify that there are no active tags yet. + // Verify that there are no active ids yet. { blink::mojom::BackgroundFetchError error; - std::vector<std::string> tags; + std::vector<std::string> ids; - ASSERT_NO_FATAL_FAILURE(GetTags(registration_id, &error, &tags)); + ASSERT_NO_FATAL_FAILURE(GetIds(registration_id, &error, &ids)); ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE); - ASSERT_EQ(tags.size(), 0u); + ASSERT_EQ(ids.size(), 0u); } // Start the Background Fetch for the |registration_id|. @@ -670,13 +670,13 @@ // Verify that there is a single active fetch (the one we just started). { blink::mojom::BackgroundFetchError error; - std::vector<std::string> tags; + std::vector<std::string> ids; - ASSERT_NO_FATAL_FAILURE(GetTags(registration_id, &error, &tags)); + ASSERT_NO_FATAL_FAILURE(GetIds(registration_id, &error, &ids)); ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE); - ASSERT_EQ(tags.size(), 1u); - EXPECT_EQ(tags[0], kExampleTag); + ASSERT_EQ(ids.size(), 1u); + EXPECT_EQ(ids[0], kExampleId); } // Start the Background Fetch for the |second_registration_id|. @@ -692,21 +692,20 @@ // Verify that there are two active fetches. { blink::mojom::BackgroundFetchError error; - std::vector<std::string> tags; + std::vector<std::string> ids; - ASSERT_NO_FATAL_FAILURE(GetTags(registration_id, &error, &tags)); + ASSERT_NO_FATAL_FAILURE(GetIds(registration_id, &error, &ids)); ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE); - ASSERT_EQ(tags.size(), 2u); + ASSERT_EQ(ids.size(), 2u); - // We make no guarantees about ordering of the tags. - const bool has_example_tag = - tags[0] == kExampleTag || tags[1] == kExampleTag; - const bool has_alternative_tag = - tags[0] == kAlternativeTag || tags[1] == kAlternativeTag; + // We make no guarantees about ordering of the ids. + const bool has_example_id = ids[0] == kExampleId || ids[1] == kExampleId; + const bool has_alternative_id = + ids[0] == kAlternativeId || ids[1] == kAlternativeId; - EXPECT_TRUE(has_example_tag); - EXPECT_TRUE(has_alternative_tag); + EXPECT_TRUE(has_example_id); + EXPECT_TRUE(has_alternative_id); } }
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h index 7b5e1d2e..106f3cca9 100644 --- a/content/browser/bad_message.h +++ b/content/browser/bad_message.h
@@ -185,7 +185,7 @@ BDH_INVALID_DESCRIPTOR_ID = 161, RWH_INVALID_BEGIN_FRAME_ACK_DID_NOT_SWAP = 162, RWH_INVALID_BEGIN_FRAME_ACK_COMPOSITOR_FRAME = 163, - BFSI_INVALID_TAG = 164, + BFSI_INVALID_ID = 164, BFSI_INVALID_REQUESTS = 165, BFSI_INVALID_TITLE = 166, RWH_INVALID_FRAME_TOKEN = 167,
diff --git a/content/browser/browser_main_runner.cc b/content/browser/browser_main_runner.cc index bddc432d..bb7e31fd 100644 --- a/content/browser/browser_main_runner.cc +++ b/content/browser/browser_main_runner.cc
@@ -26,6 +26,7 @@ #include "content/browser/browser_main_loop.h" #include "content/browser/browser_shutdown_profile_dumper.h" #include "content/browser/notification_service_impl.h" +#include "content/common/content_switches_internal.h" #include "content/public/browser/tracing_controller.h" #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" @@ -88,6 +89,9 @@ if (parameters.command_line.HasSwitch(switches::kWaitForDebugger)) base::debug::WaitForDebugger(60, true); + if (parameters.command_line.HasSwitch(switches::kBrowserStartupDialog)) + WaitForDebugger("Browser"); + base::StatisticsRecorder::Initialize(); notification_service_.reset(new NotificationServiceImpl);
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc index da1f666..1a1d723 100644 --- a/content/browser/compositor/gpu_process_transport_factory.cc +++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -344,6 +344,10 @@ // Software fallback does not happen on Chrome OS. return true; #endif + + if (compositor->force_software_compositor()) + return false; + #if defined(OS_WIN) if (::GetProp(compositor->widget(), kForceSoftwareCompositor) && ::RemoveProp(compositor->widget(), kForceSoftwareCompositor))
diff --git a/content/browser/generic_sensor_browsertest.cc b/content/browser/generic_sensor_browsertest.cc index af946d440..f478149 100644 --- a/content/browser/generic_sensor_browsertest.cc +++ b/content/browser/generic_sensor_browsertest.cc
@@ -106,9 +106,9 @@ GetBufferOffset()); device::SensorReading reading; - reading.timestamp = + reading.als.timestamp = (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); - reading.values[0] = 50; + reading.als.value = 50; device::SensorReadingSharedBuffer* buffer = static_cast<device::SensorReadingSharedBuffer*>(shared_buffer.get());
diff --git a/content/browser/indexed_db/leveldb/leveldb_database.cc b/content/browser/indexed_db/leveldb/leveldb_database.cc index 4433dbcf..bc05c95d 100644 --- a/content/browser/indexed_db/leveldb/leveldb_database.cc +++ b/content/browser/indexed_db/leveldb/leveldb_database.cc
@@ -83,6 +83,27 @@ return StringPiece(s.data(), s.size()); } +class ComparatorAdapter : public leveldb::Comparator { + public: + explicit ComparatorAdapter(const LevelDBComparator* comparator) + : comparator_(comparator) {} + + int Compare(const leveldb::Slice& a, const leveldb::Slice& b) const override { + return comparator_->Compare(MakeStringPiece(a), MakeStringPiece(b)); + } + + const char* Name() const override { return comparator_->Name(); } + + // TODO(jsbell): Support the methods below in the future. + void FindShortestSeparator(std::string* start, + const leveldb::Slice& limit) const override {} + + void FindShortSuccessor(std::string* key) const override {} + + private: + const LevelDBComparator* comparator_; +}; + size_t DefaultBlockCacheSize() { if (base::SysInfo::IsLowEndDevice()) return 512 * 1024; // 512KB @@ -233,27 +254,6 @@ } // namespace -LevelDBDatabase::ComparatorAdapter::ComparatorAdapter( - const LevelDBComparator* comparator) - : comparator_(comparator) {} - -int LevelDBDatabase::ComparatorAdapter::Compare(const leveldb::Slice& a, - const leveldb::Slice& b) const { - return comparator_->Compare(MakeStringPiece(a), MakeStringPiece(b)); -} - -const char* LevelDBDatabase::ComparatorAdapter::Name() const { - return comparator_->Name(); -} - -// TODO(jsbell): Support the methods below in the future. -void LevelDBDatabase::ComparatorAdapter::FindShortestSeparator( - std::string* start, - const leveldb::Slice& limit) const {} - -void LevelDBDatabase::ComparatorAdapter::FindShortSuccessor( - std::string* key) const {} - LevelDBSnapshot::LevelDBSnapshot(LevelDBDatabase* db) : db_(db->db_.get()), snapshot_(db_->GetSnapshot()) {}
diff --git a/content/browser/indexed_db/leveldb/leveldb_database.h b/content/browser/indexed_db/leveldb/leveldb_database.h index e6276a2..1ebadfe 100644 --- a/content/browser/indexed_db/leveldb/leveldb_database.h +++ b/content/browser/indexed_db/leveldb/leveldb_database.h
@@ -65,23 +65,6 @@ // large. See https://crbug/696055. static const size_t kDefaultMaxOpenIteratorsPerDatabase = 50; - class ComparatorAdapter : public leveldb::Comparator { - public: - explicit ComparatorAdapter(const LevelDBComparator* comparator); - - int Compare(const leveldb::Slice& a, - const leveldb::Slice& b) const override; - - const char* Name() const override; - - void FindShortestSeparator(std::string* start, - const leveldb::Slice& limit) const override; - void FindShortSuccessor(std::string* key) const override; - - private: - const LevelDBComparator* comparator_; - }; - // |max_open_cursors| cannot be 0. static leveldb::Status Open(const base::FilePath& file_name, const LevelDBComparator* comparator,
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index f880762..1e40d64 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -1858,12 +1858,13 @@ // Don't cancel navigations that are expected to live beyond this process. if (IsTransferredNavigation(id)) any_requests_transferring = true; - if (info->detachable_handler()) { - info->detachable_handler()->Detach(); - } else if (!info->IsDownload() && !info->is_stream() && - !IsTransferredNavigation(id) && - (cancel_all_routes || route_id == info->GetRenderFrameID())) { - matching_requests.push_back(id); + if (cancel_all_routes || route_id == info->GetRenderFrameID()) { + if (info->detachable_handler()) { + info->detachable_handler()->Detach(); + } else if (!info->IsDownload() && !info->is_stream() && + !IsTransferredNavigation(id)) { + matching_requests.push_back(id); + } } }
diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h index 8a28e1c..8c6187c 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.h +++ b/content/browser/loader/resource_dispatcher_host_impl.h
@@ -357,6 +357,7 @@ DetachableResourceTimesOut); FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest, TestProcessCancelDetachableTimesOut); + FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest, CancelRequestsForRoute); FRIEND_TEST_ALL_PREFIXES(SitePerProcessIgnoreCertErrorsBrowserTest, CrossSiteRedirectCertificateStore); FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest, LoadInfo);
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc index 54c5ce4..0241e5d 100644 --- a/content/browser/loader/resource_dispatcher_host_unittest.cc +++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -1124,6 +1124,14 @@ return filter->requester_info_for_test(); } + bool IsDetached(net::URLRequest* request) { + auto* request_info = ResourceRequestInfoImpl::ForRequest(request); + if (!request_info) + return false; + return request_info->detachable_handler() && + request_info->detachable_handler()->is_detached(); + } + content::TestBrowserThreadBundle thread_bundle_; std::unique_ptr<TestBrowserContext> browser_context_; std::unique_ptr<TestURLRequestJobFactory> job_factory_; @@ -1856,6 +1864,52 @@ CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_ACCESS_DENIED); } +TEST_F(ResourceDispatcherHostTest, CancelRequestsForRoute) { + job_factory_->SetDelayedStartJobGeneration(true); + MakeTestRequestWithRenderFrame(0, 11, 1, net::URLRequestTestJob::test_url_1(), + RESOURCE_TYPE_XHR); + EXPECT_EQ(1, host_.pending_requests()); + + MakeTestRequestWithRenderFrame(0, 12, 2, net::URLRequestTestJob::test_url_2(), + RESOURCE_TYPE_XHR); + EXPECT_EQ(2, host_.pending_requests()); + + MakeTestRequestWithRenderFrame(0, 11, 3, net::URLRequestTestJob::test_url_3(), + RESOURCE_TYPE_PING); + EXPECT_EQ(3, host_.pending_requests()); + + MakeTestRequestWithRenderFrame(0, 12, 4, net::URLRequestTestJob::test_url_4(), + RESOURCE_TYPE_PING); + EXPECT_EQ(4, host_.pending_requests()); + + EXPECT_TRUE(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 1))); + EXPECT_TRUE(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 2))); + EXPECT_TRUE(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 3))); + EXPECT_TRUE(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 4))); + + host_.CancelRequestsForRoute(GlobalFrameRoutingId(filter_->child_id(), 11)); + + EXPECT_FALSE(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 1))); + EXPECT_TRUE(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 2))); + ASSERT_TRUE(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 3))); + ASSERT_TRUE(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 4))); + + EXPECT_TRUE( + IsDetached(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 3)))); + EXPECT_FALSE( + IsDetached(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 4)))); + + CompleteStartRequest(2); + CompleteStartRequest(3); + CompleteStartRequest(4); + + while (host_.pending_requests() > 0) { + while (net::URLRequestTestJob::ProcessOnePendingMessage()) { + } + content::RunAllBlockingPoolTasksUntilIdle(); + } +} + // Tests CancelRequestsForProcess TEST_F(ResourceDispatcherHostTest, TestProcessCancel) { scoped_refptr<TestFilter> test_filter = new TestFilter(
diff --git a/content/browser/loader/sync_resource_handler.cc b/content/browser/loader/sync_resource_handler.cc index 596fbc93..a3a71b8 100644 --- a/content/browser/loader/sync_resource_handler.cc +++ b/content/browser/loader/sync_resource_handler.cc
@@ -87,6 +87,7 @@ result_.response_time = response->head.response_time; result_.load_timing = response->head.load_timing; result_.devtools_info = response->head.devtools_info; + result_.socket_address = response->head.socket_address; controller->Resume(); }
diff --git a/content/browser/renderer_host/media/audio_input_renderer_host_unittest.cc b/content/browser/renderer_host/media/audio_input_renderer_host_unittest.cc index c441897..692522a 100644 --- a/content/browser/renderer_host/media/audio_input_renderer_host_unittest.cc +++ b/content/browser/renderer_host/media/audio_input_renderer_host_unittest.cc
@@ -116,7 +116,6 @@ private: bool Send(IPC::Message* message) override { - DCHECK_CURRENTLY_ON(BrowserThread::IO); bool handled = true; IPC_BEGIN_MESSAGE_MAP(AudioInputRendererHostWithInterception, *message)
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 941c425b..ffd1e2ee 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1839,7 +1839,7 @@ // RenderWidgetHostViewAura, aura::WindowTreeHostObserver implementation: void RenderWidgetHostViewAura::OnHostMovedInPixels( - const aura::WindowTreeHost* host, + aura::WindowTreeHost* host, const gfx::Point& new_origin_in_pixels) { TRACE_EVENT1("ui", "RenderWidgetHostViewAura::OnHostMovedInPixels", "new_origin_in_pixels", new_origin_in_pixels.ToString());
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index 49674e5..910d321 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -276,7 +276,7 @@ aura::Window* lost_focus) override; // Overridden from aura::WindowTreeHostObserver: - void OnHostMovedInPixels(const aura::WindowTreeHost* host, + void OnHostMovedInPixels(aura::WindowTreeHost* host, const gfx::Point& new_origin_in_pixels) override; #if defined(OS_WIN)
diff --git a/content/browser/service_worker/service_worker_context_core_observer.h b/content/browser/service_worker/service_worker_context_core_observer.h index 2a60771..e8bf108 100644 --- a/content/browser/service_worker/service_worker_context_core_observer.h +++ b/content/browser/service_worker/service_worker_context_core_observer.h
@@ -29,6 +29,11 @@ line_number(line), column_number(column), source_url(url) {} + ErrorInfo(const ErrorInfo& info) + : error_message(info.error_message), + line_number(info.line_number), + column_number(info.column_number), + source_url(info.source_url) {} const base::string16 error_message; const int line_number; const int column_number;
diff --git a/content/browser/service_worker/service_worker_context_watcher.cc b/content/browser/service_worker/service_worker_context_watcher.cc index a88d4084..eac701e 100644 --- a/content/browser/service_worker/service_worker_context_watcher.cc +++ b/content/browser/service_worker/service_worker_context_watcher.cc
@@ -42,19 +42,23 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::Bind(&ServiceWorkerContextWatcher::GetStoredRegistrationsOnIOThread, - this)); + base::BindOnce( + &ServiceWorkerContextWatcher::GetStoredRegistrationsOnIOThread, + this)); } void ServiceWorkerContextWatcher::Stop() { DCHECK_CURRENTLY_ON(BrowserThread::UI); + stop_called_ = true; BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::Bind(&ServiceWorkerContextWatcher::StopOnIOThread, this)); + base::BindOnce(&ServiceWorkerContextWatcher::StopOnIOThread, this)); } void ServiceWorkerContextWatcher::GetStoredRegistrationsOnIOThread() { DCHECK_CURRENTLY_ON(BrowserThread::IO); + if (is_stopped_) + return; context_->GetAllRegistrations(base::Bind( &ServiceWorkerContextWatcher::OnStoredRegistrationsOnIOThread, this)); } @@ -63,6 +67,8 @@ ServiceWorkerStatusCode status, const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) { DCHECK_CURRENTLY_ON(BrowserThread::IO); + if (is_stopped_) + return; context_->AddObserver(this); std::unordered_map<int64_t, std::unique_ptr<ServiceWorkerRegistrationInfo>> @@ -74,32 +80,41 @@ for (const auto& version : context_->GetAllLiveVersionInfo()) StoreVersionInfo(version); - std::vector<ServiceWorkerRegistrationInfo> registrations; - registrations.reserve(registration_info_map.size()); + std::unique_ptr<std::vector<ServiceWorkerRegistrationInfo>> registrations = + base::MakeUnique<std::vector<ServiceWorkerRegistrationInfo>>(); + registrations->reserve(registration_info_map.size()); for (const auto& registration_id_info_pair : registration_info_map) - registrations.push_back(*registration_id_info_pair.second); + registrations->push_back(*registration_id_info_pair.second); - std::vector<ServiceWorkerVersionInfo> versions; - versions.reserve(version_info_map_.size()); + std::unique_ptr<std::vector<ServiceWorkerVersionInfo>> versions = + base::MakeUnique<std::vector<ServiceWorkerVersionInfo>>(); + versions->reserve(version_info_map_.size()); for (auto version_it = version_info_map_.begin(); version_it != version_info_map_.end();) { - versions.push_back(*version_it->second); + versions->push_back(*version_it->second); if (IsStoppedAndRedundant(*version_it->second)) version_info_map_.erase(version_it++); else ++version_it; } - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(registration_callback_, registrations)); - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(version_callback_, versions)); + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce( + &ServiceWorkerContextWatcher::RunWorkerRegistrationUpdatedCallback, + this, std::move(registrations))); + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce( + &ServiceWorkerContextWatcher::RunWorkerVersionUpdatedCallback, this, + std::move(versions))); } void ServiceWorkerContextWatcher::StopOnIOThread() { DCHECK_CURRENTLY_ON(BrowserThread::IO); context_->RemoveObserver(this); + is_stopped_ = true; } ServiceWorkerContextWatcher::~ServiceWorkerContextWatcher() { @@ -132,36 +147,73 @@ int64_t registration_id, const GURL& pattern, ServiceWorkerRegistrationInfo::DeleteFlag delete_flag) { - std::vector<ServiceWorkerRegistrationInfo> registrations; + DCHECK_CURRENTLY_ON(BrowserThread::IO); + std::unique_ptr<std::vector<ServiceWorkerRegistrationInfo>> registrations = + base::MakeUnique<std::vector<ServiceWorkerRegistrationInfo>>(); ServiceWorkerRegistration* registration = context_->GetLiveRegistration(registration_id); if (registration) { - registrations.push_back(registration->GetInfo()); + registrations->push_back(registration->GetInfo()); } else { - registrations.push_back( + registrations->push_back( ServiceWorkerRegistrationInfo(pattern, registration_id, delete_flag)); } - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(registration_callback_, registrations)); + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce( + &ServiceWorkerContextWatcher::RunWorkerRegistrationUpdatedCallback, + this, std::move(registrations))); } void ServiceWorkerContextWatcher::SendVersionInfo( const ServiceWorkerVersionInfo& version_info) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - std::vector<ServiceWorkerVersionInfo> versions; - versions.push_back(version_info); - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(version_callback_, versions)); + std::unique_ptr<std::vector<ServiceWorkerVersionInfo>> versions = + base::MakeUnique<std::vector<ServiceWorkerVersionInfo>>(); + versions->push_back(version_info); + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce( + &ServiceWorkerContextWatcher::RunWorkerVersionUpdatedCallback, this, + std::move(versions))); +} + +void ServiceWorkerContextWatcher::RunWorkerRegistrationUpdatedCallback( + std::unique_ptr<std::vector<ServiceWorkerRegistrationInfo>> registrations) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (stop_called_) + return; + registration_callback_.Run(*registrations.get()); +} + +void ServiceWorkerContextWatcher::RunWorkerVersionUpdatedCallback( + std::unique_ptr<std::vector<ServiceWorkerVersionInfo>> versions) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (stop_called_) + return; + version_callback_.Run(*versions.get()); +} + +void ServiceWorkerContextWatcher::RunWorkerErrorReportedCallback( + int64_t registration_id, + int64_t version_id, + std::unique_ptr<ErrorInfo> error_info) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (stop_called_) + return; + error_callback_.Run(registration_id, version_id, *error_info.get()); } void ServiceWorkerContextWatcher::OnNewLiveRegistration(int64_t registration_id, const GURL& pattern) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); SendRegistrationInfo(registration_id, pattern, ServiceWorkerRegistrationInfo::IS_NOT_DELETED); } void ServiceWorkerContextWatcher::OnNewLiveVersion( const ServiceWorkerVersionInfo& version_info) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); int64_t version_id = version_info.version_id; auto it = version_info_map_.find(version_id); if (it != version_info_map_.end()) { @@ -180,6 +232,7 @@ void ServiceWorkerContextWatcher::OnRunningStateChanged( int64_t version_id, content::EmbeddedWorkerStatus running_status) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); auto it = version_info_map_.find(version_id); if (it == version_info_map_.end()) return; @@ -195,6 +248,7 @@ void ServiceWorkerContextWatcher::OnVersionStateChanged( int64_t version_id, content::ServiceWorkerVersion::Status status) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); auto it = version_info_map_.find(version_id); if (it == version_info_map_.end()) return; @@ -211,6 +265,7 @@ int64_t version_id, int process_id, int devtools_agent_route_id) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); auto it = version_info_map_.find(version_id); if (it == version_info_map_.end()) return; @@ -230,6 +285,7 @@ int64_t version_id, base::Time script_response_time, base::Time script_last_modified) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); auto it = version_info_map_.find(version_id); if (it == version_info_map_.end()) return; @@ -243,13 +299,16 @@ int process_id, int thread_id, const ErrorInfo& info) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); int64_t registration_id = kInvalidServiceWorkerRegistrationId; auto it = version_info_map_.find(version_id); if (it != version_info_map_.end()) registration_id = it->second->registration_id; BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind(error_callback_, registration_id, version_id, info)); + base::BindOnce( + &ServiceWorkerContextWatcher::RunWorkerErrorReportedCallback, this, + registration_id, version_id, base::MakeUnique<ErrorInfo>(info))); } void ServiceWorkerContextWatcher::OnReportConsoleMessage( @@ -257,17 +316,21 @@ int process_id, int thread_id, const ConsoleMessage& message) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (message.message_level != CONSOLE_MESSAGE_LEVEL_ERROR) return; int64_t registration_id = kInvalidServiceWorkerRegistrationId; auto it = version_info_map_.find(version_id); if (it != version_info_map_.end()) registration_id = it->second->registration_id; + BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind(error_callback_, registration_id, version_id, - ErrorInfo(message.message, message.line_number, -1, - message.source_url))); + base::BindOnce( + &ServiceWorkerContextWatcher::RunWorkerErrorReportedCallback, this, + registration_id, version_id, + base::MakeUnique<ErrorInfo>(message.message, message.line_number, -1, + message.source_url))); } void ServiceWorkerContextWatcher::OnControlleeAdded( @@ -277,6 +340,7 @@ int route_id, const base::Callback<WebContents*(void)>& web_contents_getter, ServiceWorkerProviderType type) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); auto it = version_info_map_.find(version_id); if (it == version_info_map_.end()) return; @@ -288,6 +352,7 @@ void ServiceWorkerContextWatcher::OnControlleeRemoved(int64_t version_id, const std::string& uuid) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); auto it = version_info_map_.find(version_id); if (it == version_info_map_.end()) return; @@ -298,12 +363,14 @@ void ServiceWorkerContextWatcher::OnRegistrationStored(int64_t registration_id, const GURL& pattern) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); SendRegistrationInfo(registration_id, pattern, ServiceWorkerRegistrationInfo::IS_NOT_DELETED); } void ServiceWorkerContextWatcher::OnRegistrationDeleted(int64_t registration_id, const GURL& pattern) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); SendRegistrationInfo(registration_id, pattern, ServiceWorkerRegistrationInfo::IS_DELETED); }
diff --git a/content/browser/service_worker/service_worker_context_watcher.h b/content/browser/service_worker/service_worker_context_watcher.h index 02c41c52..10847d4a 100644 --- a/content/browser/service_worker/service_worker_context_watcher.h +++ b/content/browser/service_worker/service_worker_context_watcher.h
@@ -13,6 +13,7 @@ #include "base/callback.h" #include "content/browser/service_worker/service_worker_context_core_observer.h" #include "content/browser/service_worker/service_worker_info.h" +#include "content/common/content_export.h" namespace content { @@ -21,7 +22,7 @@ // Used to monitor the status change of the ServiceWorker registrations and // versions in the ServiceWorkerContext from UI thread. -class ServiceWorkerContextWatcher +class CONTENT_EXPORT ServiceWorkerContextWatcher : public ServiceWorkerContextCoreObserver, public base::RefCountedThreadSafe<ServiceWorkerContextWatcher> { public: @@ -44,6 +45,8 @@ private: friend class base::RefCountedThreadSafe<ServiceWorkerContextWatcher>; + friend class ServiceWorkerContextWatcherTest; + ~ServiceWorkerContextWatcher() override; void GetStoredRegistrationsOnIOThread(); @@ -65,6 +68,15 @@ ServiceWorkerRegistrationInfo::DeleteFlag delete_flag); void SendVersionInfo(const ServiceWorkerVersionInfo& version); + void RunWorkerRegistrationUpdatedCallback( + std::unique_ptr<std::vector<ServiceWorkerRegistrationInfo>> + registrations); + void RunWorkerVersionUpdatedCallback( + std::unique_ptr<std::vector<ServiceWorkerVersionInfo>> versions); + void RunWorkerErrorReportedCallback(int64_t registration_id, + int64_t version_id, + std::unique_ptr<ErrorInfo> error_info); + // ServiceWorkerContextCoreObserver implements void OnNewLiveRegistration(int64_t registration_id, const GURL& pattern) override; @@ -110,6 +122,10 @@ WorkerRegistrationUpdatedCallback registration_callback_; WorkerVersionUpdatedCallback version_callback_; WorkerErrorReportedCallback error_callback_; + // Should be used on UI thread only. + bool stop_called_ = false; + // Should be used on IO thread only. + bool is_stopped_ = false; }; } // namespace content
diff --git a/content/browser/service_worker/service_worker_context_watcher_unittest.cc b/content/browser/service_worker/service_worker_context_watcher_unittest.cc new file mode 100644 index 0000000..67249fe --- /dev/null +++ b/content/browser/service_worker/service_worker_context_watcher_unittest.cc
@@ -0,0 +1,386 @@ +// 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 "content/browser/service_worker/service_worker_context_watcher.h" + +#include "base/memory/weak_ptr.h" +#include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" +#include "content/browser/service_worker/embedded_worker_test_helper.h" +#include "content/browser/service_worker/service_worker_context_wrapper.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { + +namespace { + +void DidRegisterServiceWorker(int64_t* registration_id_out, + ServiceWorkerStatusCode status, + const std::string& status_message, + int64_t registration_id) { + ASSERT_TRUE(registration_id_out); + EXPECT_EQ(SERVICE_WORKER_OK, status); + *registration_id_out = registration_id; +} + +void DidUnregisterServiceWorker(ServiceWorkerStatusCode* status_out, + ServiceWorkerStatusCode status) { + ASSERT_TRUE(status_out); + *status_out = status; +} + +class WatcherCallback { + public: + WatcherCallback() : weak_factory_(this) {} + + ~WatcherCallback() {} + + scoped_refptr<ServiceWorkerContextWatcher> StartWatch( + scoped_refptr<ServiceWorkerContextWrapper> context) { + scoped_refptr<ServiceWorkerContextWatcher> watcher = + base::MakeRefCounted<ServiceWorkerContextWatcher>( + context, + base::Bind(&WatcherCallback::OnRegistrationUpdated, + weak_factory_.GetWeakPtr()), + base::Bind(&WatcherCallback::OnVersionUpdated, + weak_factory_.GetWeakPtr()), + base::Bind(&WatcherCallback::OnErrorReported, + weak_factory_.GetWeakPtr())); + watcher->Start(); + return watcher; + } + + const std::map<int64_t, ServiceWorkerRegistrationInfo>& registrations() + const { + return registrations_; + } + + const std::map<int64_t, std::map<int64_t, ServiceWorkerVersionInfo>>& + versions() const { + return versions_; + } + const std::map< + int64_t, + std::map<int64_t, + std::vector<ServiceWorkerContextCoreObserver::ErrorInfo>>>& + errors() const { + return errors_; + } + + int callback_count() const { return callback_count_; }; + + private: + void OnRegistrationUpdated( + const std::vector<ServiceWorkerRegistrationInfo>& registrations) { + ++callback_count_; + for (const auto& info : registrations) { + if (info.delete_flag == + ServiceWorkerRegistrationInfo::DeleteFlag::IS_DELETED) { + registrations_.erase(info.registration_id); + } else { + registrations_[info.registration_id] = info; + } + } + } + + void OnVersionUpdated(const std::vector<ServiceWorkerVersionInfo>& versions) { + ++callback_count_; + for (const auto& info : versions) { + versions_[info.registration_id][info.version_id] = info; + } + } + + void OnErrorReported( + int64_t registration_id, + int64_t version_id, + const ServiceWorkerContextCoreObserver::ErrorInfo& error_info) { + ++callback_count_; + errors_[registration_id][version_id].push_back(error_info); + } + + std::map<int64_t /* registration_id */, ServiceWorkerRegistrationInfo> + registrations_; + std::map<int64_t /* registration_id */, + std::map<int64_t /* version_id */, ServiceWorkerVersionInfo>> + versions_; + std::map<int64_t /* registration_id */, + std::map<int64_t /* version_id */, + std::vector<ServiceWorkerContextCoreObserver::ErrorInfo>>> + errors_; + + int callback_count_ = 0; + + base::WeakPtrFactory<WatcherCallback> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(WatcherCallback); +}; + +} // namespace + +class ServiceWorkerContextWatcherTest : public testing::Test { + public: + ServiceWorkerContextWatcherTest() + : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} + + void SetUp() override { + helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath())); + base::RunLoop().RunUntilIdle(); + } + + void TearDown() override { + helper_.reset(); + base::RunLoop().RunUntilIdle(); + } + + protected: + ServiceWorkerContextCore* context() { return helper_->context(); } + ServiceWorkerContextWrapper* context_wrapper() { + return helper_->context_wrapper(); + } + int64_t RegisterServiceWorker(const GURL& scope, const GURL& script_url) { + int64_t registration_id = kInvalidServiceWorkerRegistrationId; + context()->RegisterServiceWorker( + script_url, ServiceWorkerRegistrationOptions(scope), + nullptr /* provider_host */, + base::Bind(&DidRegisterServiceWorker, ®istration_id)); + base::RunLoop().RunUntilIdle(); + return registration_id; + } + + ServiceWorkerStatusCode UnregisterServiceWorker(const GURL& scope) { + ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; + context()->UnregisterServiceWorker( + scope, base::Bind(&DidUnregisterServiceWorker, &status)); + base::RunLoop().RunUntilIdle(); + return status; + } + + void ReportError( + scoped_refptr<ServiceWorkerContextWatcher> watcher, + int64_t version_id, + const ServiceWorkerContextCoreObserver::ErrorInfo& error_info) { + watcher->OnErrorReported(version_id, 0 /* process_id */, 0 /* thread_id */, + error_info); + } + + private: + std::unique_ptr<EmbeddedWorkerTestHelper> helper_; + TestBrowserThreadBundle browser_thread_bundle_; + + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextWatcherTest); +}; + +TEST_F(ServiceWorkerContextWatcherTest, NoServiceWorker) { + WatcherCallback watcher_callback; + scoped_refptr<ServiceWorkerContextWatcher> watcher = + watcher_callback.StartWatch(context_wrapper()); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(0u, watcher_callback.registrations().size()); + EXPECT_EQ(0u, watcher_callback.versions().size()); + EXPECT_EQ(0u, watcher_callback.errors().size()); + // OnRegistrationUpdated() and OnVersionUpdated() must be called with the + // empty initial data. + EXPECT_EQ(2, watcher_callback.callback_count()); + watcher->Stop(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(0u, watcher_callback.registrations().size()); + EXPECT_EQ(0u, watcher_callback.versions().size()); + EXPECT_EQ(2, watcher_callback.callback_count()); +} + +TEST_F(ServiceWorkerContextWatcherTest, StoredServiceWorkers) { + GURL scope_1 = GURL("https://www1.example.com/"); + GURL script_1 = GURL("https://www1.example.com/worker.js"); + int64_t registration_id_1 = RegisterServiceWorker(scope_1, script_1); + ASSERT_NE(kInvalidServiceWorkerRegistrationId, registration_id_1); + + GURL scope_2 = GURL("https://www2.example.com/"); + GURL script_2 = GURL("https://www2.example.com/worker.js"); + int64_t registration_id_2 = RegisterServiceWorker(scope_2, script_2); + ASSERT_NE(kInvalidServiceWorkerRegistrationId, registration_id_2); + + WatcherCallback watcher_callback; + scoped_refptr<ServiceWorkerContextWatcher> watcher = + watcher_callback.StartWatch(context_wrapper()); + base::RunLoop().RunUntilIdle(); + + ASSERT_EQ(2u, watcher_callback.registrations().size()); + EXPECT_EQ(scope_1, + watcher_callback.registrations().at(registration_id_1).pattern); + EXPECT_EQ(scope_2, + watcher_callback.registrations().at(registration_id_2).pattern); + ASSERT_EQ(2u, watcher_callback.versions().size()); + EXPECT_EQ(script_1, watcher_callback.versions() + .at(registration_id_1) + .begin() + ->second.script_url); + EXPECT_EQ(script_2, watcher_callback.versions() + .at(registration_id_2) + .begin() + ->second.script_url); + EXPECT_EQ(0u, watcher_callback.errors().size()); + + watcher->Stop(); + base::RunLoop().RunUntilIdle(); +} + +TEST_F(ServiceWorkerContextWatcherTest, RegisteredServiceWorker) { + GURL scope_1 = GURL("https://www1.example.com/"); + GURL script_1 = GURL("https://www1.example.com/worker.js"); + int64_t registration_id_1 = RegisterServiceWorker(scope_1, script_1); + ASSERT_NE(kInvalidServiceWorkerRegistrationId, registration_id_1); + + WatcherCallback watcher_callback; + scoped_refptr<ServiceWorkerContextWatcher> watcher = + watcher_callback.StartWatch(context_wrapper()); + base::RunLoop().RunUntilIdle(); + ASSERT_EQ(1u, watcher_callback.registrations().size()); + EXPECT_EQ(scope_1, + watcher_callback.registrations().at(registration_id_1).pattern); + ASSERT_EQ(1u, watcher_callback.versions().size()); + EXPECT_EQ(script_1, watcher_callback.versions() + .at(registration_id_1) + .begin() + ->second.script_url); + EXPECT_EQ(0u, watcher_callback.errors().size()); + + GURL scope_2 = GURL("https://www2.example.com/"); + GURL script_2 = GURL("https://www2.example.com/worker.js"); + int64_t registration_id_2 = RegisterServiceWorker(scope_2, script_2); + ASSERT_EQ(2u, watcher_callback.registrations().size()); + EXPECT_EQ(scope_1, + watcher_callback.registrations().at(registration_id_1).pattern); + EXPECT_EQ(scope_2, + watcher_callback.registrations().at(registration_id_2).pattern); + ASSERT_EQ(2u, watcher_callback.versions().size()); + EXPECT_EQ(script_1, watcher_callback.versions() + .at(registration_id_1) + .begin() + ->second.script_url); + EXPECT_EQ(script_2, watcher_callback.versions() + .at(registration_id_2) + .begin() + ->second.script_url); + EXPECT_EQ(0u, watcher_callback.errors().size()); + + watcher->Stop(); + base::RunLoop().RunUntilIdle(); +} + +TEST_F(ServiceWorkerContextWatcherTest, UnregisteredServiceWorker) { + GURL scope_1 = GURL("https://www1.example.com/"); + GURL script_1 = GURL("https://www1.example.com/worker.js"); + int64_t registration_id_1 = RegisterServiceWorker(scope_1, script_1); + ASSERT_NE(kInvalidServiceWorkerRegistrationId, registration_id_1); + + GURL scope_2 = GURL("https://www2.example.com/"); + GURL script_2 = GURL("https://www2.example.com/worker.js"); + int64_t registration_id_2 = RegisterServiceWorker(scope_2, script_2); + + WatcherCallback watcher_callback; + scoped_refptr<ServiceWorkerContextWatcher> watcher = + watcher_callback.StartWatch(context_wrapper()); + base::RunLoop().RunUntilIdle(); + + ASSERT_EQ(2u, watcher_callback.registrations().size()); + EXPECT_EQ(scope_1, + watcher_callback.registrations().at(registration_id_1).pattern); + EXPECT_EQ(scope_2, + watcher_callback.registrations().at(registration_id_2).pattern); + ASSERT_EQ(2u, watcher_callback.versions().size()); + + ASSERT_EQ(SERVICE_WORKER_OK, UnregisterServiceWorker(scope_1)); + + ASSERT_EQ(1u, watcher_callback.registrations().size()); + EXPECT_EQ(scope_2, + watcher_callback.registrations().at(registration_id_2).pattern); + + watcher->Stop(); + base::RunLoop().RunUntilIdle(); +} + +TEST_F(ServiceWorkerContextWatcherTest, ErrorReport) { + GURL scope = GURL("https://www1.example.com/"); + GURL script = GURL("https://www1.example.com/worker.js"); + int64_t registration_id = RegisterServiceWorker(scope, script); + ASSERT_NE(kInvalidServiceWorkerRegistrationId, registration_id); + + WatcherCallback watcher_callback; + scoped_refptr<ServiceWorkerContextWatcher> watcher = + watcher_callback.StartWatch(context_wrapper()); + base::RunLoop().RunUntilIdle(); + ASSERT_EQ(1u, watcher_callback.registrations().size()); + EXPECT_EQ(scope, + watcher_callback.registrations().at(registration_id).pattern); + ASSERT_EQ(1u, watcher_callback.versions().size()); + EXPECT_EQ(script, watcher_callback.versions() + .at(registration_id) + .begin() + ->second.script_url); + int64_t version_id = + watcher_callback.versions().at(registration_id).begin()->first; + EXPECT_EQ(0u, watcher_callback.errors().size()); + + base::string16 message(base::ASCIIToUTF16("HELLO")); + ReportError( + watcher, version_id, + ServiceWorkerContextCoreObserver::ErrorInfo(message, 0, 0, script)); + base::RunLoop().RunUntilIdle(); + ASSERT_EQ(1u, watcher_callback.errors().size()); + ASSERT_EQ(1u, watcher_callback.errors().at(registration_id).size()); + ASSERT_EQ( + 1u, watcher_callback.errors().at(registration_id).at(version_id).size()); + EXPECT_EQ(message, watcher_callback.errors() + .at(registration_id) + .at(version_id)[0] + .error_message); + + watcher->Stop(); + base::RunLoop().RunUntilIdle(); +} + +// This test checks that even if ServiceWorkerContextWatcher::Stop() is called +// quickly after Start() is called, the crash (crbug.com/727877) should not +// happen. +TEST_F(ServiceWorkerContextWatcherTest, StopQuickly) { + WatcherCallback watcher_callback; + scoped_refptr<ServiceWorkerContextWatcher> watcher = + watcher_callback.StartWatch(context_wrapper()); + watcher->Stop(); + + int callback_count = watcher_callback.callback_count(); + GURL scope = GURL("https://www1.example.com/"); + GURL script = GURL("https://www1.example.com/worker.js"); + int64_t registration_id = RegisterServiceWorker(scope, script); + ASSERT_NE(kInvalidServiceWorkerRegistrationId, registration_id); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(callback_count, watcher_callback.callback_count()); +} + +// This test checks that any callbacks should not be executed after +// ServiceWorkerContextWatcher::Stop() is called. +TEST_F(ServiceWorkerContextWatcherTest, Race) { + GURL scope = GURL("https://www1.example.com/"); + GURL script = GURL("https://www1.example.com/worker.js"); + int64_t registration_id = RegisterServiceWorker(scope, script); + ASSERT_NE(kInvalidServiceWorkerRegistrationId, registration_id); + base::RunLoop().RunUntilIdle(); + + WatcherCallback watcher_callback; + scoped_refptr<ServiceWorkerContextWatcher> watcher = + watcher_callback.StartWatch(context_wrapper()); + base::RunLoop().RunUntilIdle(); + watcher->Stop(); + + int callback_count = watcher_callback.callback_count(); + base::string16 message(base::ASCIIToUTF16("HELLO")); + ReportError( + watcher, 0 /*version_id*/, + ServiceWorkerContextCoreObserver::ErrorInfo(message, 0, 0, script)); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(callback_count, watcher_callback.callback_count()); +} + +} // namespace content
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc index 5666bde8..b000380fc 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host.cc +++ b/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -6,7 +6,6 @@ #include <utility> -#include "base/debug/crash_logging.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/ptr_util.h" @@ -666,9 +665,6 @@ this, bad_message::SWDH_ENABLE_NAVIGATION_PRELOAD_BAD_REGISTRATION_ID); return; } - // The spec discussion consensus is to reject if there is no active worker: - // https://github.com/w3c/ServiceWorker/issues/920#issuecomment-262212670 - // TODO(falken): Remove this comment when the spec is updated. if (!registration->active_version()) { Send(new ServiceWorkerMsg_EnableNavigationPreloadError( thread_id, request_id, WebServiceWorkerError::kErrorTypeState, @@ -808,9 +804,6 @@ bad_message::SWDH_SET_NAVIGATION_PRELOAD_HEADER_BAD_REGISTRATION_ID); return; } - // The spec discussion consensus is to reject if there is no active worker: - // https://github.com/w3c/ServiceWorker/issues/920#issuecomment-262212670 - // TODO(falken): Remove this comment when the spec is updated. if (!registration->active_version()) { Send(new ServiceWorkerMsg_SetNavigationPreloadHeaderError( thread_id, request_id, WebServiceWorkerError::kErrorTypeState,
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index b4c8e67d..17c5e75 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -566,6 +566,9 @@ blob_context, partition->filesystem_context_); } + partition->appcache_service_->set_url_loader_factory_getter( + partition->url_loader_factory_getter_.get()); + return partition; }
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc index abff384..374c7a0 100644 --- a/content/browser/web_contents/web_contents_view_aura.cc +++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -492,7 +492,7 @@ } // Overridden WindowTreeHostObserver: - void OnHostMovedInPixels(const aura::WindowTreeHost* host, + void OnHostMovedInPixels(aura::WindowTreeHost* host, const gfx::Point& new_origin_in_pixels) override { TRACE_EVENT1("ui", "WebContentsViewAura::WindowObserver::OnHostMovedInPixels",
diff --git a/content/browser/webrtc/webrtc_eventlog_host_unittest.cc b/content/browser/webrtc/webrtc_eventlog_host_unittest.cc index 15c8970..06a39035 100644 --- a/content/browser/webrtc/webrtc_eventlog_host_unittest.cc +++ b/content/browser/webrtc/webrtc_eventlog_host_unittest.cc
@@ -4,6 +4,7 @@ #include "content/browser/webrtc/webrtc_eventlog_host.h" +#include <set> #include <tuple> #include "base/files/file.h" @@ -81,6 +82,23 @@ IPC::PlatformFileForTransitToFile(std::get<1>(start_params)).Close(); } + // This version of the function returns the peer connection ID instead of + // validating it. + int ReadStartIPCMessageAndCloseFile(const IPC::Message* msg) { + EXPECT_TRUE(msg); + if (msg) { + std::tuple<int, IPC::PlatformFileForTransit> start_params; + PeerConnectionTracker_StartEventLog::Read(msg, &start_params); + EXPECT_NE(IPC::InvalidPlatformFileForTransit(), + std::get<1>(start_params)); + if (std::get<1>(start_params) != IPC::InvalidPlatformFileForTransit()) { + IPC::PlatformFileForTransitToFile(std::get<1>(start_params)).Close(); + } + return std::get<0>(start_params); + } + return -1; + } + void ValidateStopIPCMessage(const IPC::Message* msg, const int peer_connection_id) { ASSERT_TRUE(msg); @@ -88,6 +106,18 @@ PeerConnectionTracker_StopEventLog::Read(msg, &stop_params); EXPECT_EQ(peer_connection_id, std::get<0>(stop_params)); } + + // This version of the function returns the peer connection ID instead of + // validating it. + int ReadStopIPCMessage(const IPC::Message* msg) { + EXPECT_TRUE(msg); + if (msg) { + std::tuple<int> stop_params; + PeerConnectionTracker_StopEventLog::Read(msg, &stop_params); + return std::get<0>(stop_params); + } + return -1; + } }; // This test calls StartWebRTCEventLog() and StopWebRTCEventLog() without having @@ -143,14 +173,7 @@ // each of the Start and Stop calls, and that a file is created for both // PeerConnections. -// Test is flaky on Windpws: https://crbug.com/750708 -#if defined(OS_WIN) -#define MAYBE_TwoPeerConnectionsTest DISABLED_TwoPeerConnectionsTest -#else -#define MAYBE_TwoPeerConnectionsTest TwoPeerConnectionsTest -#endif - -TEST_F(WebRtcEventlogHostTest, MAYBE_TwoPeerConnectionsTest) { +TEST_F(WebRtcEventlogHostTest, TwoPeerConnectionsTest) { const int kTestPeerConnectionId1 = 123; const int kTestPeerConnectionId2 = 321; mock_render_process_host_->sink().ClearMessages(); @@ -164,10 +187,15 @@ EXPECT_EQ(size_t(2), mock_render_process_host_->sink().message_count()); const IPC::Message* start_msg1 = mock_render_process_host_->sink().GetMessageAt(0); - ValidateStartIPCMessageAndCloseFile(start_msg1, kTestPeerConnectionId1); + int start_msg1_id = ReadStartIPCMessageAndCloseFile(start_msg1); const IPC::Message* start_msg2 = mock_render_process_host_->sink().GetMessageAt(1); - ValidateStartIPCMessageAndCloseFile(start_msg2, kTestPeerConnectionId2); + int start_msg2_id = ReadStartIPCMessageAndCloseFile(start_msg2); + + const std::set<int> expected_ids = {kTestPeerConnectionId1, + kTestPeerConnectionId2}; + std::set<int> actual_start_ids = {start_msg1_id, start_msg2_id}; + EXPECT_EQ(expected_ids, actual_start_ids); // Stop logging. mock_render_process_host_->sink().ClearMessages(); @@ -177,10 +205,13 @@ EXPECT_EQ(size_t(2), mock_render_process_host_->sink().message_count()); const IPC::Message* stop_msg1 = mock_render_process_host_->sink().GetMessageAt(0); - ValidateStopIPCMessage(stop_msg1, kTestPeerConnectionId1); + int stop_msg1_id = ReadStopIPCMessage(stop_msg1); const IPC::Message* stop_msg2 = mock_render_process_host_->sink().GetMessageAt(1); - ValidateStopIPCMessage(stop_msg2, kTestPeerConnectionId2); + int stop_msg2_id = ReadStopIPCMessage(stop_msg2); + + std::set<int> actual_stop_ids = {stop_msg1_id, stop_msg2_id}; + EXPECT_EQ(expected_ids, actual_stop_ids); // Clean up the logfiles. base::FilePath expected_file1 = GetExpectedEventLogFileName( @@ -198,7 +229,7 @@ // maximum allowed number of IPC messages and log files will be opened, but we // expect the number of stop IPC messages to be equal to the actual number of // PeerConnections. -TEST_F(WebRtcEventlogHostTest, DISABLED_ExceedMaxPeerConnectionsTest) { +TEST_F(WebRtcEventlogHostTest, ExceedMaxPeerConnectionsTest) { #if defined(OS_ANDROID) const int kMaxNumberLogFiles = 3; #else @@ -213,12 +244,18 @@ StartLogging(); // Check that the correct IPC messages were sent. - ASSERT_EQ(size_t(kMaxNumberLogFiles), - mock_render_process_host_->sink().message_count()); - for (int i = 0; i < kMaxNumberLogFiles; ++i) { - const IPC::Message* start_msg = - mock_render_process_host_->sink().GetMessageAt(i); - ValidateStartIPCMessageAndCloseFile(start_msg, i); + { + std::set<int> actual_ids, expected_ids; + ASSERT_EQ(size_t(kMaxNumberLogFiles), + mock_render_process_host_->sink().message_count()); + for (int i = 0; i < kMaxNumberLogFiles; ++i) { + const IPC::Message* start_msg = + mock_render_process_host_->sink().GetMessageAt(i); + int id = ReadStartIPCMessageAndCloseFile(start_msg); + actual_ids.insert(id); + expected_ids.insert(i); + } + EXPECT_EQ(actual_ids, expected_ids); } // Stop logging. @@ -226,12 +263,18 @@ StopLogging(); // Check that the correct IPC messages were sent. - ASSERT_EQ(size_t(kNumberOfPeerConnections), - mock_render_process_host_->sink().message_count()); - for (int i = 0; i < kNumberOfPeerConnections; ++i) { - const IPC::Message* stop_msg = - mock_render_process_host_->sink().GetMessageAt(i); - ValidateStopIPCMessage(stop_msg, i); + { + std::set<int> actual_ids, expected_ids; + ASSERT_EQ(size_t(kNumberOfPeerConnections), + mock_render_process_host_->sink().message_count()); + for (int i = 0; i < kNumberOfPeerConnections; ++i) { + const IPC::Message* stop_msg = + mock_render_process_host_->sink().GetMessageAt(i); + int id = ReadStopIPCMessage(stop_msg); + actual_ids.insert(id); + expected_ids.insert(i); + } + EXPECT_EQ(actual_ids, expected_ids); } // Clean up the logfiles.
diff --git a/content/child/child_process.cc b/content/child/child_process.cc index d3f557e1..b28d6e8 100644 --- a/content/child/child_process.cc +++ b/content/child/child_process.cc
@@ -12,23 +12,12 @@ #include "base/metrics/statistics_recorder.h" #include "base/process/process_handle.h" #include "base/single_thread_task_runner.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/utf_string_conversions.h" #include "base/task_scheduler/task_scheduler.h" #include "base/threading/thread.h" #include "base/threading/thread_local.h" #include "build/build_config.h" #include "content/child/child_thread_impl.h" -#if defined(OS_ANDROID) -#include "base/debug/debugger.h" -#endif - -#if defined(OS_POSIX) && !defined(OS_ANDROID) -#include <signal.h> -static void SigUSR1Handler(int signal) { } -#endif - namespace content { namespace { @@ -145,44 +134,4 @@ return &shutdown_event_; } -void ChildProcess::WaitForDebugger(const std::string& label) { -#if defined(OS_WIN) -#if defined(GOOGLE_CHROME_BUILD) - std::string title = "Google Chrome"; -#else // CHROMIUM_BUILD - std::string title = "Chromium"; -#endif // CHROMIUM_BUILD - title += " "; - title += label; // makes attaching to process easier - std::string message = label; - message += " starting with pid: "; - message += base::IntToString(base::GetCurrentProcId()); - ::MessageBox(NULL, base::UTF8ToWide(message).c_str(), - base::UTF8ToWide(title).c_str(), - MB_OK | MB_SETFOREGROUND); -#elif defined(OS_POSIX) -#if defined(OS_ANDROID) - LOG(ERROR) << label << " waiting for GDB."; - // Wait 24 hours for a debugger to be attached to the current process. - base::debug::WaitForDebugger(24 * 60 * 60, true); -#else - // TODO(playmobil): In the long term, overriding this flag doesn't seem - // right, either use our own flag or open a dialog we can use. - // This is just to ease debugging in the interim. - LOG(ERROR) << label - << " (" - << getpid() - << ") paused waiting for debugger to attach. " - << "Send SIGUSR1 to unpause."; - // Install a signal handler so that pause can be woken. - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = SigUSR1Handler; - sigaction(SIGUSR1, &sa, NULL); - - pause(); -#endif // defined(OS_ANDROID) -#endif // defined(OS_POSIX) -} - } // namespace content
diff --git a/content/child/child_process.h b/content/child/child_process.h index d96e459..7b1426b 100644 --- a/content/child/child_process.h +++ b/content/child/child_process.h
@@ -87,8 +87,6 @@ // on the main thread. static ChildProcess* current(); - static void WaitForDebugger(const std::string& label); - private: int ref_count_;
diff --git a/content/child/loader/cors_url_loader.cc b/content/child/loader/cors_url_loader.cc index 333917f..ae94d0d6 100644 --- a/content/child/loader/cors_url_loader.cc +++ b/content/child/loader/cors_url_loader.cc
@@ -20,6 +20,8 @@ : network_loader_factory_(network_loader_factory), network_client_binding_(this), forwarding_client_(std::move(client)) { + DCHECK(network_loader_factory_); + mojom::URLLoaderClientPtr network_client; network_client_binding_.Bind(mojo::MakeRequest(&network_client)); network_loader_factory_->CreateLoaderAndStart(
diff --git a/content/child/loader/cors_url_loader_factory.cc b/content/child/loader/cors_url_loader_factory.cc index e4848cc..aef3667 100644 --- a/content/child/loader/cors_url_loader_factory.cc +++ b/content/child/loader/cors_url_loader_factory.cc
@@ -16,6 +16,8 @@ PossiblyAssociatedInterfacePtr<mojom::URLLoaderFactory> network_loader_factory, mojom::URLLoaderFactoryRequest request) { + DCHECK(network_loader_factory); + mojo::MakeStrongBinding( base::MakeUnique<CORSURLLoaderFactory>(std::move(network_loader_factory)), std::move(request));
diff --git a/content/common/background_fetch/background_fetch_struct_traits.cc b/content/common/background_fetch/background_fetch_struct_traits.cc index c0f5f30..1fe3b79 100644 --- a/content/common/background_fetch/background_fetch_struct_traits.cc +++ b/content/common/background_fetch/background_fetch_struct_traits.cc
@@ -28,7 +28,7 @@ content::BackgroundFetchRegistration>:: Read(blink::mojom::BackgroundFetchRegistrationDataView data, content::BackgroundFetchRegistration* registration) { - if (!data.ReadTag(®istration->tag) || + if (!data.ReadId(®istration->id) || !data.ReadIcons(®istration->icons) || !data.ReadTitle(®istration->title)) { return false;
diff --git a/content/common/background_fetch/background_fetch_struct_traits.h b/content/common/background_fetch/background_fetch_struct_traits.h index d1d3ee35..2f2c67a 100644 --- a/content/common/background_fetch/background_fetch_struct_traits.h +++ b/content/common/background_fetch/background_fetch_struct_traits.h
@@ -45,9 +45,9 @@ struct CONTENT_EXPORT StructTraits<blink::mojom::BackgroundFetchRegistrationDataView, content::BackgroundFetchRegistration> { - static const std::string& tag( + static const std::string& id( const content::BackgroundFetchRegistration& registration) { - return registration.tag; + return registration.id; } static const std::vector<content::IconDefinition>& icons( const content::BackgroundFetchRegistration& registration) {
diff --git a/content/common/background_fetch/background_fetch_struct_traits_unittest.cc b/content/common/background_fetch/background_fetch_struct_traits_unittest.cc index 92a6aa9..c44f4ae 100644 --- a/content/common/background_fetch/background_fetch_struct_traits_unittest.cc +++ b/content/common/background_fetch/background_fetch_struct_traits_unittest.cc
@@ -59,7 +59,7 @@ TEST(BackgroundFetchStructTraitsTest, BackgroundFetchRegistrationRoundTrip) { BackgroundFetchRegistration registration; - registration.tag = "my_tag"; + registration.id = "my_id"; registration.icons = { CreateIconDefinition("my_icon.png", "256x256", "image/png"), CreateIconDefinition("my_small_icon.jpg", "128x128", "image/jpg")}; @@ -71,7 +71,7 @@ blink::mojom::BackgroundFetchRegistration::Serialize(®istration), &roundtrip_registration)); - EXPECT_EQ(roundtrip_registration.tag, registration.tag); + EXPECT_EQ(roundtrip_registration.id, registration.id); ASSERT_EQ(roundtrip_registration.icons.size(), registration.icons.size()); for (size_t i = 0; i < registration.icons.size(); ++i) {
diff --git a/content/common/background_fetch/background_fetch_types.h b/content/common/background_fetch/background_fetch_types.h index 263cfa6..92860002 100644 --- a/content/common/background_fetch/background_fetch_types.h +++ b/content/common/background_fetch/background_fetch_types.h
@@ -52,7 +52,7 @@ BackgroundFetchRegistration(const BackgroundFetchRegistration& other); ~BackgroundFetchRegistration(); - std::string tag; + std::string id; std::vector<IconDefinition> icons; std::string title; int64_t total_download_size = 0;
diff --git a/content/common/content_switches_internal.cc b/content/common/content_switches_internal.cc index 0752026..8294762 100644 --- a/content/common/content_switches_internal.cc +++ b/content/common/content_switches_internal.cc
@@ -9,9 +9,20 @@ #include "base/command_line.h" #include "base/feature_list.h" #include "base/metrics/field_trial.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "content/public/common/content_switches.h" +#if defined(OS_ANDROID) +#include "base/debug/debugger.h" +#endif + +#if defined(OS_POSIX) && !defined(OS_ANDROID) +#include <signal.h> +static void SigUSR1Handler(int signal) {} +#endif + #if defined(OS_WIN) #include "base/win/windows_version.h" #endif @@ -122,4 +133,41 @@ return ProgressBarCompletion::LOAD_EVENT; } +void WaitForDebugger(const std::string& label) { +#if defined(OS_WIN) +#if defined(GOOGLE_CHROME_BUILD) + std::string title = "Google Chrome"; +#else // CHROMIUM_BUILD + std::string title = "Chromium"; +#endif // CHROMIUM_BUILD + title += " "; + title += label; // makes attaching to process easier + std::string message = label; + message += " starting with pid: "; + message += base::IntToString(base::GetCurrentProcId()); + ::MessageBox(NULL, base::UTF8ToWide(message).c_str(), + base::UTF8ToWide(title).c_str(), MB_OK | MB_SETFOREGROUND); +#elif defined(OS_POSIX) +#if defined(OS_ANDROID) + LOG(ERROR) << label << " waiting for GDB."; + // Wait 24 hours for a debugger to be attached to the current process. + base::debug::WaitForDebugger(24 * 60 * 60, true); +#else + // TODO(playmobil): In the long term, overriding this flag doesn't seem + // right, either use our own flag or open a dialog we can use. + // This is just to ease debugging in the interim. + LOG(ERROR) << label << " (" << getpid() + << ") paused waiting for debugger to attach. " + << "Send SIGUSR1 to unpause."; + // Install a signal handler so that pause can be woken. + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SigUSR1Handler; + sigaction(SIGUSR1, &sa, NULL); + + pause(); +#endif // defined(OS_ANDROID) +#endif // defined(OS_POSIX) +} + } // namespace content
diff --git a/content/common/content_switches_internal.h b/content/common/content_switches_internal.h index 024a4d7..8f1a5b8e36 100644 --- a/content/common/content_switches_internal.h +++ b/content/common/content_switches_internal.h
@@ -22,6 +22,8 @@ CONTENT_EXPORT bool IsUseZoomForDSFEnabled(); +void WaitForDebugger(const std::string& label); + } // namespace content #endif // CONTENT_COMMON_CONTENT_SWITCHES_INTERNAL_H_
diff --git a/content/common/net_adapters.cc b/content/common/net_adapters.cc index 589f081..504f389 100644 --- a/content/common/net_adapters.cc +++ b/content/common/net_adapters.cc
@@ -52,4 +52,51 @@ NetToMojoIOBuffer::~NetToMojoIOBuffer() {} +MojoToNetPendingBuffer::MojoToNetPendingBuffer( + mojo::ScopedDataPipeConsumerHandle handle, + const void* buffer) + : handle_(std::move(handle)), buffer_(buffer) {} + +MojoToNetPendingBuffer::~MojoToNetPendingBuffer() {} + +// static +MojoResult MojoToNetPendingBuffer::BeginRead( + mojo::ScopedDataPipeConsumerHandle* handle, + scoped_refptr<MojoToNetPendingBuffer>* pending, + uint32_t* num_bytes) { + const void* buffer = NULL; + *num_bytes = 0; + MojoResult result = + (*handle)->BeginReadData(&buffer, num_bytes, MOJO_READ_DATA_FLAG_NONE); + if (result == MOJO_RESULT_OK) + *pending = new MojoToNetPendingBuffer(std::move(*handle), buffer); + return result; +} + +void MojoToNetPendingBuffer::CompleteRead(uint32_t num_bytes) { + handle_->EndReadData(num_bytes); + buffer_ = NULL; +} + +mojo::ScopedDataPipeConsumerHandle MojoToNetPendingBuffer::ReleaseHandle() { + DCHECK(IsComplete()); + return std::move(handle_); +} + +bool MojoToNetPendingBuffer::IsComplete() const { + return buffer_ == nullptr; +} + +MojoToNetIOBuffer::MojoToNetIOBuffer(MojoToNetPendingBuffer* pending_buffer, + int bytes_to_be_read) + : net::WrappedIOBuffer(pending_buffer->buffer()), + pending_buffer_(pending_buffer), + bytes_to_be_read_(bytes_to_be_read) {} + +MojoToNetIOBuffer::~MojoToNetIOBuffer() { + // We can safely notify mojo, that the data has been consumed and can be + // released at this point. + pending_buffer_->CompleteRead(bytes_to_be_read_); +} + } // namespace content
diff --git a/content/common/net_adapters.h b/content/common/net_adapters.h index 5c65d9fe..f9955c13 100644 --- a/content/common/net_adapters.h +++ b/content/common/net_adapters.h
@@ -18,6 +18,7 @@ // // Mojo pipe Data flow Network library // ---------------------------------------------------------- +// MojoToNetPendingBuffer ---> MojoToNetIOBuffer // NetToMojoPendingBuffer <--- NetToMojoIOBuffer // // While the operation is in progress, the Mojo-side objects keep ownership @@ -70,6 +71,66 @@ DISALLOW_COPY_AND_ASSIGN(NetToMojoIOBuffer); }; +class MojoToNetPendingBuffer + : public base::RefCountedThreadSafe<MojoToNetPendingBuffer> { + public: + // Starts reading from Mojo. + // + // On success, MOJO_RESULT_OK will be returned. The ownership of the given + // consumer handle will be transferred to the new MojoToNetPendingBuffer that + // will be placed into *pending, and the size of the buffer will be in + // *num_bytes. + // + // On failure or MOJO_RESULT_SHOULD_WAIT, there will be no change to the + // handle, and *pending and *num_bytes will be unused. + static MojoResult BeginRead(mojo::ScopedDataPipeConsumerHandle* handle, + scoped_refptr<MojoToNetPendingBuffer>* pending, + uint32_t* num_bytes); + + // Indicates the buffer is done being read from. The argument is the number + // of bytes actually read, since net may do partial writes, which will result + // in partial reads from the Mojo pipe's perspective. + void CompleteRead(uint32_t num_bytes); + + // Releases ownership of the pipe handle and returns it. + mojo::ScopedDataPipeConsumerHandle ReleaseHandle(); + + // Returns true if the data was successfully read from the Mojo pipe. We + // assume that if the buffer_ is null, data was read from the pipe. + bool IsComplete() const; + + const char* buffer() { return static_cast<const char*>(buffer_); } + + private: + friend class base::RefCountedThreadSafe<MojoToNetPendingBuffer>; + + // Takes ownership of the handle. + explicit MojoToNetPendingBuffer(mojo::ScopedDataPipeConsumerHandle handle, + const void* buffer); + ~MojoToNetPendingBuffer(); + + mojo::ScopedDataPipeConsumerHandle handle_; + const void* buffer_; + + DISALLOW_COPY_AND_ASSIGN(MojoToNetPendingBuffer); +}; + +// Net side of a Mojo -> Net copy. The data will already be in the +// MojoToNetPendingBuffer's buffer. +class MojoToNetIOBuffer : public net::WrappedIOBuffer { + public: + // |bytes_to_be_read| contains the number of bytes expected to be read by + // the consumer. + MojoToNetIOBuffer(MojoToNetPendingBuffer* pending_buffer, + int bytes_to_be_read); + + private: + ~MojoToNetIOBuffer() override; + + scoped_refptr<MojoToNetPendingBuffer> pending_buffer_; + int bytes_to_be_read_; +}; + } // namespace content #endif // CONTENT_COMMON_NET_ADAPTERS_
diff --git a/content/common/service_worker/service_worker_event_dispatcher.mojom b/content/common/service_worker/service_worker_event_dispatcher.mojom index 6c24be7..96ec145 100644 --- a/content/common/service_worker/service_worker_event_dispatcher.mojom +++ b/content/common/service_worker/service_worker_event_dispatcher.mojom
@@ -93,17 +93,17 @@ DispatchActivateEvent() => (blink.mojom.ServiceWorkerEventStatus status, mojo.common.mojom.Time dispatch_event_time); - DispatchBackgroundFetchAbortEvent(string tag) + DispatchBackgroundFetchAbortEvent(string id) => (blink.mojom.ServiceWorkerEventStatus status, mojo.common.mojom.Time dispatch_event_time); - DispatchBackgroundFetchClickEvent(string tag, BackgroundFetchState state) + DispatchBackgroundFetchClickEvent(string id, BackgroundFetchState state) => (blink.mojom.ServiceWorkerEventStatus status, mojo.common.mojom.Time dispatch_event_time); - DispatchBackgroundFetchFailEvent(string tag, + DispatchBackgroundFetchFailEvent(string id, array<BackgroundFetchSettledFetch> fetches) => (blink.mojom.ServiceWorkerEventStatus status, mojo.common.mojom.Time dispatch_event_time); - DispatchBackgroundFetchedEvent(string tag, + DispatchBackgroundFetchedEvent(string id, array<BackgroundFetchSettledFetch> fetches) => (blink.mojom.ServiceWorkerEventStatus status, mojo.common.mojom.Time dispatch_event_time); @@ -134,7 +134,7 @@ mojo.common.mojom.Time dispatch_event_time); // Arguments are passed to the event handler as parameters of SyncEvent. // Ref: https://wicg.github.io/BackgroundSync/spec/#sync-event - DispatchSyncEvent(string tag, + DispatchSyncEvent(string id, blink.mojom.BackgroundSyncEventLastChance last_chance) => (blink.mojom.ServiceWorkerEventStatus status, mojo.common.mojom.Time dispatch_event_time);
diff --git a/content/common/service_worker/service_worker_utils.cc b/content/common/service_worker/service_worker_utils.cc index 9ad5aaf..56fead10 100644 --- a/content/common/service_worker/service_worker_utils.cc +++ b/content/common/service_worker/service_worker_utils.cc
@@ -71,7 +71,7 @@ } max_scope_string = max_scope.path(); } else { - max_scope_string = script_url.Resolve(".").path(); + max_scope_string = script_url.GetWithoutFilename().path(); } std::string scope_string = scope.path();
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc index 4b87a8c8..453ee7c 100644 --- a/content/gpu/gpu_main.cc +++ b/content/gpu/gpu_main.cc
@@ -21,8 +21,8 @@ #include "base/timer/hi_res_timer_manager.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" -#include "content/child/child_process.h" #include "content/common/content_constants_internal.h" +#include "content/common/content_switches_internal.h" #include "content/gpu/gpu_child_thread.h" #include "content/gpu/gpu_process.h" #include "content/public/common/content_client.h" @@ -175,9 +175,8 @@ kTraceEventGpuProcessSortIndex); const base::CommandLine& command_line = parameters.command_line; - if (command_line.HasSwitch(switches::kGpuStartupDialog)) { - ChildProcess::WaitForDebugger("Gpu"); - } + if (command_line.HasSwitch(switches::kGpuStartupDialog)) + WaitForDebugger("Gpu"); base::Time start_time = base::Time::Now();
diff --git a/content/network/url_loader_impl.cc b/content/network/url_loader_impl.cc index 4bca06c..1074715e 100644 --- a/content/network/url_loader_impl.cc +++ b/content/network/url_loader_impl.cc
@@ -333,6 +333,7 @@ } void URLLoaderImpl::DidRead(uint32_t num_bytes, bool completed_synchronously) { + total_written_bytes_ += num_bytes; pending_write_buffer_offset_ += num_bytes; DCHECK(url_request_->status().is_success()); bool complete_read = true; @@ -398,6 +399,7 @@ request_complete_data.encoded_data_length = url_request_->GetTotalReceivedBytes(); request_complete_data.encoded_body_length = url_request_->GetRawBodyBytes(); + request_complete_data.decoded_body_length = total_written_bytes_; url_loader_client_->OnComplete(request_complete_data); DeleteIfNeeded();
diff --git a/content/network/url_loader_impl.h b/content/network/url_loader_impl.h index 81509eb7..914e29f 100644 --- a/content/network/url_loader_impl.h +++ b/content/network/url_loader_impl.h
@@ -69,6 +69,7 @@ std::unique_ptr<net::URLRequest> url_request_; mojo::Binding<mojom::URLLoader> binding_; mojom::URLLoaderClientPtr url_loader_client_; + int64_t total_written_bytes_ = 0; mojo::ScopedDataPipeProducerHandle response_body_stream_; scoped_refptr<NetToMojoPendingBuffer> pending_write_;
diff --git a/content/ppapi_plugin/ppapi_broker_main.cc b/content/ppapi_plugin/ppapi_broker_main.cc index f0e107f..4ff86832 100644 --- a/content/ppapi_plugin/ppapi_broker_main.cc +++ b/content/ppapi_plugin/ppapi_broker_main.cc
@@ -8,6 +8,7 @@ #include "build/build_config.h" #include "content/child/child_process.h" #include "content/common/content_constants_internal.h" +#include "content/common/content_switches_internal.h" #include "content/ppapi_plugin/ppapi_thread.h" #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" @@ -17,9 +18,8 @@ // Main function for starting the PPAPI broker process. int PpapiBrokerMain(const MainFunctionParams& parameters) { const base::CommandLine& command_line = parameters.command_line; - if (command_line.HasSwitch(switches::kPpapiStartupDialog)) { - ChildProcess::WaitForDebugger("PpapiBroker"); - } + if (command_line.HasSwitch(switches::kPpapiStartupDialog)) + WaitForDebugger("PpapiBroker"); base::MessageLoop main_message_loop; base::PlatformThread::SetName("CrPPAPIBrokerMain");
diff --git a/content/ppapi_plugin/ppapi_plugin_main.cc b/content/ppapi_plugin/ppapi_plugin_main.cc index 146a4ff4..0ebaeb5 100644 --- a/content/ppapi_plugin/ppapi_plugin_main.cc +++ b/content/ppapi_plugin/ppapi_plugin_main.cc
@@ -16,6 +16,7 @@ #include "build/build_config.h" #include "content/child/child_process.h" #include "content/common/content_constants_internal.h" +#include "content/common/content_switches_internal.h" #include "content/ppapi_plugin/ppapi_thread.h" #include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" @@ -70,13 +71,12 @@ #endif // If |g_target_services| is not null this process is sandboxed. One side - // effect is that we can't pop dialogs like ChildProcess::WaitForDebugger() - // does. + // effect is that we can't pop dialogs like WaitForDebugger() does. if (command_line.HasSwitch(switches::kPpapiStartupDialog)) { if (g_target_services) base::debug::WaitForDebugger(2*60, false); else - ChildProcess::WaitForDebugger("Ppapi"); + WaitForDebugger("Ppapi"); } // Set the default locale to be the current UI language. WebKit uses ICU's
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/SuggestionsPopupWindow.java b/content/public/android/java/src/org/chromium/content/browser/input/SuggestionsPopupWindow.java index 19d8d9c..036efba 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/SuggestionsPopupWindow.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/SuggestionsPopupWindow.java
@@ -87,14 +87,22 @@ mPopupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT); mPopupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + // Set the background on the PopupWindow instead of on mContentView (where we set it for + // pre-Lollipop) since the popup will not properly dismiss on pre-Marshmallow unless it + // has a background set. + mPopupWindow.setBackgroundDrawable(ApiCompatibilityUtils.getDrawable( + mContext.getResources(), R.drawable.floating_popup_background_light)); // On Lollipop and later, we use elevation to create a drop shadow effect. - // On pre-Lollipop, we use a background image instead (in the layout file). + // On pre-Lollipop, we instead use a background image on mContentView (in + // initContentView). mPopupWindow.setElevation(mContext.getResources().getDimensionPixelSize( R.dimen.text_suggestion_popup_elevation)); } else { - // The PopupWindow does not properly dismiss on Jelly Bean without the following line. + // The PopupWindow does not properly dismiss pre-Marshmallow unless it has a background + // set. mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); } + mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); mPopupWindow.setFocusable(true); mPopupWindow.setClippingEnabled(false); @@ -107,10 +115,9 @@ mContentView = (LinearLayout) inflater.inflate(R.layout.text_edit_suggestion_container, null); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - mContentView.setBackground(ApiCompatibilityUtils.getDrawable( - mContext.getResources(), R.drawable.floating_popup_background_light)); - } else { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + // Set this on the content view instead of on the PopupWindow so we can retrieve the + // padding later. mContentView.setBackground(ApiCompatibilityUtils.getDrawable( mContext.getResources(), R.drawable.dropdown_popup_background)); }
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index f2b89f1..1380274 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -412,6 +412,10 @@ // Controls whether the WebNFC API is enabled: // https://w3c.github.io/web-nfc/ const base::Feature kWebNfc{"WebNFC", base::FEATURE_DISABLED_BY_DEFAULT}; + +// Enables WebVR VSync-aligned render loop timing. +const base::Feature kWebVrVsyncAlign{"WebVrVsyncAlign", + base::FEATURE_ENABLED_BY_DEFAULT}; #endif // defined(OS_ANDROID) #if defined(OS_WIN)
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 56c58f9f..371fda86 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -104,6 +104,7 @@ CONTENT_EXPORT extern const base::Feature kImeThread; CONTENT_EXPORT extern const base::Feature kServiceWorkerPaymentApps; CONTENT_EXPORT extern const base::Feature kWebNfc; +CONTENT_EXPORT extern const base::Feature kWebVrVsyncAlign; #endif // defined(OS_ANDROID) #if defined(OS_WIN)
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index b138b2a1..095c779 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc
@@ -64,6 +64,9 @@ // Causes the browser process to crash on startup. const char kBrowserCrashTest[] = "crash-test"; +// Causes the browser process to display a dialog on launch. +const char kBrowserStartupDialog[] = "browser-startup-dialog"; + // Path to the exe to run for the renderer and plugin subprocesses. const char kBrowserSubprocessPath[] = "browser-subprocess-path"; @@ -904,6 +907,9 @@ const char kUtilityProcessRunningElevated[] = "utility-run-elevated"; +// Causes the utility process to display a dialog on launch. +const char kUtilityStartupDialog[] = "utility-startup-dialog"; + // In debug builds, asserts that the stream of input events is valid. const char kValidateInputEventStream[] = "validate-input-event-stream";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index 7d574279..d9cb66d9 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h
@@ -26,6 +26,7 @@ CONTENT_EXPORT extern const char kAndroidFontsPath[]; CONTENT_EXPORT extern const char kBlinkSettings[]; CONTENT_EXPORT extern const char kBrowserCrashTest[]; +CONTENT_EXPORT extern const char kBrowserStartupDialog[]; CONTENT_EXPORT extern const char kBrowserSubprocessPath[]; CONTENT_EXPORT extern const char kDefaultTileWidth[]; CONTENT_EXPORT extern const char kDefaultTileHeight[]; @@ -249,6 +250,7 @@ CONTENT_EXPORT extern const char kUtilityProcess[]; extern const char kUtilityProcessAllowedDir[]; CONTENT_EXPORT extern const char kUtilityProcessRunningElevated[]; +CONTENT_EXPORT extern const char kUtilityStartupDialog[]; CONTENT_EXPORT extern const char kV8CacheOptions[]; CONTENT_EXPORT extern const char kV8CacheStrategiesForCacheStorage[]; CONTENT_EXPORT extern const char kValidateInputEventStream[];
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index c633690..49c519e6 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -973,8 +973,8 @@ if (enable_mojo_media) { sources += [ - "media/media_interface_provider.cc", - "media/media_interface_provider.h", + "media/media_interface_factory.cc", + "media/media_interface_factory.h", ] }
diff --git a/content/renderer/accessibility/blink_ax_tree_source.cc b/content/renderer/accessibility/blink_ax_tree_source.cc index 4994796..b53793d 100644 --- a/content/renderer/accessibility/blink_ax_tree_source.cc +++ b/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -842,11 +842,15 @@ } if (src.IsEditable()) { + if (src.IsEditableRoot()) + dst->AddBoolAttribute(ui::AX_ATTR_EDITABLE_ROOT, true); + if (src.IsControl() && !src.IsRichlyEditable()) { // Only for simple input controls -- rich editable areas use AXTreeData dst->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_START, src.SelectionStart()); dst->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_END, src.SelectionEnd()); } + #if defined(OS_CHROMEOS) // This attribute will soon be deprecated; see crbug.com/669134. WebVector<int> src_line_breaks;
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index 2ca9859..1647846 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -186,6 +186,7 @@ cc_bound.layer_id = web_bound.layer_id; cc_bound.edge_top = gfx::Point(web_bound.edge_top_in_layer); cc_bound.edge_bottom = gfx::Point(web_bound.edge_bottom_in_layer); + cc_bound.hidden = web_bound.hidden; return cc_bound; }
diff --git a/content/renderer/media/media_factory.cc b/content/renderer/media/media_factory.cc index 5aa742a..358d319 100644 --- a/content/renderer/media/media_factory.cc +++ b/content/renderer/media/media_factory.cc
@@ -46,7 +46,7 @@ #endif #if BUILDFLAG(ENABLE_MOJO_MEDIA) -#include "content/renderer/media/media_interface_provider.h" +#include "content/renderer/media/media_interface_factory.h" #endif #if BUILDFLAG(ENABLE_MOJO_CDM) @@ -334,7 +334,7 @@ base::MakeUnique<media::MojoRendererFactory>( base::Bind(&RenderThreadImpl::GetGpuFactories, base::Unretained(render_thread)), - GetMediaInterfaceProvider())); + GetMediaInterfaceFactory())); factory_selector->SetBaseFactoryType( media::RendererFactorySelector::FactoryType::MOJO); @@ -436,7 +436,7 @@ #if BUILDFLAG(ENABLE_MOJO_AUDIO_DECODER) || BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) if (!decoder_factory_) { decoder_factory_.reset( - new media::MojoDecoderFactory(GetMediaInterfaceProvider())); + new media::MojoDecoderFactory(GetMediaInterfaceFactory())); } #endif return decoder_factory_.get(); @@ -472,13 +472,13 @@ BUILDFLAG(ENABLE_MOJO_CDM), "Mojo CDM should always be enabled when library CDM is enabled"); if (base::FeatureList::IsEnabled(media::kMojoCdm)) { - cdm_factory_.reset(new media::MojoCdmFactory(GetMediaInterfaceProvider())); + cdm_factory_.reset(new media::MojoCdmFactory(GetMediaInterfaceFactory())); } else { cdm_factory_.reset(new RenderCdmFactory( base::Bind(&PepperCdmWrapperImpl::Create, web_frame))); } #elif BUILDFLAG(ENABLE_MOJO_CDM) - cdm_factory_.reset(new media::MojoCdmFactory(GetMediaInterfaceProvider())); + cdm_factory_.reset(new media::MojoCdmFactory(GetMediaInterfaceFactory())); #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) #if BUILDFLAG(ENABLE_MEDIA_REMOTING) @@ -491,15 +491,14 @@ } #if BUILDFLAG(ENABLE_MOJO_MEDIA) -service_manager::mojom::InterfaceProvider* -MediaFactory::GetMediaInterfaceProvider() { - if (!media_interface_provider_) { +media::mojom::InterfaceFactory* MediaFactory::GetMediaInterfaceFactory() { + if (!media_interface_factory_) { DCHECK(remote_interfaces_); - media_interface_provider_.reset( - new MediaInterfaceProvider(remote_interfaces_)); + media_interface_factory_.reset( + new MediaInterfaceFactory(remote_interfaces_)); } - return media_interface_provider_.get(); + return media_interface_factory_.get(); } #endif // BUILDFLAG(ENABLE_MOJO_MEDIA)
diff --git a/content/renderer/media/media_factory.h b/content/renderer/media/media_factory.h index d990458..42044a1 100644 --- a/content/renderer/media/media_factory.h +++ b/content/renderer/media/media_factory.h
@@ -22,6 +22,10 @@ #include "third_party/WebKit/public/platform/WebString.h" #include "url/gurl.h" +#if BUILDFLAG(ENABLE_MOJO_MEDIA) +#include "media/mojo/interfaces/interface_factory.mojom.h" // nogncheck +#endif + namespace blink { class WebContentDecryptionModule; class WebEncryptedMediaClient; @@ -57,7 +61,7 @@ namespace content { class RenderFrameImpl; -class MediaInterfaceProvider; +class MediaInterfaceFactory; class MediaStreamRendererFactory; #if defined(OS_ANDROID) @@ -134,10 +138,10 @@ media::CdmFactory* GetCdmFactory(); #if BUILDFLAG(ENABLE_MOJO_MEDIA) - service_manager::mojom::InterfaceProvider* GetMediaInterfaceProvider(); + media::mojom::InterfaceFactory* GetMediaInterfaceFactory(); // The media interface provider attached to this frame, lazily initialized. - std::unique_ptr<MediaInterfaceProvider> media_interface_provider_; + std::unique_ptr<MediaInterfaceFactory> media_interface_factory_; #endif // The render frame we're helping. RenderFrameImpl owns this factory, so the
diff --git a/content/renderer/media/media_interface_factory.cc b/content/renderer/media/media_interface_factory.cc new file mode 100644 index 0000000..f050989 --- /dev/null +++ b/content/renderer/media/media_interface_factory.cc
@@ -0,0 +1,104 @@ +// 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 "content/renderer/media/media_interface_factory.h" + +#include <string> + +#include "base/bind.h" +#include "media/mojo/interfaces/content_decryption_module.mojom.h" +#include "media/mojo/interfaces/renderer.mojom.h" +#include "mojo/public/cpp/bindings/interface_request.h" +#include "services/service_manager/public/cpp/interface_provider.h" + +namespace content { + +MediaInterfaceFactory::MediaInterfaceFactory( + service_manager::InterfaceProvider* remote_interfaces) + : remote_interfaces_(remote_interfaces), weak_factory_(this) { + task_runner_ = base::ThreadTaskRunnerHandle::Get(); + weak_this_ = weak_factory_.GetWeakPtr(); +} + +MediaInterfaceFactory::~MediaInterfaceFactory() { + DCHECK(task_runner_->BelongsToCurrentThread()); +} + +void MediaInterfaceFactory::CreateAudioDecoder( + media::mojom::AudioDecoderRequest request) { + if (!task_runner_->BelongsToCurrentThread()) { + task_runner_->PostTask( + FROM_HERE, base::BindOnce(&MediaInterfaceFactory::CreateAudioDecoder, + weak_this_, std::move(request))); + return; + } + + DVLOG(1) << __func__; + GetMediaInterfaceFactory()->CreateAudioDecoder(std::move(request)); +} + +void MediaInterfaceFactory::CreateVideoDecoder( + media::mojom::VideoDecoderRequest request) { + if (!task_runner_->BelongsToCurrentThread()) { + task_runner_->PostTask( + FROM_HERE, base::BindOnce(&MediaInterfaceFactory::CreateVideoDecoder, + weak_this_, std::move(request))); + return; + } + + DVLOG(1) << __func__; + GetMediaInterfaceFactory()->CreateVideoDecoder(std::move(request)); +} + +void MediaInterfaceFactory::CreateRenderer( + const std::string& audio_device_id, + media::mojom::RendererRequest request) { + if (!task_runner_->BelongsToCurrentThread()) { + task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&MediaInterfaceFactory::CreateRenderer, weak_this_, + audio_device_id, std::move(request))); + return; + } + + DVLOG(1) << __func__; + GetMediaInterfaceFactory()->CreateRenderer(audio_device_id, + std::move(request)); +} + +void MediaInterfaceFactory::CreateCdm( + media::mojom::ContentDecryptionModuleRequest request) { + if (!task_runner_->BelongsToCurrentThread()) { + task_runner_->PostTask( + FROM_HERE, base::BindOnce(&MediaInterfaceFactory::CreateCdm, weak_this_, + std::move(request))); + return; + } + + DVLOG(1) << __func__; + GetMediaInterfaceFactory()->CreateCdm(std::move(request)); +} + +media::mojom::InterfaceFactory* +MediaInterfaceFactory::GetMediaInterfaceFactory() { + DVLOG(1) << __func__; + DCHECK(task_runner_->BelongsToCurrentThread()); + + if (!media_interface_factory_) { + remote_interfaces_->GetInterface(&media_interface_factory_); + media_interface_factory_.set_connection_error_handler(base::Bind( + &MediaInterfaceFactory::OnConnectionError, base::Unretained(this))); + } + + return media_interface_factory_.get(); +} + +void MediaInterfaceFactory::OnConnectionError() { + DVLOG(1) << __func__; + DCHECK(task_runner_->BelongsToCurrentThread()); + + media_interface_factory_.reset(); +} + +} // namespace content
diff --git a/content/renderer/media/media_interface_factory.h b/content/renderer/media/media_interface_factory.h new file mode 100644 index 0000000..7ff4f444 --- /dev/null +++ b/content/renderer/media/media_interface_factory.h
@@ -0,0 +1,55 @@ +// 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 CONTENT_RENDERER_MEDIA_MEDIA_INTERFACE_FACTORY_H_ +#define CONTENT_RENDERER_MEDIA_MEDIA_INTERFACE_FACTORY_H_ + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.h" +#include "content/common/content_export.h" +#include "media/mojo/interfaces/interface_factory.mojom.h" +#include "url/gurl.h" + +namespace service_manager { +class InterfaceProvider; +} + +namespace content { + +// MediaInterfaceFactory is an implementation of media::mojom::InterfaceFactory +// that provides thread safety and handles disconnection error automatically. +// The Create* methods can be called on any thread. +class CONTENT_EXPORT MediaInterfaceFactory + : public media::mojom::InterfaceFactory { + public: + explicit MediaInterfaceFactory( + service_manager::InterfaceProvider* remote_interfaces); + ~MediaInterfaceFactory() final; + + // media::mojom::InterfaceFactory implementation. + void CreateAudioDecoder(media::mojom::AudioDecoderRequest request) final; + void CreateVideoDecoder(media::mojom::VideoDecoderRequest request) final; + void CreateRenderer(const std::string& audio_device_id, + media::mojom::RendererRequest request) final; + void CreateCdm(media::mojom::ContentDecryptionModuleRequest request) final; + + private: + media::mojom::InterfaceFactory* GetMediaInterfaceFactory(); + void OnConnectionError(); + + service_manager::InterfaceProvider* remote_interfaces_; + media::mojom::InterfaceFactoryPtr media_interface_factory_; + + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + base::WeakPtr<MediaInterfaceFactory> weak_this_; + base::WeakPtrFactory<MediaInterfaceFactory> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(MediaInterfaceFactory); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_MEDIA_INTERFACE_FACTORY_H_
diff --git a/content/renderer/media/media_interface_provider.cc b/content/renderer/media/media_interface_provider.cc deleted file mode 100644 index 1fe6b49..0000000 --- a/content/renderer/media/media_interface_provider.cc +++ /dev/null
@@ -1,78 +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 "content/renderer/media/media_interface_provider.h" - -#include <string> - -#include "base/bind.h" -#include "media/mojo/interfaces/content_decryption_module.mojom.h" -#include "media/mojo/interfaces/renderer.mojom.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "services/service_manager/public/cpp/interface_provider.h" - -namespace content { - -MediaInterfaceProvider::MediaInterfaceProvider( - service_manager::InterfaceProvider* remote_interfaces) - : remote_interfaces_(remote_interfaces), weak_factory_(this) { - task_runner_ = base::ThreadTaskRunnerHandle::Get(); - weak_this_ = weak_factory_.GetWeakPtr(); -} - -MediaInterfaceProvider::~MediaInterfaceProvider() { - DCHECK(task_runner_->BelongsToCurrentThread()); -} - -void MediaInterfaceProvider::GetInterface(const std::string& interface_name, - mojo::ScopedMessagePipeHandle pipe) { - DVLOG(1) << __func__; - if (!task_runner_->BelongsToCurrentThread()) { - task_runner_->PostTask( - FROM_HERE, base::Bind(&MediaInterfaceProvider::GetInterface, weak_this_, - interface_name, base::Passed(&pipe))); - return; - } - - DCHECK(task_runner_->BelongsToCurrentThread()); - - if (interface_name == media::mojom::ContentDecryptionModule::Name_) { - GetMediaInterfaceFactory()->CreateCdm( - media::mojom::ContentDecryptionModuleRequest(std::move(pipe))); - } else if (interface_name == media::mojom::Renderer::Name_) { - GetMediaInterfaceFactory()->CreateRenderer( - std::string(), media::mojom::RendererRequest(std::move(pipe))); - } else if (interface_name == media::mojom::AudioDecoder::Name_) { - GetMediaInterfaceFactory()->CreateAudioDecoder( - media::mojom::AudioDecoderRequest(std::move(pipe))); - } else if (interface_name == media::mojom::VideoDecoder::Name_) { - GetMediaInterfaceFactory()->CreateVideoDecoder( - media::mojom::VideoDecoderRequest(std::move(pipe))); - } else { - NOTREACHED(); - } -} - -media::mojom::InterfaceFactory* -MediaInterfaceProvider::GetMediaInterfaceFactory() { - DVLOG(1) << __func__; - DCHECK(task_runner_->BelongsToCurrentThread()); - - if (!media_interface_factory_) { - remote_interfaces_->GetInterface(&media_interface_factory_); - media_interface_factory_.set_connection_error_handler(base::Bind( - &MediaInterfaceProvider::OnConnectionError, base::Unretained(this))); - } - - return media_interface_factory_.get(); -} - -void MediaInterfaceProvider::OnConnectionError() { - DVLOG(1) << __func__; - DCHECK(task_runner_->BelongsToCurrentThread()); - - media_interface_factory_.reset(); -} - -} // namespace content
diff --git a/content/renderer/media/media_interface_provider.h b/content/renderer/media/media_interface_provider.h deleted file mode 100644 index 532bb4ca..0000000 --- a/content/renderer/media/media_interface_provider.h +++ /dev/null
@@ -1,53 +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 CONTENT_RENDERER_MEDIA_MEDIA_INTERFACE_PROVIDER_H_ -#define CONTENT_RENDERER_MEDIA_MEDIA_INTERFACE_PROVIDER_H_ - -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/single_thread_task_runner.h" -#include "content/common/content_export.h" -#include "media/mojo/interfaces/interface_factory.mojom.h" -#include "services/service_manager/public/interfaces/interface_provider.mojom.h" -#include "url/gurl.h" - -namespace service_manager { -class InterfaceProvider; -} - -namespace content { - -// MediaInterfaceProvider is an implementation of mojo InterfaceProvider that -// provides media related services and handles disconnection automatically. -// The GetInterface can be called on any thread. -class CONTENT_EXPORT MediaInterfaceProvider - : public service_manager::mojom::InterfaceProvider { - public: - explicit MediaInterfaceProvider( - service_manager::InterfaceProvider* remote_interfaces); - ~MediaInterfaceProvider() final; - - // InterfaceProvider implementation. - void GetInterface(const std::string& interface_name, - mojo::ScopedMessagePipeHandle pipe) final; - - private: - media::mojom::InterfaceFactory* GetMediaInterfaceFactory(); - void OnConnectionError(); - - service_manager::InterfaceProvider* remote_interfaces_; - media::mojom::InterfaceFactoryPtr media_interface_factory_; - - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - base::WeakPtr<MediaInterfaceProvider> weak_this_; - base::WeakPtrFactory<MediaInterfaceProvider> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(MediaInterfaceProvider); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_MEDIA_INTERFACE_PROVIDER_H_
diff --git a/content/renderer/pepper/pepper_webplugin_impl.cc b/content/renderer/pepper/pepper_webplugin_impl.cc index b620da7..bfc1965 100644 --- a/content/renderer/pepper/pepper_webplugin_impl.cc +++ b/content/renderer/pepper/pepper_webplugin_impl.cc
@@ -310,7 +310,11 @@ instance_->ReplaceSelection(""); return true; } - if (name == "Paste") { + // If the clipboard contains something other than text (e.g. an image), + // WebClipboard::ReadPlainText() returns an empty string. The empty string is + // then pasted, replacing any selected text. This behavior is consistent with + // that of HTML text form fields. + if (name == "Paste" || name == "PasteAndMatchStyle") { if (!CanEditText()) return false;
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index 7cebb9d..d2fe585 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -346,7 +346,7 @@ // network URLLoader. if (base::FeatureList::IsEnabled(features::kOutOfBlinkCORS)) { mojom::URLLoaderFactoryPtr factory_ptr; - CORSURLLoaderFactory::CreateAndBind(std::move(url_loader_factory_), + CORSURLLoaderFactory::CreateAndBind(std::move(url_loader_factory), mojo::MakeRequest(&factory_ptr)); url_loader_factory = std::move(factory_ptr); }
diff --git a/content/renderer/renderer_main.cc b/content/renderer/renderer_main.cc index 99ebfe0..36635f6c 100644 --- a/content/renderer/renderer_main.cc +++ b/content/renderer/renderer_main.cc
@@ -21,8 +21,8 @@ #include "base/timer/hi_res_timer_manager.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" -#include "content/child/child_process.h" #include "content/common/content_constants_internal.h" +#include "content/common/content_switches_internal.h" #include "content/common/service_manager/service_manager_connection_impl.h" #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" @@ -78,7 +78,7 @@ base::debug::WaitForDebugger(60, true); if (command_line.HasSwitch(switches::kRendererStartupDialog)) - ChildProcess::WaitForDebugger("Renderer"); + WaitForDebugger("Renderer"); } #if defined(USE_OZONE)
diff --git a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.cc b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.cc index 223660b5..4b824339 100644 --- a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.cc +++ b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.cc
@@ -180,6 +180,8 @@ // Called on the IO thread. void OnScriptReceived(mojom::ServiceWorkerScriptInfoPtr script_info) { + using RawScriptData = + blink::WebServiceWorkerInstalledScriptsManager::RawScriptData; DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_); const GURL& script_url = script_info->script_url; auto iter = running_receivers_.find(script_url); @@ -188,19 +190,15 @@ DCHECK(receivers); if (!receivers->body()->has_received_all_data() || !receivers->meta_data()->has_received_all_data()) { - // TODO(shimazu): Add a RawScriptData with a failure flag to - // |script_container_| in order to distinguish failure of receiving the - // script from getting the script twice. + script_container_->AddOnIOThread(script_url, + RawScriptData::CreateInvalidInstance()); running_receivers_.erase(iter); - script_container_->OnAllDataAddedOnIOThread(); return; } - auto script_data = - blink::WebServiceWorkerInstalledScriptsManager::RawScriptData::Create( - blink::WebString::FromUTF8(script_info->encoding), - receivers->body()->TakeChunks(), - receivers->meta_data()->TakeChunks()); + auto script_data = RawScriptData::Create( + blink::WebString::FromUTF8(script_info->encoding), + receivers->body()->TakeChunks(), receivers->meta_data()->TakeChunks()); for (const auto& entry : script_info->headers) { script_data->AddHeader(blink::WebString::FromUTF8(entry.first), blink::WebString::FromUTF8(entry.second));
diff --git a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc index 41fa0677..444b6012 100644 --- a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc +++ b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc
@@ -216,6 +216,7 @@ // Wait for the script's arrival. get_raw_script_data_waiter->Wait(); ASSERT_TRUE(script_data); + EXPECT_TRUE(script_data->IsValid()); ASSERT_EQ(1u, script_data->ScriptTextChunks().size()); ASSERT_EQ(kExpectedBody.size() + 1, script_data->ScriptTextChunks()[0].size()); @@ -269,16 +270,17 @@ // Wait for the script's arrival. get_raw_script_data_waiter->Wait(); - // |script_data| should be nullptr since the data pipe for body gets - // disconnected during sending. - EXPECT_FALSE(script_data); + // script_data->IsValid() should return false since the data pipe for body + // gets disconnected during sending. + ASSERT_TRUE(script_data); + EXPECT_FALSE(script_data->IsValid()); } { std::unique_ptr<RawScriptData> script_data; GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data)->Wait(); // This should not be blocked because the script won't arrive. nullptr will - // be returned after disconnection. + // be returned when reading again. EXPECT_EQ(nullptr, script_data.get()); } } @@ -300,8 +302,8 @@ // Start transferring the script. // Meta data is expected to be 100 bytes larger than kExpectedMetaData, but - // sender only sends kExpectedBody and a null byte (kExpectedMetaData.size() - // + 1 bytes in total). + // sender only sends kExpectedMetaData and a null byte + // (kExpectedMetaData.size() + 1 bytes in total). EXPECT_EQ(kScriptUrl, sender.TransferInstalledScript(kExpectedBody.size() + 1, kExpectedMetaData.size() + 100)); @@ -315,16 +317,17 @@ // Wait for the script's arrival. get_raw_script_data_waiter->Wait(); - // |script_data| should be nullptr since the data pipe for body gets - // disconnected during sending. - EXPECT_FALSE(script_data); + // script_data->IsValid() should return false since the data pipe for meta + // data gets disconnected during sending. + ASSERT_TRUE(script_data); + EXPECT_FALSE(script_data->IsValid()); } { std::unique_ptr<RawScriptData> script_data; GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data)->Wait(); // This should not be blocked because the script won't arrive. nullptr will - // be returned after disconnection. + // be returned when reading again. EXPECT_EQ(nullptr, script_data.get()); } }
diff --git a/content/shell/test_runner/web_ax_object_proxy.cc b/content/shell/test_runner/web_ax_object_proxy.cc index 8d2aa58..db30448 100644 --- a/content/shell/test_runner/web_ax_object_proxy.cc +++ b/content/shell/test_runner/web_ax_object_proxy.cc
@@ -593,6 +593,7 @@ .SetProperty("isBusy", &WebAXObjectProxy::IsBusy) .SetProperty("isRequired", &WebAXObjectProxy::IsRequired) .SetProperty("isEditable", &WebAXObjectProxy::IsEditable) + .SetProperty("isEditableRoot", &WebAXObjectProxy::IsEditableRoot) .SetProperty("isRichlyEditable", &WebAXObjectProxy::IsRichlyEditable) .SetProperty("isFocused", &WebAXObjectProxy::IsFocused) .SetProperty("isFocusable", &WebAXObjectProxy::IsFocusable) @@ -997,6 +998,11 @@ return accessibility_object_.IsRequired(); } +bool WebAXObjectProxy::IsEditableRoot() { + accessibility_object_.UpdateLayoutAndCheckValidity(); + return accessibility_object_.IsEditableRoot(); +} + bool WebAXObjectProxy::IsEditable() { accessibility_object_.UpdateLayoutAndCheckValidity(); return accessibility_object_.IsEditable();
diff --git a/content/shell/test_runner/web_ax_object_proxy.h b/content/shell/test_runner/web_ax_object_proxy.h index f8057f6d..9e481c5 100644 --- a/content/shell/test_runner/web_ax_object_proxy.h +++ b/content/shell/test_runner/web_ax_object_proxy.h
@@ -95,6 +95,7 @@ bool IsAtomic(); bool IsBusy(); bool IsRequired(); + bool IsEditableRoot(); bool IsEditable(); bool IsRichlyEditable(); bool IsFocused();
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index cd4fd6f..4ced993 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1328,6 +1328,7 @@ "../browser/service_worker/service_worker_context_core_unittest.cc", "../browser/service_worker/service_worker_context_request_handler_unittest.cc", "../browser/service_worker/service_worker_context_unittest.cc", + "../browser/service_worker/service_worker_context_watcher_unittest.cc", "../browser/service_worker/service_worker_controllee_request_handler_unittest.cc", "../browser/service_worker/service_worker_data_pipe_reader_unittest.cc", "../browser/service_worker/service_worker_database_unittest.cc",
diff --git a/content/test/data/accessibility/html/contenteditable-descendants-expected-blink.txt b/content/test/data/accessibility/html/contenteditable-descendants-expected-blink.txt index 0e37f42a..17480d2f 100644 --- a/content/test/data/accessibility/html/contenteditable-descendants-expected-blink.txt +++ b/content/test/data/accessibility/html/contenteditable-descendants-expected-blink.txt
@@ -1,5 +1,5 @@ rootWebArea -++genericContainer editable multiline richlyEditable +++genericContainer editable multiline richlyEditable editableRoot=true ++++paragraph editable richlyEditable ++++++staticText editable richlyEditable name='A contenteditable with a ' ++++++++inlineTextBox name='A contenteditable with a ' @@ -29,6 +29,6 @@ ++paragraph ++++staticText name='Non-editable paragraph.' ++++++inlineTextBox name='Non-editable paragraph.' -++paragraph editable multiline richlyEditable +++paragraph editable multiline richlyEditable editableRoot=true ++++staticText editable richlyEditable name='Should keep the role but change the state.' -++++++inlineTextBox name='Should keep the role but change the state.' \ No newline at end of file +++++++inlineTextBox name='Should keep the role but change the state.'
diff --git a/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-blink.txt b/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-blink.txt index aa6b662b..02a4674 100644 --- a/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-blink.txt +++ b/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-blink.txt
@@ -1,5 +1,5 @@ rootWebArea -++genericContainer editable multiline richlyEditable +++genericContainer editable multiline richlyEditable editableRoot=true ++++paragraph editable richlyEditable ++++++staticText editable richlyEditable name='A contenteditable with a ' TreeData.textSelStartOffset=0 ++++++++inlineTextBox name='A contenteditable with a ' @@ -25,4 +25,4 @@ ++++++listItem editable richlyEditable ++++++++listMarker name='1' ++++++++staticText editable richlyEditable name='Editable list item.' TreeData.textSelEndOffset=19 -++++++++++inlineTextBox name='Editable list item.' \ No newline at end of file +++++++++++inlineTextBox name='Editable list item.'
diff --git a/content/test/data/accessibility/html/contenteditable-descendants.html b/content/test/data/accessibility/html/contenteditable-descendants.html index 822e778d..d9f940f 100644 --- a/content/test/data/accessibility/html/contenteditable-descendants.html +++ b/content/test/data/accessibility/html/contenteditable-descendants.html
@@ -1,4 +1,7 @@ +<!DOCTYPE html> <!-- +@MAC-ALLOW:AXEditableAncestor* +@MAC-ALLOW:AXHighestEditableAncestor* @WIN-ALLOW:caret_offset* @WIN-ALLOW:IA2_STATE_EDITABLE @WIN-ALLOW:IA2_STATE_MULTI_LINE
diff --git a/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-blink.txt b/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-blink.txt index 521e850..56c0ad38 100644 --- a/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-blink.txt +++ b/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-blink.txt
@@ -1,5 +1,5 @@ rootWebArea -++genericContainer editable multiline richlyEditable +++genericContainer editable multiline richlyEditable editableRoot=true ++++paragraph editable richlyEditable ++++++staticText editable richlyEditable name='This is editable.' ++++++++inlineTextBox name='This is editable.' @@ -7,9 +7,9 @@ ++++++inlineTextBox name='This is not editable.' ++++lineBreak name='<newline>' ++++++inlineTextBox name='<newline>' -++++paragraph editable multiline richlyEditable +++++paragraph editable multiline richlyEditable editableRoot=true ++++++staticText editable richlyEditable name='But this one is.' ++++++++inlineTextBox name='But this one is.' ++++paragraph editable multiline richlyEditable ++++++staticText editable richlyEditable name='So is this one.' -++++++++inlineTextBox name='So is this one.' \ No newline at end of file +++++++++inlineTextBox name='So is this one.'
diff --git a/content/test/data/accessibility/html/input-text-expected-mac.txt b/content/test/data/accessibility/html/input-text-expected-mac.txt index 893526f3..4514ce7 100644 --- a/content/test/data/accessibility/html/input-text-expected-mac.txt +++ b/content/test/data/accessibility/html/input-text-expected-mac.txt
@@ -1,3 +1,4 @@ AXWebArea AXRoleDescription='HTML content' ++AXGroup AXRoleDescription='group' -++++AXTextField AXRoleDescription='text field' AXDescription='Name' +++++AXTextField AXRoleDescription='text field' AXDescription='Name' AXEditableAncestor='AXTextField Name' AXHighestEditableAncestor='AXTextField Name' +
diff --git a/content/test/data/accessibility/html/input-text.html b/content/test/data/accessibility/html/input-text.html index 92a37e0..1162b73 100644 --- a/content/test/data/accessibility/html/input-text.html +++ b/content/test/data/accessibility/html/input-text.html
@@ -1,4 +1,7 @@ +<!DOCTYPE html> <!-- +@MAC-ALLOW:AXEditableAncestor* +@MAC-ALLOW:AXHighestEditableAncestor* @MAC-ALLOW:AXRole* @MAC-ALLOW:AXPlaceholder* @WIN-ALLOW:caret_offset* @@ -14,7 +17,6 @@ @BLINK-DENY:value='http://* @BLINK-ALLOW:textSel* --> -<!DOCTYPE html> <html> <body> <input type="text" placeholder="Name" autofocus>
diff --git a/content/test/data/accessibility/html/textarea-expected-mac.txt b/content/test/data/accessibility/html/textarea-expected-mac.txt index a216fdcd..fb6909c 100644 --- a/content/test/data/accessibility/html/textarea-expected-mac.txt +++ b/content/test/data/accessibility/html/textarea-expected-mac.txt
@@ -1,3 +1,3 @@ AXWebArea AXRoleDescription='HTML content' ++AXGroup AXRoleDescription='group' -++++AXTextArea AXRoleDescription='text entry area' AXValue='The textarea tag defines a multi-line text input control.<newline>' +++++AXTextArea AXRoleDescription='text entry area' AXValue='The textarea tag defines a multi-line text input control.<newline>' AXEditableAncestor='AXTextArea The textarea tag defines a multi-line text input control.<newline>' AXHighestEditableAncestor='AXTextArea The textarea tag defines a multi-line text input control.<newline>'
diff --git a/content/test/data/accessibility/html/textarea.html b/content/test/data/accessibility/html/textarea.html index e2f7540..c43ca6f 100644 --- a/content/test/data/accessibility/html/textarea.html +++ b/content/test/data/accessibility/html/textarea.html
@@ -1,4 +1,7 @@ +<!DOCTYPE html> <!-- +@MAC-ALLOW:AXEditableAncestor* +@MAC-ALLOW:AXHighestEditableAncestor* @MAC-ALLOW:AXRole* @WIN-ALLOW:caret_offset* @WIN-ALLOW:ia2_hypertext=* @@ -8,7 +11,6 @@ @WIN-ALLOW:selection_end* @BLINK-ALLOW:textSel* --> -<!DOCTYPE html> <html> <body>
diff --git a/content/test/data/gpu/pixel_offscreenCanvas_2d_commit_main.html b/content/test/data/gpu/pixel_offscreenCanvas_2d_commit_main.html index 4a008142..cccd796 100644 --- a/content/test/data/gpu/pixel_offscreenCanvas_2d_commit_main.html +++ b/content/test/data/gpu/pixel_offscreenCanvas_2d_commit_main.html
@@ -18,7 +18,7 @@ <body onload="main()"> <div style="position:relative; width:360px; height:200px; background-color:white"> </div> -<div id="container" style="position:absolute; top:0px; left:0px"> +<div id="container" style="position:absolute; top:0px; left:0px;font-size: 0"> <canvas id="canvas1" width="180" height="200" class="nomargin"></canvas> <canvas id="canvas2" width="180" height="200" class="nomargin"></canvas> </div>
diff --git a/content/test/data/gpu/pixel_offscreenCanvas_2d_commit_worker.html b/content/test/data/gpu/pixel_offscreenCanvas_2d_commit_worker.html index 0ceb819..79589eeb 100644 --- a/content/test/data/gpu/pixel_offscreenCanvas_2d_commit_worker.html +++ b/content/test/data/gpu/pixel_offscreenCanvas_2d_commit_worker.html
@@ -11,7 +11,7 @@ <title>OffscreenCanvas 2d commit flow on worker thread: Two Canvases</title> <style type="text/css"> .nomargin { - margin: 0px auto; + margin: 0px; } </style> <script id="myWorker" type="text/worker"> @@ -34,7 +34,7 @@ g_ctx2 = e.data.offscreenCanvas2.getContext("2d"); startTest(); -} +} function startTest() { g_ctx1.fillStyle = "green"; @@ -122,7 +122,7 @@ { var offscreenCanvas1 = document.getElementById("canvas1").transferControlToOffscreen(); var offscreenCanvas2 = document.getElementById("canvas2").transferControlToOffscreen(); - + var worker = makeWorker(document.getElementById("myWorker").textContent); worker.onmessage = function (e) { waitForFinish(); @@ -137,7 +137,7 @@ <body onload="main()"> <div style="position:relative; width:360px; height:200px; background-color:white"> </div> -<div id="container" style="position:absolute; top:0px; left:0px"> +<div id="container" style="position:absolute; top:0px; left:0px; font-size: 0"> <canvas id="canvas1" width="180" height="200" class="nomargin"></canvas> <canvas id="canvas2" width="180" height="200" class="nomargin"></canvas> </div>
diff --git a/content/test/gpu/gpu_tests/pixel_expectations.py b/content/test/gpu/gpu_tests/pixel_expectations.py index 79ff64c..8b64811 100644 --- a/content/test/gpu/gpu_tests/pixel_expectations.py +++ b/content/test/gpu/gpu_tests/pixel_expectations.py
@@ -60,6 +60,22 @@ self.Flaky('Pixel_OffscreenCanvasTransferAfterStyleResize', ['mac', 'linux', 'win', 'android'], bug=735171) + # TODO(fserb): already fixed, just needed to submit so the tests pass. + self.Fail('Pixel_OffscreenCanvasAccelerated2D', + ['mac', 'linux', 'win', 'android']) + self.Fail('Pixel_OffscreenCanvasAccelerated2DWorker', + ['mac', 'linux', 'win', 'android']) + self.Fail('Pixel_OffscreenCanvasUnaccelerated2D', + ['mac', 'linux', 'win', 'android']) + self.Fail('Pixel_OffscreenCanvasUnaccelerated2DGPUCompositing', + ['mac', 'linux', 'win', 'android']) + self.Fail('Pixel_OffscreenCanvasUnaccelerated2DGPUCompositingWorker', + ['mac', 'linux', 'win', 'android']) + self.Fail('Pixel_OffscreenCanvasUnaccelerated2DWorker', + ['mac', 'linux', 'win', 'android']) + + + # TODO(junov): update reference images self.Fail('Pixel_CSSFilterEffects', ['mac'], bug=721727) self.Fail('Pixel_CSSFilterEffects_NoOverlays', ['mac'], bug=721727) @@ -72,4 +88,3 @@ self.Flaky('Pixel_OffscreenCanvasWebGLSoftwareCompositingWorker', ['mac', ('nvidia', 0xfe9), 'debug'], bug=751328) -
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py index 5a73856..55da2c7 100644 --- a/content/test/gpu/gpu_tests/pixel_test_pages.py +++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -354,42 +354,42 @@ 'pixel_offscreenCanvas_2d_commit_main.html', base_name + '_OffscreenCanvasAccelerated2D', test_rect=[0, 0, 360, 200], - revision=6, + revision=7, browser_args=browser_args), PixelTestPage( 'pixel_offscreenCanvas_2d_commit_worker.html', base_name + '_OffscreenCanvasAccelerated2DWorker', test_rect=[0, 0, 360, 200], - revision=6, + revision=7, browser_args=browser_args), PixelTestPage( 'pixel_offscreenCanvas_2d_commit_main.html', base_name + '_OffscreenCanvasUnaccelerated2D', test_rect=[0, 0, 360, 200], - revision=5, + revision=6, browser_args=browser_args + unaccelerated_args), PixelTestPage( 'pixel_offscreenCanvas_2d_commit_worker.html', base_name + '_OffscreenCanvasUnaccelerated2DWorker', test_rect=[0, 0, 360, 200], - revision=5, + revision=6, browser_args=browser_args + unaccelerated_args), PixelTestPage( 'pixel_offscreenCanvas_2d_commit_main.html', base_name + '_OffscreenCanvasUnaccelerated2DGPUCompositing', test_rect=[0, 0, 360, 200], - revision=7, + revision=8, browser_args=browser_args + ['--disable-accelerated-2d-canvas']), PixelTestPage( 'pixel_offscreenCanvas_2d_commit_worker.html', base_name + '_OffscreenCanvasUnaccelerated2DGPUCompositingWorker', test_rect=[0, 0, 360, 200], - revision=7, + revision=8, browser_args=browser_args + ['--disable-accelerated-2d-canvas']), PixelTestPage(
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index 370b24f2..c60e8fc 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -145,8 +145,6 @@ # Keep a separate set of failures for the R7 240, since it can use a new # and updated driver. The older drivers won't ever get fixes from AMD. # Use ['win', ('amd', 0x6613)] for the R7 240 devices. - self.Fail('deqp/functional/gles3/buffercopy.html', - ['win', ('amd', 0x6613)], bug=752681) # Have seen this time out. Think it may be because it's currently # the first test that runs in the shard, and the browser might not
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index 4fddd69..4f70de2f 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -550,6 +550,9 @@ self.Fail('conformance/glsl/bugs/' + 'varying-arrays-should-not-be-reversed.html', ['android', ('qualcomm', 'Adreno (TM) 330')], bug=709704) + self.Flaky('conformance/textures/video/tex-2d-rgb-rgb-unsigned_byte.html', + ['android', 'android-chromium', ('qualcomm', 'Adreno (TM) 330')], + bug=752291) # Nexus 5X # This one is causing intermittent timeouts on the device, and it
diff --git a/content/utility/utility_main.cc b/content/utility/utility_main.cc index 9ae4eeae..e8902edf 100644 --- a/content/utility/utility_main.cc +++ b/content/utility/utility_main.cc
@@ -12,6 +12,7 @@ #include "base/timer/hi_res_timer_manager.h" #include "build/build_config.h" #include "content/child/child_process.h" +#include "content/common/content_switches_internal.h" #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" #include "content/public/common/sandbox_init.h" @@ -34,6 +35,9 @@ base::MessageLoop main_message_loop; base::PlatformThread::SetName("CrUtilityMain"); + if (parameters.command_line.HasSwitch(switches::kUtilityStartupDialog)) + WaitForDebugger("Utility"); + #if defined(OS_LINUX) // Initializes the sandbox before any threads are created. // TODO(jorgelo): move this after GTK initialization when we enable a strict
diff --git a/docs/es6_chromium.md b/docs/es6_chromium.md index a48fb4c..66551ba3 100644 --- a/docs/es6_chromium.md +++ b/docs/es6_chromium.md
@@ -432,6 +432,28 @@ --- +## for...of Loops + +Convenient operator to iterate over all values in an iterable collection. This +differs from `for ...in`, which iterates over all enumerable properties of an +object. + +**Usage Example:** + +```js +// Given an iterable collection of Fibonacci numbers... +for (let n of fibonacci) { + console.log(n); // 1, 1, 2, 3, ... +} +``` + +**Documentation:** [link1](http://www.ecma-international.org/ecma-262/6.0/#sec-for-in-and-for-of-statements) +[link2](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) + +**Discussion Notes / Link to Thread:** [link](https://groups.google.com/a/chromium.org/d/msg/chromium-dev/d_2zUYQZJTg/-_PSji_OAQAJ) + +--- + # Banned Features The following features are banned for Chromium development. @@ -756,27 +778,6 @@ --- -## for...of Loops - -Convenient operator to iterate over all values in an iterable collection. This -differs from `for ...in`, which iterates over all iterable properties. - -**Usage Example:** - -```js -// Given an iterable collection fibonacci numbers... -for (var n of fibonacci) { - console.log(n); // 1, 1, 2, 3, ... -} -``` - -**Documentation:** [link](http://www.ecma-international.org/ecma-262/6.0/#sec-for-in-and-for-of-statements) -[link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) - -**Discussion Notes / Link to Thread:** - ---- - ## String Static & Prototype methods **Usage Example:**
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn index 7f16ee4..e0f3e12 100644 --- a/extensions/browser/BUILD.gn +++ b/extensions/browser/BUILD.gn
@@ -485,6 +485,7 @@ "api/declarative/declarative_rule_unittest.cc", "api/declarative/deduping_factory_unittest.cc", "api/declarative/rules_registry_unittest.cc", + "api/declarative_net_request/indexed_rule_unittest.cc", "api/declarative_webrequest/webrequest_condition_attribute_unittest.cc", "api/declarative_webrequest/webrequest_condition_unittest.cc", "api/document_scan/document_scan_api_unittest.cc",
diff --git a/extensions/browser/api/BUILD.gn b/extensions/browser/api/BUILD.gn index 6f7f982..93d88434 100644 --- a/extensions/browser/api/BUILD.gn +++ b/extensions/browser/api/BUILD.gn
@@ -52,6 +52,7 @@ "//extensions/browser/api/cast_channel", "//extensions/browser/api/declarative", "//extensions/browser/api/declarative_content", + "//extensions/browser/api/declarative_net_request", "//extensions/browser/api/declarative_webrequest", "//extensions/browser/api/display_source", "//extensions/browser/api/dns",
diff --git a/extensions/browser/api/declarative_net_request/BUILD.gn b/extensions/browser/api/declarative_net_request/BUILD.gn new file mode 100644 index 0000000..fe012041 --- /dev/null +++ b/extensions/browser/api/declarative_net_request/BUILD.gn
@@ -0,0 +1,22 @@ +# 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. + +source_set("declarative_net_request") { + sources = [ + "constants.h", + "indexed_rule.cc", + "indexed_rule.h", + ] + + public_deps = [ + "//components/url_pattern_index", + ] + + deps = [ + "//base", + "//extensions/common", + "//extensions/common/api", + "//url", + ] +}
diff --git a/extensions/browser/api/declarative_net_request/DEPS b/extensions/browser/api/declarative_net_request/DEPS new file mode 100644 index 0000000..7ca4cb34 --- /dev/null +++ b/extensions/browser/api/declarative_net_request/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+components/url_pattern_index", +]
diff --git a/extensions/browser/api/declarative_net_request/constants.h b/extensions/browser/api/declarative_net_request/constants.h new file mode 100644 index 0000000..e165da1 --- /dev/null +++ b/extensions/browser/api/declarative_net_request/constants.h
@@ -0,0 +1,38 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_CONSTANTS_H_ +#define EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_CONSTANTS_H_ + +namespace extensions { +namespace declarative_net_request { + +// The result of parsing a JSON rule provided by an extension. +enum class ParseResult { + SUCCESS, + ERROR_RESOURCE_TYPE_DUPLICATED, + ERROR_EMPTY_REDIRECT_RULE_PRIORITY, + ERROR_EMPTY_REDIRECT_URL, + ERROR_INVALID_RULE_ID, + ERROR_INVALID_REDIRECT_RULE_PRIORITY, + ERROR_NO_APPLICABLE_RESOURCE_TYPES, + ERROR_EMPTY_DOMAINS_LIST, + ERROR_EMPTY_RESOURCE_TYPES_LIST, + ERROR_EMPTY_URL_FILTER, + ERROR_INVALID_REDIRECT_URL, +}; + +// Minimum valid value of a declarative rule ID. +constexpr int kMinValidID = 1; + +// Minimum valid value of a declarative rule priority. +constexpr int kMinValidPriority = 1; + +// Default priority used for rules when the priority is not explicity provided +// by an extension. +constexpr int kDefaultPriority = 1; +} // namespace declarative_net_request +} // namespace extensions + +#endif // EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_CONSTANTS_H_
diff --git a/extensions/browser/api/declarative_net_request/indexed_rule.cc b/extensions/browser/api/declarative_net_request/indexed_rule.cc new file mode 100644 index 0000000..cede396e --- /dev/null +++ b/extensions/browser/api/declarative_net_request/indexed_rule.cc
@@ -0,0 +1,326 @@ +// 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 "extensions/browser/api/declarative_net_request/indexed_rule.h" + +#include <algorithm> +#include <utility> + +#include "base/numerics/safe_conversions.h" +#include "base/strings/string_util.h" +#include "extensions/browser/api/declarative_net_request/constants.h" +#include "extensions/common/api/declarative_net_request.h" +#include "extensions/common/api/declarative_net_request/utils.h" +#include "url/gurl.h" + +namespace extensions { +namespace declarative_net_request { + +namespace { + +namespace flat_rule = url_pattern_index::flat; +namespace dnr_api = extensions::api::declarative_net_request; + +// Returns true if bitmask |sub| is a subset of |super|. +constexpr bool IsSubset(unsigned sub, unsigned super) { + return (super | sub) == super; +} + +// Helper class to parse the url filter of a Declarative Net Request API rule. +class UrlFilterParser { + public: + // This sets the |url_pattern_type|, |anchor_left|, |anchor_right| and + // |url_pattern| fields on the |indexed_rule_|. + static void Parse(std::unique_ptr<std::string> url_filter, + IndexedRule* indexed_rule) { + DCHECK(indexed_rule); + UrlFilterParser(url_filter ? std::move(*url_filter) : std::string(), + indexed_rule) + .ParseImpl(); + } + + private: + UrlFilterParser(std::string url_filter, IndexedRule* indexed_rule) + : url_filter_(std::move(url_filter)), + url_filter_len_(url_filter_.length()), + index_(0), + indexed_rule_(indexed_rule) {} + + void ParseImpl() { + ParseLeftAnchor(); + DCHECK_LE(index_, 2u); + + ParseFilterString(); + DCHECK(index_ == url_filter_len_ || index_ + 1 == url_filter_len_); + + ParseRightAnchor(); + DCHECK_EQ(url_filter_len_, index_); + } + + void ParseLeftAnchor() { + indexed_rule_->anchor_left = flat_rule::AnchorType_NONE; + + if (IsAtAnchor()) { + ++index_; + indexed_rule_->anchor_left = flat_rule::AnchorType_BOUNDARY; + if (IsAtAnchor()) { + ++index_; + indexed_rule_->anchor_left = flat_rule::AnchorType_SUBDOMAIN; + } + } + } + + void ParseFilterString() { + indexed_rule_->url_pattern_type = flat_rule::UrlPatternType_SUBSTRING; + size_t left_index = index_; + while (index_ < url_filter_len_ && !IsAtRightAnchor()) { + if (IsAtSeparatorOrWildcard()) + indexed_rule_->url_pattern_type = flat_rule::UrlPatternType_WILDCARDED; + ++index_; + } + // Note: Empty url patterns are supported. + indexed_rule_->url_pattern = + url_filter_.substr(left_index, index_ - left_index); + } + + void ParseRightAnchor() { + indexed_rule_->anchor_right = flat_rule::AnchorType_NONE; + if (IsAtRightAnchor()) { + ++index_; + indexed_rule_->anchor_right = flat_rule::AnchorType_BOUNDARY; + } + } + + bool IsAtSeparatorOrWildcard() const { + return IsAtValidIndex() && (url_filter_[index_] == kSeparatorCharacter || + url_filter_[index_] == kWildcardCharacter); + } + + bool IsAtRightAnchor() const { + return IsAtAnchor() && index_ > 0 && index_ + 1 == url_filter_len_; + } + + bool IsAtValidIndex() const { return index_ < url_filter_len_; } + + bool IsAtAnchor() const { + return IsAtValidIndex() && url_filter_[index_] == kAnchorCharacter; + } + + static constexpr char kAnchorCharacter = '|'; + static constexpr char kSeparatorCharacter = '^'; + static constexpr char kWildcardCharacter = '*'; + + const std::string url_filter_; + const size_t url_filter_len_; + size_t index_; + IndexedRule* indexed_rule_; // Must outlive this instance. + + DISALLOW_COPY_AND_ASSIGN(UrlFilterParser); +}; + +// Returns a bitmask of flat_rule::OptionFlag corresponding to |parsed_rule|. +uint8_t GetOptionsMask(const dnr_api::Rule& parsed_rule) { + uint8_t mask = flat_rule::OptionFlag_NONE; + + if (parsed_rule.action.type == dnr_api::RULE_ACTION_TYPE_WHITELIST) + mask |= flat_rule::OptionFlag_IS_WHITELIST; + if (parsed_rule.condition.is_url_filter_case_sensitive && + *parsed_rule.condition.is_url_filter_case_sensitive) { + mask |= flat_rule::OptionFlag_IS_MATCH_CASE; + } + + switch (parsed_rule.condition.domain_type) { + case dnr_api::DOMAIN_TYPE_FIRSTPARTY: + mask |= flat_rule::OptionFlag_APPLIES_TO_FIRST_PARTY; + break; + case dnr_api::DOMAIN_TYPE_THIRDPARTY: + mask |= flat_rule::OptionFlag_APPLIES_TO_THIRD_PARTY; + break; + case dnr_api::DOMAIN_TYPE_NONE: + mask |= (flat_rule::OptionFlag_APPLIES_TO_FIRST_PARTY | + flat_rule::OptionFlag_APPLIES_TO_THIRD_PARTY); + break; + } + return mask; +} + +uint8_t GetActivationTypes(const dnr_api::Rule& parsed_rule) { + // Extensions don't use any activation types currently. + return flat_rule::ActivationType_NONE; +} + +flat_rule::ElementType GetElementType(dnr_api::ResourceType resource_type) { + switch (resource_type) { + case dnr_api::RESOURCE_TYPE_NONE: + return flat_rule::ElementType_NONE; + case dnr_api::RESOURCE_TYPE_SUB_FRAME: + return flat_rule::ElementType_SUBDOCUMENT; + case dnr_api::RESOURCE_TYPE_STYLESHEET: + return flat_rule::ElementType_STYLESHEET; + case dnr_api::RESOURCE_TYPE_SCRIPT: + return flat_rule::ElementType_SCRIPT; + case dnr_api::RESOURCE_TYPE_IMAGE: + return flat_rule::ElementType_IMAGE; + case dnr_api::RESOURCE_TYPE_FONT: + return flat_rule::ElementType_FONT; + case dnr_api::RESOURCE_TYPE_OBJECT: + return flat_rule::ElementType_OBJECT; + case dnr_api::RESOURCE_TYPE_XMLHTTPREQUEST: + return flat_rule::ElementType_XMLHTTPREQUEST; + case dnr_api::RESOURCE_TYPE_PING: + return flat_rule::ElementType_PING; + case dnr_api::RESOURCE_TYPE_MEDIA: + return flat_rule::ElementType_MEDIA; + case dnr_api::RESOURCE_TYPE_WEBSOCKET: + return flat_rule::ElementType_WEBSOCKET; + case dnr_api::RESOURCE_TYPE_OTHER: + return flat_rule::ElementType_OTHER; + } + NOTREACHED(); + return flat_rule::ElementType_NONE; +} + +// Returns a bitmask of flat_rule::ElementType corresponding to passed +// |resource_types|. +uint16_t GetResourceTypesMask( + const std::vector<dnr_api::ResourceType>* resource_types) { + uint16_t mask = flat_rule::ElementType_NONE; + if (!resource_types) + return mask; + + for (const auto resource_type : *resource_types) + mask |= GetElementType(resource_type); + return mask; +} + +// Computes the bitmask of flat_rule::ElementType taking into consideration +// the included and excluded resource types for |condition|. +ParseResult ComputeElementTypes(const dnr_api::RuleCondition& condition, + uint16_t* element_types) { + uint16_t include_element_type_mask = + GetResourceTypesMask(condition.resource_types.get()); + uint16_t exclude_element_type_mask = + GetResourceTypesMask(condition.excluded_resource_types.get()); + + // OBJECT_SUBREQUEST is not used by Extensions. + if (exclude_element_type_mask == + (flat_rule::ElementType_ANY & + ~flat_rule::ElementType_OBJECT_SUBREQUEST)) { + return ParseResult::ERROR_NO_APPLICABLE_RESOURCE_TYPES; + } + + if (include_element_type_mask & exclude_element_type_mask) + return ParseResult::ERROR_RESOURCE_TYPE_DUPLICATED; + + *element_types = + include_element_type_mask + ? include_element_type_mask + : (flat_rule::ElementType_ANY & ~exclude_element_type_mask); + + return ParseResult::SUCCESS; +} + +// TODO(http://crbug.com/753031): url_pattern_index requires the domains to be +// sorted differently. Expose the comparator to sort domains as part of +// url_pattern_index and use it here. +// Lower-cases and sorts domains, as required by the url_pattern_index +// component. +std::vector<std::string> CanonicalizeDomains( + std::unique_ptr<std::vector<std::string>> domains) { + if (!domains) + return std::vector<std::string>(); + + // Convert to lower case as required by the url_pattern_index component. + for (size_t i = 0; i < domains->size(); i++) + (*domains)[i] = base::ToLowerASCII((*domains)[i]); + + std::sort(domains->begin(), domains->end()); + + // Move the vector, because it isn't eligible for return value optimization. + return std::move(*domains); +} + +} // namespace + +IndexedRule::IndexedRule() = default; +IndexedRule::~IndexedRule() = default; + +// static +ParseResult IndexedRule::CreateIndexedRule( + std::unique_ptr<dnr_api::Rule> parsed_rule, + IndexedRule* indexed_rule) { + DCHECK(indexed_rule); + DCHECK(IsAPIAvailable()); + + if (parsed_rule->id < kMinValidID) + return ParseResult::ERROR_INVALID_RULE_ID; + + const bool is_redirect_rule = + parsed_rule->action.type == dnr_api::RULE_ACTION_TYPE_REDIRECT; + if (is_redirect_rule) { + if (!parsed_rule->action.redirect_url || + parsed_rule->action.redirect_url->empty()) { + return ParseResult::ERROR_EMPTY_REDIRECT_URL; + } + if (!GURL(*parsed_rule->action.redirect_url).is_valid()) + return ParseResult::ERROR_INVALID_REDIRECT_URL; + if (!parsed_rule->priority) + return ParseResult::ERROR_EMPTY_REDIRECT_RULE_PRIORITY; + if (*parsed_rule->priority < kMinValidPriority) + return ParseResult::ERROR_INVALID_REDIRECT_RULE_PRIORITY; + } + + if (parsed_rule->condition.domains && parsed_rule->condition.domains->empty()) + return ParseResult::ERROR_EMPTY_DOMAINS_LIST; + + if (parsed_rule->condition.resource_types && + parsed_rule->condition.resource_types->empty()) { + return ParseResult::ERROR_EMPTY_RESOURCE_TYPES_LIST; + } + + if (parsed_rule->condition.url_filter && + parsed_rule->condition.url_filter->empty()) { + return ParseResult::ERROR_EMPTY_URL_FILTER; + } + + indexed_rule->id = base::checked_cast<uint32_t>(parsed_rule->id); + indexed_rule->priority = base::checked_cast<uint32_t>( + is_redirect_rule ? *parsed_rule->priority : kDefaultPriority); + indexed_rule->options = GetOptionsMask(*parsed_rule); + indexed_rule->activation_types = GetActivationTypes(*parsed_rule); + + { + ParseResult result = ComputeElementTypes(parsed_rule->condition, + &indexed_rule->element_types); + if (result != ParseResult::SUCCESS) + return result; + } + + indexed_rule->domains = + CanonicalizeDomains(std::move(parsed_rule->condition.domains)); + indexed_rule->excluded_domains = + CanonicalizeDomains(std::move(parsed_rule->condition.excluded_domains)); + + if (is_redirect_rule) + indexed_rule->redirect_url = std::move(*parsed_rule->action.redirect_url); + + // Parse the |anchor_left|, |anchor_right|, |url_pattern_type| and + // |url_pattern| fields. + UrlFilterParser::Parse(std::move(parsed_rule->condition.url_filter), + indexed_rule); + + // Some sanity checks to ensure we return a valid IndexedRule. + DCHECK_GE(indexed_rule->id, static_cast<uint32_t>(kMinValidID)); + DCHECK_GE(indexed_rule->priority, static_cast<uint32_t>(kMinValidPriority)); + DCHECK(IsSubset(indexed_rule->options, flat_rule::OptionFlag_ANY)); + DCHECK(IsSubset(indexed_rule->element_types, flat_rule::ElementType_ANY)); + DCHECK_EQ(flat_rule::ActivationType_NONE, indexed_rule->activation_types); + DCHECK_NE(flat_rule::UrlPatternType_REGEXP, indexed_rule->url_pattern_type); + DCHECK_NE(flat_rule::AnchorType_SUBDOMAIN, indexed_rule->anchor_right); + + return ParseResult::SUCCESS; +} + +} // namespace declarative_net_request +} // namespace extensions
diff --git a/extensions/browser/api/declarative_net_request/indexed_rule.h b/extensions/browser/api/declarative_net_request/indexed_rule.h new file mode 100644 index 0000000..ad67dda8 --- /dev/null +++ b/extensions/browser/api/declarative_net_request/indexed_rule.h
@@ -0,0 +1,67 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_INDEXED_RULE_H_ +#define EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_INDEXED_RULE_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "base/macros.h" +#include "components/url_pattern_index/flat/url_pattern_index_generated.h" + +namespace extensions { + +namespace api { +namespace declarative_net_request { +struct Rule; +} // namespace declarative_net_request +} // namespace api + +namespace declarative_net_request { + +enum class ParseResult; + +// An intermediate structure to store a Declarative Net Request API rule while +// indexing. This structure aids in the subsequent conversion to a flatbuffer +// UrlRule as specified by the url_pattern_index component. +struct IndexedRule { + IndexedRule(); + ~IndexedRule(); + + static ParseResult CreateIndexedRule( + std::unique_ptr<extensions::api::declarative_net_request::Rule> + parsed_rule, + IndexedRule* indexed_rule); + + // These fields correspond to the attributes of a flatbuffer UrlRule, as + // specified by the url_pattern_index component. + uint32_t id = 0; + uint32_t priority = 0; + uint8_t options = url_pattern_index::flat::OptionFlag_NONE; + uint16_t element_types = url_pattern_index::flat::ElementType_NONE; + uint8_t activation_types = url_pattern_index::flat::ActivationType_NONE; + url_pattern_index::flat::UrlPatternType url_pattern_type = + url_pattern_index::flat::UrlPatternType_SUBSTRING; + url_pattern_index::flat::AnchorType anchor_left = + url_pattern_index::flat::AnchorType_NONE; + url_pattern_index::flat::AnchorType anchor_right = + url_pattern_index::flat::AnchorType_NONE; + std::string url_pattern; + // Lower-cased and sorted as required by the url_pattern_index component. + // TODO(http://crbug.com/696822): Use a std::set. + std::vector<std::string> domains; + std::vector<std::string> excluded_domains; + + // The redirect url, valid iff this is a redirect rule. + std::string redirect_url; + + DISALLOW_COPY_AND_ASSIGN(IndexedRule); +}; + +} // namespace declarative_net_request +} // namespace extensions + +#endif // EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_INDEXED_RULE_H_
diff --git a/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc b/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc new file mode 100644 index 0000000..eff8fb0 --- /dev/null +++ b/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc
@@ -0,0 +1,361 @@ +// 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 "extensions/browser/api/declarative_net_request/indexed_rule.h" + +#include <memory> +#include <utility> + +#include "base/format_macros.h" +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/numerics/safe_conversions.h" +#include "base/strings/stringprintf.h" +#include "components/version_info/version_info.h" +#include "extensions/browser/api/declarative_net_request/constants.h" +#include "extensions/common/api/declarative_net_request.h" +#include "extensions/common/features/feature_channel.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace extensions { +namespace declarative_net_request { +namespace { + +namespace flat_rule = url_pattern_index::flat; +namespace dnr_api = extensions::api::declarative_net_request; + +std::unique_ptr<dnr_api::Rule> CreateGenericParsedRule() { + auto rule = base::MakeUnique<dnr_api::Rule>(); + rule->id = kMinValidID; + rule->condition.url_filter = base::MakeUnique<std::string>("filter"); + rule->action.type = dnr_api::RULE_ACTION_TYPE_BLOCK; + return rule; +} + +class IndexedRuleTest : public testing::Test { + public: + IndexedRuleTest() : channel_(::version_info::Channel::UNKNOWN) {} + + private: + ScopedCurrentChannel channel_; + + DISALLOW_COPY_AND_ASSIGN(IndexedRuleTest); +}; + +TEST_F(IndexedRuleTest, IDParsing) { + struct { + const int id; + const ParseResult expected_result; + } cases[] = { + {kMinValidID - 1, ParseResult::ERROR_INVALID_RULE_ID}, + {kMinValidID, ParseResult::SUCCESS}, + {kMinValidID + 1, ParseResult::SUCCESS}, + }; + for (size_t i = 0; i < arraysize(cases); ++i) { + SCOPED_TRACE(base::StringPrintf("Testing case[%" PRIuS "]", i)); + std::unique_ptr<dnr_api::Rule> rule = CreateGenericParsedRule(); + rule->id = cases[i].id; + + IndexedRule indexed_rule; + ParseResult result = + IndexedRule::CreateIndexedRule(std::move(rule), &indexed_rule); + + EXPECT_EQ(cases[i].expected_result, result); + if (result == ParseResult::SUCCESS) + EXPECT_EQ(base::checked_cast<uint32_t>(cases[i].id), indexed_rule.id); + } +} + +TEST_F(IndexedRuleTest, PriorityParsing) { + struct { + std::unique_ptr<int> priority; + const ParseResult expected_result; + // Only valid if |expected_result| is SUCCESS. + const uint32_t expected_priority; + } cases[] = { + {base::MakeUnique<int>(kMinValidPriority - 1), + ParseResult::ERROR_INVALID_REDIRECT_RULE_PRIORITY, kDefaultPriority}, + {base::MakeUnique<int>(kMinValidPriority), ParseResult::SUCCESS, + kMinValidPriority}, + {base::MakeUnique<int>(kMinValidPriority + 1), ParseResult::SUCCESS, + kMinValidPriority + 1}, + {nullptr, ParseResult::ERROR_EMPTY_REDIRECT_RULE_PRIORITY, + kDefaultPriority}, + }; + + for (size_t i = 0; i < arraysize(cases); ++i) { + SCOPED_TRACE(base::StringPrintf("Testing case[%" PRIuS "]", i)); + std::unique_ptr<dnr_api::Rule> rule = CreateGenericParsedRule(); + rule->priority = std::move(cases[i].priority); + rule->action.type = dnr_api::RULE_ACTION_TYPE_REDIRECT; + rule->action.redirect_url = + base::MakeUnique<std::string>("http://google.com"); + + IndexedRule indexed_rule; + ParseResult result = + IndexedRule::CreateIndexedRule(std::move(rule), &indexed_rule); + + EXPECT_EQ(cases[i].expected_result, result); + if (result == ParseResult::SUCCESS) + EXPECT_EQ(cases[i].expected_priority, indexed_rule.priority); + } + + // Ensure priority is ignored for non-redirect rules. + { + std::unique_ptr<dnr_api::Rule> rule = CreateGenericParsedRule(); + rule->priority = base::MakeUnique<int>(5); + IndexedRule indexed_rule; + ParseResult result = + IndexedRule::CreateIndexedRule(std::move(rule), &indexed_rule); + EXPECT_EQ(ParseResult::SUCCESS, result); + EXPECT_EQ(static_cast<uint32_t>(kDefaultPriority), indexed_rule.priority); + } +} + +TEST_F(IndexedRuleTest, OptionsParsing) { + struct { + const dnr_api::DomainType domain_type; + const dnr_api::RuleActionType action_type; + std::unique_ptr<bool> is_url_filter_case_sensitive; + const uint8_t expected_options; + } cases[] = { + {dnr_api::DOMAIN_TYPE_NONE, dnr_api::RULE_ACTION_TYPE_BLOCK, nullptr, + flat_rule::OptionFlag_APPLIES_TO_THIRD_PARTY | + flat_rule::OptionFlag_APPLIES_TO_FIRST_PARTY}, + {dnr_api::DOMAIN_TYPE_FIRSTPARTY, dnr_api::RULE_ACTION_TYPE_WHITELIST, + base::MakeUnique<bool>(true), + flat_rule::OptionFlag_IS_WHITELIST | + flat_rule::OptionFlag_APPLIES_TO_FIRST_PARTY | + flat_rule::OptionFlag_IS_MATCH_CASE}, + }; + + for (size_t i = 0; i < arraysize(cases); ++i) { + SCOPED_TRACE(base::StringPrintf("Testing case[%" PRIuS "]", i)); + std::unique_ptr<dnr_api::Rule> rule = CreateGenericParsedRule(); + rule->condition.domain_type = cases[i].domain_type; + rule->action.type = cases[i].action_type; + rule->condition.is_url_filter_case_sensitive = + std::move(cases[i].is_url_filter_case_sensitive); + + IndexedRule indexed_rule; + ParseResult result = + IndexedRule::CreateIndexedRule(std::move(rule), &indexed_rule); + + EXPECT_EQ(ParseResult::SUCCESS, result); + EXPECT_EQ(cases[i].expected_options, indexed_rule.options); + } +} + +TEST_F(IndexedRuleTest, ResourceTypesParsing) { + using ResourceTypeVec = std::vector<dnr_api::ResourceType>; + + struct { + std::unique_ptr<ResourceTypeVec> resource_types; + std::unique_ptr<ResourceTypeVec> excluded_resource_types; + const ParseResult expected_result; + // Only valid if |expected_result| is SUCCESS. + const uint16_t expected_element_types; + } cases[] = { + {nullptr, nullptr, ParseResult::SUCCESS, flat_rule::ElementType_ANY}, + {nullptr, + base::MakeUnique<ResourceTypeVec>( + ResourceTypeVec({dnr_api::RESOURCE_TYPE_SCRIPT})), + ParseResult::SUCCESS, + flat_rule::ElementType_ANY & ~flat_rule::ElementType_SCRIPT}, + {base::MakeUnique<ResourceTypeVec>(ResourceTypeVec( + {dnr_api::RESOURCE_TYPE_SCRIPT, dnr_api::RESOURCE_TYPE_IMAGE})), + nullptr, ParseResult::SUCCESS, + flat_rule::ElementType_SCRIPT | flat_rule::ElementType_IMAGE}, + {base::MakeUnique<ResourceTypeVec>(ResourceTypeVec( + {dnr_api::RESOURCE_TYPE_SCRIPT, dnr_api::RESOURCE_TYPE_IMAGE})), + base::MakeUnique<ResourceTypeVec>( + ResourceTypeVec({dnr_api::RESOURCE_TYPE_SCRIPT})), + ParseResult::ERROR_RESOURCE_TYPE_DUPLICATED, + flat_rule::ElementType_NONE}, + {nullptr, + base::MakeUnique<ResourceTypeVec>(ResourceTypeVec( + {dnr_api::RESOURCE_TYPE_SUB_FRAME, dnr_api::RESOURCE_TYPE_STYLESHEET, + dnr_api::RESOURCE_TYPE_SCRIPT, dnr_api::RESOURCE_TYPE_IMAGE, + dnr_api::RESOURCE_TYPE_FONT, dnr_api::RESOURCE_TYPE_OBJECT, + dnr_api::RESOURCE_TYPE_XMLHTTPREQUEST, dnr_api::RESOURCE_TYPE_PING, + dnr_api::RESOURCE_TYPE_MEDIA, dnr_api::RESOURCE_TYPE_WEBSOCKET, + dnr_api::RESOURCE_TYPE_OTHER})), + ParseResult::ERROR_NO_APPLICABLE_RESOURCE_TYPES, + flat_rule::ElementType_NONE}, + {base::MakeUnique<ResourceTypeVec>(ResourceTypeVec()), + base::MakeUnique<ResourceTypeVec>(ResourceTypeVec()), + ParseResult::ERROR_EMPTY_RESOURCE_TYPES_LIST, + flat_rule::ElementType_NONE}, + {base::MakeUnique<ResourceTypeVec>( + ResourceTypeVec({dnr_api::RESOURCE_TYPE_SCRIPT})), + base::MakeUnique<ResourceTypeVec>(ResourceTypeVec()), + ParseResult::SUCCESS, flat_rule::ElementType_SCRIPT}, + }; + + for (size_t i = 0; i < arraysize(cases); ++i) { + SCOPED_TRACE(base::StringPrintf("Testing case[%" PRIuS "]", i)); + std::unique_ptr<dnr_api::Rule> rule = CreateGenericParsedRule(); + rule->condition.resource_types = std::move(cases[i].resource_types); + rule->condition.excluded_resource_types = + std::move(cases[i].excluded_resource_types); + + IndexedRule indexed_rule; + ParseResult result = + IndexedRule::CreateIndexedRule(std::move(rule), &indexed_rule); + + EXPECT_EQ(cases[i].expected_result, result); + if (result == ParseResult::SUCCESS) + EXPECT_EQ(cases[i].expected_element_types, indexed_rule.element_types); + } +} + +TEST_F(IndexedRuleTest, UrlFilterParsing) { + struct { + std::unique_ptr<std::string> input_url_filter; + + // Only valid if |expected_result| is SUCCESS. + const flat_rule::UrlPatternType expected_url_pattern_type; + const flat_rule::AnchorType expected_anchor_left; + const flat_rule::AnchorType expected_anchor_right; + const std::string expected_url_pattern; + + const ParseResult expected_result; + } cases[] = { + {nullptr, flat_rule::UrlPatternType_SUBSTRING, flat_rule::AnchorType_NONE, + flat_rule::AnchorType_NONE, "", ParseResult::SUCCESS}, + {base::MakeUnique<std::string>(""), flat_rule::UrlPatternType_SUBSTRING, + flat_rule::AnchorType_NONE, flat_rule::AnchorType_NONE, "", + ParseResult::ERROR_EMPTY_URL_FILTER}, + {base::MakeUnique<std::string>("|"), flat_rule::UrlPatternType_SUBSTRING, + flat_rule::AnchorType_BOUNDARY, flat_rule::AnchorType_NONE, "", + ParseResult::SUCCESS}, + {base::MakeUnique<std::string>("||"), flat_rule::UrlPatternType_SUBSTRING, + flat_rule::AnchorType_SUBDOMAIN, flat_rule::AnchorType_NONE, "", + ParseResult::SUCCESS}, + {base::MakeUnique<std::string>("|||"), + flat_rule::UrlPatternType_SUBSTRING, flat_rule::AnchorType_SUBDOMAIN, + flat_rule::AnchorType_BOUNDARY, "", ParseResult::SUCCESS}, + {base::MakeUnique<std::string>("|*|||"), + flat_rule::UrlPatternType_WILDCARDED, flat_rule::AnchorType_BOUNDARY, + flat_rule::AnchorType_BOUNDARY, "*||", ParseResult::SUCCESS}, + {base::MakeUnique<std::string>("|xyz|"), + flat_rule::UrlPatternType_SUBSTRING, flat_rule::AnchorType_BOUNDARY, + flat_rule::AnchorType_BOUNDARY, "xyz", ParseResult::SUCCESS}, + {base::MakeUnique<std::string>("||x^yz"), + flat_rule::UrlPatternType_WILDCARDED, flat_rule::AnchorType_SUBDOMAIN, + flat_rule::AnchorType_NONE, "x^yz", ParseResult::SUCCESS}, + {base::MakeUnique<std::string>("||xyz|"), + flat_rule::UrlPatternType_SUBSTRING, flat_rule::AnchorType_SUBDOMAIN, + flat_rule::AnchorType_BOUNDARY, "xyz", ParseResult::SUCCESS}, + {base::MakeUnique<std::string>("x*y|z"), + flat_rule::UrlPatternType_WILDCARDED, flat_rule::AnchorType_NONE, + flat_rule::AnchorType_NONE, "x*y|z", ParseResult::SUCCESS}, + {base::MakeUnique<std::string>("**^"), + flat_rule::UrlPatternType_WILDCARDED, flat_rule::AnchorType_NONE, + flat_rule::AnchorType_NONE, "**^", ParseResult::SUCCESS}, + {base::MakeUnique<std::string>("||google.com"), + flat_rule::UrlPatternType_SUBSTRING, flat_rule::AnchorType_SUBDOMAIN, + flat_rule::AnchorType_NONE, "google.com", ParseResult::SUCCESS}, + }; + + for (size_t i = 0; i < arraysize(cases); ++i) { + SCOPED_TRACE(base::StringPrintf("Testing case[%" PRIuS "]", i)); + std::unique_ptr<dnr_api::Rule> rule = CreateGenericParsedRule(); + rule->condition.url_filter = std::move(cases[i].input_url_filter); + + IndexedRule indexed_rule; + ParseResult result = + IndexedRule::CreateIndexedRule(std::move(rule), &indexed_rule); + if (result != ParseResult::SUCCESS) + continue; + + EXPECT_EQ(cases[i].expected_result, result); + EXPECT_EQ(cases[i].expected_url_pattern_type, + indexed_rule.url_pattern_type); + EXPECT_EQ(cases[i].expected_anchor_left, indexed_rule.anchor_left); + EXPECT_EQ(cases[i].expected_anchor_right, indexed_rule.anchor_right); + EXPECT_EQ(cases[i].expected_url_pattern, indexed_rule.url_pattern); + } +} + +TEST_F(IndexedRuleTest, DomainsParsing) { + using DomainVec = std::vector<std::string>; + struct { + std::unique_ptr<DomainVec> domains; + std::unique_ptr<DomainVec> excluded_domains; + const ParseResult expected_result; + // Only valid if |expected_result| is SUCCESS. + const DomainVec expected_domains; + const DomainVec expected_excluded_domains; + } cases[] = { + {nullptr, nullptr, ParseResult::SUCCESS, {}, {}}, + {base::MakeUnique<DomainVec>(DomainVec()), + nullptr, + ParseResult::ERROR_EMPTY_DOMAINS_LIST, + {}, + {}}, + {nullptr, + base::MakeUnique<DomainVec>(DomainVec()), + ParseResult::SUCCESS, + {}, + {}}, + {base::MakeUnique<DomainVec>(DomainVec({"a.com", "b.com", "a.com"})), + base::MakeUnique<DomainVec>(DomainVec({"g.com", "A.COM", "g.com"})), + ParseResult::SUCCESS, + {"a.com", "a.com", "b.com"}, + {"a.com", "g.com", "g.com"}}}; + + for (size_t i = 0; i < arraysize(cases); ++i) { + SCOPED_TRACE(base::StringPrintf("Testing case[%" PRIuS "]", i)); + std::unique_ptr<dnr_api::Rule> rule = CreateGenericParsedRule(); + rule->condition.domains = std::move(cases[i].domains); + rule->condition.excluded_domains = std::move(cases[i].excluded_domains); + + IndexedRule indexed_rule; + ParseResult result = + IndexedRule::CreateIndexedRule(std::move(rule), &indexed_rule); + + EXPECT_EQ(cases[i].expected_result, result); + if (result == ParseResult::SUCCESS) { + EXPECT_EQ(cases[i].expected_domains, indexed_rule.domains); + EXPECT_EQ(cases[i].expected_excluded_domains, + indexed_rule.excluded_domains); + } + } +} + +TEST_F(IndexedRuleTest, RedirectUrlParsing) { + struct { + std::unique_ptr<std::string> redirect_url; + const ParseResult expected_result; + // Only valid if |expected_result| is SUCCESS. + const std::string expected_redirect_url; + } cases[] = {{base::MakeUnique<std::string>(""), + ParseResult::ERROR_EMPTY_REDIRECT_URL, ""}, + {nullptr, ParseResult::ERROR_EMPTY_REDIRECT_URL, ""}, + {base::MakeUnique<std::string>("http://google.com"), + ParseResult::SUCCESS, "http://google.com"}, + {base::MakeUnique<std::string>("abc"), + ParseResult::ERROR_INVALID_REDIRECT_URL, ""}}; + + for (size_t i = 0; i < arraysize(cases); ++i) { + SCOPED_TRACE(base::StringPrintf("Testing case[%" PRIuS "]", i)); + std::unique_ptr<dnr_api::Rule> rule = CreateGenericParsedRule(); + rule->action.redirect_url = std::move(cases[i].redirect_url); + rule->action.type = dnr_api::RULE_ACTION_TYPE_REDIRECT; + rule->priority = base::MakeUnique<int>(kMinValidPriority); + + IndexedRule indexed_rule; + ParseResult result = + IndexedRule::CreateIndexedRule(std::move(rule), &indexed_rule); + + EXPECT_EQ(cases[i].expected_result, result); + if (result == ParseResult::SUCCESS) + EXPECT_EQ(cases[i].expected_redirect_url, indexed_rule.redirect_url); + } +} + +} // namespace +} // namespace declarative_net_request +} // namespace extensions
diff --git a/extensions/shell/browser/desktop_controller.h b/extensions/shell/browser/desktop_controller.h index 9971dcb..f262800 100644 --- a/extensions/shell/browser/desktop_controller.h +++ b/extensions/shell/browser/desktop_controller.h
@@ -11,10 +11,6 @@ class BrowserContext; } -namespace gfx { -class Size; -} - namespace extensions { class AppWindow; class Extension; @@ -34,10 +30,6 @@ // we need a singleton somewhere). static DesktopController* instance(); - // Get the size of the window created by this DesktopController. This should - // typically be full-screen. - virtual gfx::Size GetWindowSize() = 0; - // Creates a new app window and adds it to the desktop. The desktop maintains // ownership of the window. The window must be closed before |extension| is // destroyed.
diff --git a/extensions/shell/browser/shell_desktop_controller_aura.cc b/extensions/shell/browser/shell_desktop_controller_aura.cc index 17bd951f..0b0d4866 100644 --- a/extensions/shell/browser/shell_desktop_controller_aura.cc +++ b/extensions/shell/browser/shell_desktop_controller_aura.cc
@@ -217,10 +217,6 @@ extensions::AppWindowClient::Set(NULL); } -gfx::Size ShellDesktopControllerAura::GetWindowSize() { - return host_->window()->bounds().size(); -} - AppWindow* ShellDesktopControllerAura::CreateAppWindow( content::BrowserContext* context, const Extension* extension) { @@ -281,7 +277,7 @@ #endif void ShellDesktopControllerAura::OnHostCloseRequested( - const aura::WindowTreeHost* host) { + aura::WindowTreeHost* host) { DCHECK_EQ(host_.get(), host); CloseAppWindows(); base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/extensions/shell/browser/shell_desktop_controller_aura.h b/extensions/shell/browser/shell_desktop_controller_aura.h index 1cd6717..02f960e 100644 --- a/extensions/shell/browser/shell_desktop_controller_aura.h +++ b/extensions/shell/browser/shell_desktop_controller_aura.h
@@ -71,7 +71,6 @@ aura::WindowTreeHost* host() { return host_.get(); } // DesktopController: - gfx::Size GetWindowSize() override; AppWindow* CreateAppWindow(content::BrowserContext* context, const Extension* extension) override; void AddAppWindow(gfx::NativeWindow window) override; @@ -95,7 +94,7 @@ #endif // aura::WindowTreeHostObserver overrides: - void OnHostCloseRequested(const aura::WindowTreeHost* host) override; + void OnHostCloseRequested(aura::WindowTreeHost* host) override; // ui::internal::InputMethodDelegate overrides: ui::EventDispatchDetails DispatchKeyEventPostIME(
diff --git a/extensions/shell/browser/shell_desktop_controller_mac.h b/extensions/shell/browser/shell_desktop_controller_mac.h index cab3595..17e9ea9 100644 --- a/extensions/shell/browser/shell_desktop_controller_mac.h +++ b/extensions/shell/browser/shell_desktop_controller_mac.h
@@ -23,7 +23,6 @@ ~ShellDesktopControllerMac() override; // DesktopController: - gfx::Size GetWindowSize() override; AppWindow* CreateAppWindow(content::BrowserContext* context, const Extension* extension) override; void AddAppWindow(gfx::NativeWindow window) override;
diff --git a/extensions/shell/browser/shell_desktop_controller_mac.mm b/extensions/shell/browser/shell_desktop_controller_mac.mm index ae47a91..bf4d662 100644 --- a/extensions/shell/browser/shell_desktop_controller_mac.mm +++ b/extensions/shell/browser/shell_desktop_controller_mac.mm
@@ -7,9 +7,6 @@ #include "extensions/browser/app_window/native_app_window.h" #include "extensions/shell/browser/shell_app_delegate.h" #include "extensions/shell/browser/shell_app_window_client.h" -#include "ui/display/display.h" -#include "ui/display/screen.h" -#include "ui/gfx/geometry/size.h" namespace extensions { @@ -24,11 +21,6 @@ CloseAppWindows(); } -gfx::Size ShellDesktopControllerMac::GetWindowSize() { - // This is the full screen size. - return display::Screen::GetScreen()->GetPrimaryDisplay().bounds().size(); -} - AppWindow* ShellDesktopControllerMac::CreateAppWindow( content::BrowserContext* context, const Extension* extension) {
diff --git a/extensions/shell/browser/shell_native_app_window.cc b/extensions/shell/browser/shell_native_app_window.cc index f11a675..02c137d 100644 --- a/extensions/shell/browser/shell_native_app_window.cc +++ b/extensions/shell/browser/shell_native_app_window.cc
@@ -169,16 +169,6 @@ NOTIMPLEMENTED(); } -gfx::Size ShellNativeAppWindow::GetContentMinimumSize() const { - // Content fills the desktop and cannot be resized. - return DesktopController::instance()->GetWindowSize(); -} - -gfx::Size ShellNativeAppWindow::GetContentMaximumSize() const { - // Content fills the desktop and cannot be resized. - return DesktopController::instance()->GetWindowSize(); -} - void ShellNativeAppWindow::SetContentSizeConstraints( const gfx::Size& min_size, const gfx::Size& max_size) {
diff --git a/extensions/shell/browser/shell_native_app_window.h b/extensions/shell/browser/shell_native_app_window.h index 389d082a..fcc3f6e 100644 --- a/extensions/shell/browser/shell_native_app_window.h +++ b/extensions/shell/browser/shell_native_app_window.h
@@ -20,7 +20,7 @@ AppWindow* app_window() const { return app_window_; } - // ui::BaseView overrides: + // ui::BaseWindow overrides: bool IsMaximized() const override; bool IsMinimized() const override; bool IsFullscreen() const override; @@ -62,8 +62,6 @@ gfx::Insets GetFrameInsets() const override; void ShowWithApp() override; void HideWithApp() override; - gfx::Size GetContentMinimumSize() const override; - gfx::Size GetContentMaximumSize() const override; void SetContentSizeConstraints(const gfx::Size& min_size, const gfx::Size& max_size) override; void SetVisibleOnAllWorkspaces(bool always_visible) override;
diff --git a/extensions/shell/browser/shell_native_app_window_aura.cc b/extensions/shell/browser/shell_native_app_window_aura.cc index c0158965..eaf92c5 100644 --- a/extensions/shell/browser/shell_native_app_window_aura.cc +++ b/extensions/shell/browser/shell_native_app_window_aura.cc
@@ -68,4 +68,13 @@ GetNativeWindow()->SetBounds(bounds); } +gfx::Size ShellNativeAppWindowAura::GetContentMinimumSize() const { + // Content fills the desktop and cannot be resized. + return GetNativeWindow()->GetBoundsInRootWindow().size(); +} + +gfx::Size ShellNativeAppWindowAura::GetContentMaximumSize() const { + return GetContentMinimumSize(); +} + } // namespace extensions
diff --git a/extensions/shell/browser/shell_native_app_window_aura.h b/extensions/shell/browser/shell_native_app_window_aura.h index c566b02..c2b026b 100644 --- a/extensions/shell/browser/shell_native_app_window_aura.h +++ b/extensions/shell/browser/shell_native_app_window_aura.h
@@ -27,6 +27,10 @@ void Deactivate() override; void SetBounds(const gfx::Rect& bounds) override; + // NativeAppWindow: + gfx::Size GetContentMinimumSize() const override; + gfx::Size GetContentMaximumSize() const override; + private: DISALLOW_COPY_AND_ASSIGN(ShellNativeAppWindowAura); };
diff --git a/extensions/shell/browser/shell_native_app_window_aura_unittest.cc b/extensions/shell/browser/shell_native_app_window_aura_unittest.cc index e762045..067b1f27 100644 --- a/extensions/shell/browser/shell_native_app_window_aura_unittest.cc +++ b/extensions/shell/browser/shell_native_app_window_aura_unittest.cc
@@ -15,10 +15,10 @@ #include "extensions/browser/extensions_test.h" #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" -#include "extensions/shell/browser/desktop_controller.h" #include "extensions/shell/browser/shell_app_delegate.h" #include "extensions/shell/browser/shell_app_window_client.h" #include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/size.h" namespace extensions { @@ -64,6 +64,10 @@ gfx::Rect bounds = window.GetBounds(); EXPECT_EQ(window_spec.bounds, bounds); + // The window should not be resizable from the extension API. + EXPECT_EQ(bounds.size(), window.GetContentMinimumSize()); + EXPECT_EQ(bounds.size(), window.GetContentMaximumSize()); + // Delete the AppWindow. app_window->OnNativeClose(); }
diff --git a/extensions/shell/browser/shell_native_app_window_mac.h b/extensions/shell/browser/shell_native_app_window_mac.h index 23b0fe3..92c26cc7 100644 --- a/extensions/shell/browser/shell_native_app_window_mac.h +++ b/extensions/shell/browser/shell_native_app_window_mac.h
@@ -49,6 +49,10 @@ void Deactivate() override; void SetBounds(const gfx::Rect& bounds) override; + // NativeAppWindow: + gfx::Size GetContentMinimumSize() const override; + gfx::Size GetContentMaximumSize() const override; + // Called when the window is about to close. void WindowWillClose();
diff --git a/extensions/shell/browser/shell_native_app_window_mac.mm b/extensions/shell/browser/shell_native_app_window_mac.mm index 2b879e8..9440d35 100644 --- a/extensions/shell/browser/shell_native_app_window_mac.mm +++ b/extensions/shell/browser/shell_native_app_window_mac.mm
@@ -10,6 +10,9 @@ #include "base/mac/foundation_util.h" #include "base/strings/sys_string_conversions.h" #include "content/public/browser/web_contents.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" +#include "ui/gfx/geometry/size.h" #import "ui/gfx/mac/coordinate_conversion.h" @implementation ShellNativeAppWindowController @@ -107,6 +110,15 @@ NOTIMPLEMENTED(); } +gfx::Size ShellNativeAppWindowMac::GetContentMinimumSize() const { + // Content fills the display and cannot be resized. + return display::Screen::GetScreen()->GetPrimaryDisplay().bounds().size(); +} + +gfx::Size ShellNativeAppWindowMac::GetContentMaximumSize() const { + return GetContentMinimumSize(); +} + void ShellNativeAppWindowMac::WindowWillClose() { [window_controller_ setAppWindow:NULL]; app_window()->OnNativeWindowChanged();
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index f525b24..9e04b94b 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -8871,6 +8871,9 @@ if (!surface_->SetDrawRectangle(rect)) { LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glSetDrawRectangleCHROMIUM", "failed on surface"); + LOG(ERROR) << "Context lost because SetDrawRectangleCHROMIUM failed."; + MarkContextLost(error::kUnknown); + group_->LoseContexts(error::kUnknown); } OnFboChanged(); } @@ -17050,8 +17053,8 @@ bool unpack_premultiply_alpha_change = (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0; // TODO(qiankun.miao@intel.com): Support level > 0 for CopyTexImage. - if (image && dest_level == 0 && !unpack_flip_y && - !unpack_premultiply_alpha_change) { + if (image && internal_format == source_internal_format && dest_level == 0 && + !unpack_flip_y && !unpack_premultiply_alpha_change) { glBindTexture(dest_binding_target, dest_texture->service_id()); if (image->CopyTexImage(dest_target)) return; @@ -17260,8 +17263,8 @@ bool unpack_premultiply_alpha_change = (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0; // TODO(qiankun.miao@intel.com): Support level > 0 for CopyTexSubImage. - if (image && dest_level == 0 && !unpack_flip_y && - !unpack_premultiply_alpha_change) { + if (image && dest_internal_format == source_internal_format && + dest_level == 0 && !unpack_flip_y && !unpack_premultiply_alpha_change) { ScopedTextureBinder binder(&state_, dest_texture->service_id(), dest_binding_target); if (image->CopyTexSubImage(dest_target, gfx::Point(xoffset, yoffset),
diff --git a/gpu/ipc/service/direct_composition_child_surface_win.cc b/gpu/ipc/service/direct_composition_child_surface_win.cc index 965186d..e3ec3f8 100644 --- a/gpu/ipc/service/direct_composition_child_surface_win.cc +++ b/gpu/ipc/service/direct_composition_child_surface_win.cc
@@ -81,7 +81,7 @@ swap_chain_.Reset(); } -void DirectCompositionChildSurfaceWin::InitializeSurface() { +bool DirectCompositionChildSurfaceWin::InitializeSurface() { TRACE_EVENT1("gpu", "DirectCompositionChildSurfaceWin::InitializeSurface()", "enable_dc_layers_", enable_dc_layers_); DCHECK(!dcomp_surface_); @@ -122,8 +122,9 @@ d3d11_device_.Get(), &desc, nullptr, swap_chain_.GetAddressOf()); has_been_rendered_to_ = false; first_swap_ = true; - CHECK(SUCCEEDED(hr)); + return SUCCEEDED(hr); } + return true; } void DirectCompositionChildSurfaceWin::ReleaseDrawTexture(bool will_discard) { @@ -241,7 +242,10 @@ if ((enable_dc_layers_ && !dcomp_surface_) || (!enable_dc_layers_ && !swap_chain_)) { ReleaseCurrentSurface(); - InitializeSurface(); + if (!InitializeSurface()) { + LOG(ERROR) << "InitializeSurface failed"; + return false; + } } if (!gfx::Rect(size_).Contains(rectangle)) {
diff --git a/gpu/ipc/service/direct_composition_child_surface_win.h b/gpu/ipc/service/direct_composition_child_surface_win.h index a91d43c..2a158aca 100644 --- a/gpu/ipc/service/direct_composition_child_surface_win.h +++ b/gpu/ipc/service/direct_composition_child_surface_win.h
@@ -50,7 +50,7 @@ private: void ReleaseCurrentSurface(); - void InitializeSurface(); + bool InitializeSurface(); // Release the texture that's currently being drawn to. If will_discard is // true then the surface should be discarded without swapping any contents // to it.
diff --git a/headless/app/headless_shell.cc b/headless/app/headless_shell.cc index 3646448..cf22fde 100644 --- a/headless/app/headless_shell.cc +++ b/headless/app/headless_shell.cc
@@ -20,6 +20,7 @@ #include "base/numerics/safe_conversions.h" #include "base/strings/string_number_conversions.h" #include "base/task_scheduler/post_task.h" +#include "build/build_config.h" #include "content/public/app/content_main.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/content_switches.h" @@ -601,8 +602,12 @@ #endif // defined(OS_WIN) HeadlessShell shell; - const base::CommandLine& command_line( - *base::CommandLine::ForCurrentProcess()); +#if defined(OS_FUCHSIA) + // TODO(fuchsia): Remove this when GPU accelerated compositing is ready. + base::CommandLine::ForCurrentProcess()->AppendSwitch(::switches::kDisableGpu); +#endif + + base::CommandLine& command_line(*base::CommandLine::ForCurrentProcess()); if (!ValidateCommandLine(command_line)) return EXIT_FAILURE;
diff --git a/headless/lib/frame_id_browsertest.cc b/headless/lib/frame_id_browsertest.cc index 3fb97c7a..e68f70b 100644 --- a/headless/lib/frame_id_browsertest.cc +++ b/headless/lib/frame_id_browsertest.cc
@@ -31,7 +31,7 @@ public: explicit TestProtocolHandler( scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner) - : test_delegate_(new TestDelegate(this)), + : test_delegate_(new TestDelegate()), dispatcher_(new ExpeditedDispatcher(io_thread_task_runner)), headless_browser_context_(nullptr) {} @@ -65,17 +65,15 @@ class MockURLFetcher : public URLFetcher { public: - explicit MockURLFetcher(const TestProtocolHandler* protocol_handler) + explicit MockURLFetcher(TestProtocolHandler* protocol_handler) : protocol_handler_(protocol_handler) {} ~MockURLFetcher() override {} // URLFetcher implementation: - void StartFetch(const GURL& url, - const std::string& method, - const std::string& post_data, - const net::HttpRequestHeaders& request_headers, + void StartFetch(const Request* request, ResultListener* result_listener) override { - EXPECT_EQ("GET", method); + GURL url = request->GetURLRequest()->url(); + EXPECT_EQ("GET", request->GetURLRequest()->method()); const Response* response = protocol_handler_->GetResponse(url.spec()); if (!response) @@ -84,31 +82,25 @@ net::LoadTimingInfo load_timing_info; result_listener->OnFetchCompleteExtractHeaders( url, response->data.c_str(), response->data.size(), load_timing_info); + + int frame_tree_node_id = request->GetFrameTreeNodeId(); + DCHECK_NE(frame_tree_node_id, -1) << " For url " << url; + protocol_handler_->url_to_frame_tree_node_id_[url.spec()] = + frame_tree_node_id; } private: - const TestProtocolHandler* protocol_handler_; + TestProtocolHandler* protocol_handler_; DISALLOW_COPY_AND_ASSIGN(MockURLFetcher); }; class TestDelegate : public GenericURLRequestJob::Delegate { public: - explicit TestDelegate(TestProtocolHandler* protocol_handler) - : protocol_handler_(protocol_handler) {} - + TestDelegate() {} ~TestDelegate() override {} // GenericURLRequestJob::Delegate implementation: - void OnPendingRequest(PendingRequest* pending_request) override { - const Request* request = pending_request->GetRequest(); - std::string url = request->GetURLRequest()->url().spec(); - int frame_tree_node_id = request->GetFrameTreeNodeId(); - DCHECK_NE(frame_tree_node_id, -1) << " For url " << url; - protocol_handler_->url_to_frame_tree_node_id_[url] = frame_tree_node_id; - pending_request->AllowRequest(); - } - void OnResourceLoadFailed(const Request* request, net::Error error) override {} @@ -120,7 +112,6 @@ size_t body_size) override {} private: - TestProtocolHandler* protocol_handler_; // NOT OWNED scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_; DISALLOW_COPY_AND_ASSIGN(TestDelegate); @@ -132,8 +123,9 @@ net::NetworkDelegate* network_delegate) const override { return new GenericURLRequestJob( request, network_delegate, dispatcher_.get(), - base::MakeUnique<MockURLFetcher>(this), test_delegate_.get(), - headless_browser_context_); + base::MakeUnique<MockURLFetcher>( + const_cast<TestProtocolHandler*>(this)), + test_delegate_.get(), headless_browser_context_); } std::map<std::string, int> url_to_frame_tree_node_id_;
diff --git a/headless/public/util/deterministic_http_protocol_handler.cc b/headless/public/util/deterministic_http_protocol_handler.cc index 62358559..8ff8e37 100644 --- a/headless/public/util/deterministic_http_protocol_handler.cc +++ b/headless/public/util/deterministic_http_protocol_handler.cc
@@ -22,11 +22,6 @@ NopGenericURLRequestJobDelegate() {} ~NopGenericURLRequestJobDelegate() override {} - // GenericURLRequestJob::Delegate methods: - void OnPendingRequest(PendingRequest* pending_request) override { - pending_request->AllowRequest(); - } - void OnResourceLoadFailed(const Request* request, net::Error error) override { }
diff --git a/headless/public/util/generic_url_request_job.cc b/headless/public/util/generic_url_request_job.cc index 73162804..316df42 100644 --- a/headless/public/util/generic_url_request_job.cc +++ b/headless/public/util/generic_url_request_job.cc
@@ -79,15 +79,12 @@ void GenericURLRequestJob::Start() { PrepareCookies(request_->url(), request_->method(), - url::Origin(request_->first_party_for_cookies()), - base::Bind(&Delegate::OnPendingRequest, - base::Unretained(delegate_), this)); + url::Origin(request_->first_party_for_cookies())); } void GenericURLRequestJob::PrepareCookies(const GURL& rewritten_url, const std::string& method, - const url::Origin& site_for_cookies, - const base::Closure& done_callback) { + const url::Origin& site_for_cookies) { DCHECK(origin_task_runner_->RunsTasksInCurrentSequence()); net::CookieStore* cookie_store = request_->context()->cookie_store(); net::CookieOptions options; @@ -112,14 +109,12 @@ cookie_store->GetCookieListWithOptionsAsync( rewritten_url, options, base::Bind(&GenericURLRequestJob::OnCookiesAvailable, - weak_factory_.GetWeakPtr(), rewritten_url, method, - done_callback)); + weak_factory_.GetWeakPtr(), rewritten_url, method)); } void GenericURLRequestJob::OnCookiesAvailable( const GURL& rewritten_url, const std::string& method, - const base::Closure& done_callback, const net::CookieList& cookie_list) { DCHECK(origin_task_runner_->RunsTasksInCurrentSequence()); // TODO(alexclarke): Set user agent. @@ -128,7 +123,7 @@ if (!cookie.empty()) extra_request_headers_.SetHeader(net::HttpRequestHeaders::kCookie, cookie); - done_callback.Run(); + url_fetcher_->StartFetch(this, this); } void GenericURLRequestJob::OnFetchStartError(net::Error error) { @@ -198,6 +193,11 @@ return request_; } +const net::HttpRequestHeaders& GenericURLRequestJob::GetHttpRequestHeaders() + const { + return extra_request_headers_; +} + int GenericURLRequestJob::GetFrameTreeNodeId() const { // URLRequestUserData will be set for all renderer initiated resource // requests, but not for browser side navigations. @@ -375,69 +375,4 @@ return reader->GetContentLength(); } -const Request* GenericURLRequestJob::GetRequest() const { - return this; -} - -void GenericURLRequestJob::AllowRequest() { - if (!origin_task_runner_->RunsTasksInCurrentSequence()) { - origin_task_runner_->PostTask( - FROM_HERE, base::Bind(&GenericURLRequestJob::AllowRequest, - weak_factory_.GetWeakPtr())); - return; - } - - url_fetcher_->StartFetch(request_->url(), request_->method(), GetPostData(), - extra_request_headers_, this); -} - -void GenericURLRequestJob::BlockRequest(net::Error error) { - if (!origin_task_runner_->RunsTasksInCurrentSequence()) { - origin_task_runner_->PostTask( - FROM_HERE, base::Bind(&GenericURLRequestJob::BlockRequest, - weak_factory_.GetWeakPtr(), error)); - return; - } - - DispatchStartError(error); -} - -void GenericURLRequestJob::ModifyRequest( - const GURL& url, - const std::string& method, - const std::string& post_data, - const net::HttpRequestHeaders& request_headers) { - if (!origin_task_runner_->RunsTasksInCurrentSequence()) { - origin_task_runner_->PostTask( - FROM_HERE, base::Bind(&GenericURLRequestJob::ModifyRequest, - weak_factory_.GetWeakPtr(), url, method, - post_data, request_headers)); - return; - } - - extra_request_headers_ = request_headers; - PrepareCookies( - request_->url(), request_->method(), - url::Origin(request_->first_party_for_cookies()), - base::Bind(&URLFetcher::StartFetch, base::Unretained(url_fetcher_.get()), - url, method, post_data, request_headers, this)); -} - -void GenericURLRequestJob::MockResponse( - std::unique_ptr<MockResponseData> mock_response) { - if (!origin_task_runner_->RunsTasksInCurrentSequence()) { - origin_task_runner_->PostTask( - FROM_HERE, base::Bind(&GenericURLRequestJob::MockResponse, - weak_factory_.GetWeakPtr(), - base::Passed(std::move(mock_response)))); - return; - } - - mock_response_ = std::move(mock_response); - - OnFetchCompleteExtractHeaders( - request_->url(), mock_response_->response_data.data(), - mock_response_->response_data.size(), mock_response_->load_timing_info); -} - } // namespace headless
diff --git a/headless/public/util/generic_url_request_job.h b/headless/public/util/generic_url_request_job.h index 59be8b8..c05b452 100644 --- a/headless/public/util/generic_url_request_job.h +++ b/headless/public/util/generic_url_request_job.h
@@ -42,6 +42,8 @@ virtual const net::URLRequest* GetURLRequest() const = 0; + virtual const net::HttpRequestHeaders& GetHttpRequestHeaders() const = 0; + // The frame from which the request came from. virtual int GetFrameTreeNodeId() const = 0; @@ -89,42 +91,6 @@ DISALLOW_COPY_AND_ASSIGN(Request); }; -// Details of a pending request received by GenericURLRequestJob which must be -// either Allowed, Blocked, Modified or have it's response Mocked. -class HEADLESS_EXPORT PendingRequest { - public: - virtual const Request* GetRequest() const = 0; - - // Allows the request to proceed as normal. - virtual void AllowRequest() = 0; - - // Causes the request to fail with the specified |error|. - virtual void BlockRequest(net::Error error) = 0; - - // Allows the request to be completely re-written. - virtual void ModifyRequest( - const GURL& url, - const std::string& method, - const std::string& post_data, - const net::HttpRequestHeaders& request_headers) = 0; - - struct MockResponseData { - std::string response_data; - net::LoadTimingInfo load_timing_info; - }; - - // Instead of fetching the request, |mock_response| is returned instead. - virtual void MockResponse( - std::unique_ptr<MockResponseData> mock_response) = 0; - - protected: - PendingRequest() {} - virtual ~PendingRequest() {} - - private: - DISALLOW_COPY_AND_ASSIGN(PendingRequest); -}; - // Intended for use in a protocol handler, this ManagedDispatchURLRequestJob has // the following features: // @@ -134,16 +100,10 @@ class HEADLESS_EXPORT GenericURLRequestJob : public ManagedDispatchURLRequestJob, public URLFetcher::ResultListener, - public PendingRequest, public Request { public: class HEADLESS_EXPORT Delegate { public: - // Notifies the delegate of an PendingRequest which must either be - // allowed, blocked, modifed or it's response mocked. Called on an arbitrary - // thread. - virtual void OnPendingRequest(PendingRequest* pending_request) = 0; - // Notifies the delegate of any fetch failure. Called on an arbitrary // thread. virtual void OnResourceLoadFailed(const Request* request, @@ -191,6 +151,7 @@ protected: // Request implementation: uint64_t GetRequestId() const override; + const net::HttpRequestHeaders& GetHttpRequestHeaders() const override; const net::URLRequest* GetURLRequest() const override; int GetFrameTreeNodeId() const override; std::string GetDevToolsAgentHostId() const override; @@ -199,31 +160,18 @@ ResourceType GetResourceType() const override; bool IsAsync() const override; - // PendingRequest implementation: - const Request* GetRequest() const override; - void AllowRequest() override; - void BlockRequest(net::Error error) override; - void ModifyRequest(const GURL& url, - const std::string& method, - const std::string& post_data, - const net::HttpRequestHeaders& request_headers) override; - void MockResponse(std::unique_ptr<MockResponseData> mock_response) override; - private: void PrepareCookies(const GURL& rewritten_url, const std::string& method, - const url::Origin& site_for_cookies, - const base::Closure& done_callback); + const url::Origin& site_for_cookies); void OnCookiesAvailable(const GURL& rewritten_url, const std::string& method, - const base::Closure& done_callback, const net::CookieList& cookie_list); std::unique_ptr<URLFetcher> url_fetcher_; net::HttpRequestHeaders extra_request_headers_; scoped_refptr<net::HttpResponseHeaders> response_headers_; scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_; - std::unique_ptr<MockResponseData> mock_response_; Delegate* delegate_; // Not owned. HeadlessBrowserContext* headless_browser_context_; // Not owned. const content::ResourceRequestInfo* request_resource_info_; // Not owned.
diff --git a/headless/public/util/generic_url_request_job_test.cc b/headless/public/util/generic_url_request_job_test.cc index e14a20d..23b3f34 100644 --- a/headless/public/util/generic_url_request_job_test.cc +++ b/headless/public/util/generic_url_request_job_test.cc
@@ -57,29 +57,34 @@ class MockFetcher : public URLFetcher { public: MockFetcher(base::DictionaryValue* fetch_request, - std::map<std::string, std::string>* json_fetch_reply_map) + std::map<std::string, std::string>* json_fetch_reply_map, + base::Callback<void(const Request*)>* on_request_callback) : json_fetch_reply_map_(json_fetch_reply_map), - fetch_request_(fetch_request) {} + fetch_request_(fetch_request), + on_request_callback_(on_request_callback) {} ~MockFetcher() override {} - void StartFetch(const GURL& url, - const std::string& method, - const std::string& post_data, - const net::HttpRequestHeaders& request_headers, + void StartFetch(const Request* request, ResultListener* result_listener) override { + if (!on_request_callback_->is_null()) + on_request_callback_->Run(request); + // Record the request. - fetch_request_->SetString("url", url.spec()); - fetch_request_->SetString("method", method); + std::string url = request->GetURLRequest()->url().spec(); + fetch_request_->SetString("url", url); + fetch_request_->SetString("method", request->GetURLRequest()->method()); std::unique_ptr<base::DictionaryValue> headers(new base::DictionaryValue); - for (net::HttpRequestHeaders::Iterator it(request_headers); it.GetNext();) { + for (net::HttpRequestHeaders::Iterator it(request->GetHttpRequestHeaders()); + it.GetNext();) { headers->SetString(it.name(), it.value()); } fetch_request_->Set("headers", std::move(headers)); + std::string post_data = request->GetPostData(); if (!post_data.empty()) - fetch_request_->SetString("post_data", post_data); + fetch_request_->SetString("post_data", std::move(post_data)); - const auto find_it = json_fetch_reply_map_->find(url.spec()); + const auto find_it = json_fetch_reply_map_->find(url); if (find_it == json_fetch_reply_map_->end()) { result_listener->OnFetchStartError(net::ERR_ADDRESS_UNREACHABLE); return; @@ -120,7 +125,8 @@ private: std::map<std::string, std::string>* json_fetch_reply_map_; // NOT OWNED - base::DictionaryValue* fetch_request_; // NOT OWNED + base::DictionaryValue* fetch_request_; // NOT OWNED + base::Callback<void(const Request*)>* on_request_callback_; // NOT OWNED std::string response_data_; // Here to ensure the required lifetime. }; @@ -131,11 +137,13 @@ MockProtocolHandler(base::DictionaryValue* fetch_request, std::map<std::string, std::string>* json_fetch_reply_map, URLRequestDispatcher* dispatcher, - GenericURLRequestJob::Delegate* job_delegate) + GenericURLRequestJob::Delegate* job_delegate, + base::Callback<void(const Request*)>* on_request_callback) : fetch_request_(fetch_request), json_fetch_reply_map_(json_fetch_reply_map), job_delegate_(job_delegate), - dispatcher_(dispatcher) {} + dispatcher_(dispatcher), + on_request_callback_(on_request_callback) {} // net::URLRequestJobFactory::ProtocolHandler override. net::URLRequestJob* MaybeCreateJob( @@ -143,15 +151,17 @@ net::NetworkDelegate* network_delegate) const override { return new GenericURLRequestJob( request, network_delegate, dispatcher_, - base::MakeUnique<MockFetcher>(fetch_request_, json_fetch_reply_map_), + base::MakeUnique<MockFetcher>(fetch_request_, json_fetch_reply_map_, + on_request_callback_), job_delegate_, nullptr); } private: - base::DictionaryValue* fetch_request_; // NOT OWNED - std::map<std::string, std::string>* json_fetch_reply_map_; // NOT OWNED - GenericURLRequestJob::Delegate* job_delegate_; // NOT OWNED - URLRequestDispatcher* dispatcher_; // NOT OWNED + base::DictionaryValue* fetch_request_; // NOT OWNED + std::map<std::string, std::string>* json_fetch_reply_map_; // NOT OWNED + GenericURLRequestJob::Delegate* job_delegate_; // NOT OWNED + URLRequestDispatcher* dispatcher_; // NOT OWNED + base::Callback<void(const Request*)>* on_request_callback_; // NOT OWNED }; } // namespace @@ -162,7 +172,7 @@ url_request_job_factory_.SetProtocolHandler( "https", base::WrapUnique(new MockProtocolHandler( &fetch_request_, &json_fetch_reply_map_, &dispatcher_, - &job_delegate_))); + &job_delegate_, &on_request_callback_))); url_request_context_.set_job_factory(&url_request_job_factory_); url_request_context_.set_cookie_store(&cookie_store_); } @@ -212,6 +222,7 @@ std::map<std::string, std::string> json_fetch_reply_map_; // Replies to be sent by MockFetcher. MockDelegate job_delegate_; + base::Callback<void(const Request*)> on_request_callback_; }; TEST_F(GenericURLRequestJobTest, BasicGetRequestParams) { @@ -461,159 +472,6 @@ EXPECT_THAT(fetch_request_, MatchesJson(expected_request_json)); } -TEST_F(GenericURLRequestJobTest, DelegateBlocksLoading) { - std::string reply = R"( - { - "url": "https://example.com", - "data": "Reply", - "headers": { - "Content-Type": "text/html; charset=UTF-8" - } - })"; - - job_delegate_.SetPolicy(base::Bind([](PendingRequest* pending_request) { - pending_request->BlockRequest(net::ERR_FILE_NOT_FOUND); - })); - - std::unique_ptr<net::URLRequest> request( - CreateAndCompleteGetJob(GURL("https://example.com"), reply)); - - EXPECT_EQ(net::URLRequestStatus::FAILED, request->status().status()); - EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request->status().error()); -} - -TEST_F(GenericURLRequestJobTest, DelegateModifiesRequest) { - json_fetch_reply_map_["https://example.com/"] = R"( - { - "url": "https://example.com", - "data": "Welcome to example.com", - "headers": { - "Content-Type": "text/html; charset=UTF-8" - } - })"; - - json_fetch_reply_map_["https://othersite.com/"] = R"( - { - "url": "https://example.com", - "data": "Welcome to othersite.com", - "headers": { - "Content-Type": "text/html; charset=UTF-8" - } - })"; - - // Turn the GET into a POST to a different site. - job_delegate_.SetPolicy(base::Bind([](PendingRequest* pending_request) { - net::HttpRequestHeaders headers; - headers.SetHeader("TestHeader", "Hello"); - pending_request->ModifyRequest(GURL("https://othersite.com"), "POST", - "Some post data!", headers); - })); - - std::unique_ptr<net::URLRequest> request(url_request_context_.CreateRequest( - GURL("https://example.com"), net::DEFAULT_PRIORITY, &request_delegate_, - TRAFFIC_ANNOTATION_FOR_TESTS)); - request->Start(); - base::RunLoop().RunUntilIdle(); - - std::string expected_request_json = R"( - { - "url": "https://othersite.com/", - "method": "POST", - "post_data": "Some post data!", - "headers": { - "TestHeader": "Hello" - } - })"; - - EXPECT_THAT(fetch_request_, MatchesJson(expected_request_json)); - - EXPECT_EQ(200, request->GetResponseCode()); - // The modification should not be visible to the URlRequest. - EXPECT_EQ("https://example.com/", request->url().spec()); - EXPECT_EQ("GET", request->method()); - - const int kBufferSize = 256; - scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize)); - int bytes_read; - EXPECT_TRUE(request->Read(buffer.get(), kBufferSize, &bytes_read)); - EXPECT_EQ(24, bytes_read); - EXPECT_EQ("Welcome to othersite.com", - std::string(buffer->data(), bytes_read)); -} - -TEST_F(GenericURLRequestJobTest, DelegateMocks404Response) { - std::string reply = R"( - { - "url": "https://example.com", - "data": "Reply", - "headers": { - "Content-Type": "text/html; charset=UTF-8" - } - })"; - - job_delegate_.SetPolicy(base::Bind([](PendingRequest* pending_request) { - std::unique_ptr<GenericURLRequestJob::MockResponseData> mock_response_data( - new GenericURLRequestJob::MockResponseData()); - mock_response_data->response_data = "HTTP/1.1 404 Not Found\r\n\r\n"; - pending_request->MockResponse(std::move(mock_response_data)); - })); - - std::unique_ptr<net::URLRequest> request( - CreateAndCompleteGetJob(GURL("https://example.com"), reply)); - - EXPECT_EQ(404, request->GetResponseCode()); -} - -TEST_F(GenericURLRequestJobTest, DelegateMocks302Response) { - job_delegate_.SetPolicy(base::Bind([](PendingRequest* pending_request) { - if (pending_request->GetRequest()->GetURLRequest()->url().spec() == - "https://example.com/") { - std::unique_ptr<GenericURLRequestJob::MockResponseData> - mock_response_data(new GenericURLRequestJob::MockResponseData()); - mock_response_data->response_data = - "HTTP/1.1 302 Found\r\n" - "Location: https://foo.com/\r\n\r\n"; - pending_request->MockResponse(std::move(mock_response_data)); - } else { - pending_request->AllowRequest(); - } - })); - - json_fetch_reply_map_["https://example.com/"] = R"( - { - "url": "https://example.com", - "data": "Welcome to example.com", - "headers": { - "Content-Type": "text/html; charset=UTF-8" - } - })"; - - json_fetch_reply_map_["https://foo.com/"] = R"( - { - "url": "https://example.com", - "data": "Welcome to foo.com", - "headers": { - "Content-Type": "text/html; charset=UTF-8" - } - })"; - - std::unique_ptr<net::URLRequest> request(url_request_context_.CreateRequest( - GURL("https://example.com"), net::DEFAULT_PRIORITY, &request_delegate_, - TRAFFIC_ANNOTATION_FOR_TESTS)); - request->Start(); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(200, request->GetResponseCode()); - EXPECT_EQ("https://foo.com/", request->url().spec()); - - const int kBufferSize = 256; - scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize)); - int bytes_read; - EXPECT_TRUE(request->Read(buffer.get(), kBufferSize, &bytes_read)); - EXPECT_EQ(18, bytes_read); - EXPECT_EQ("Welcome to foo.com", std::string(buffer->data(), bytes_read)); -} - TEST_F(GenericURLRequestJobTest, OnResourceLoadFailed) { EXPECT_CALL(job_delegate_, OnResourceLoadFailed(_, net::ERR_ADDRESS_UNREACHABLE)); @@ -637,12 +495,11 @@ })"; std::set<uint64_t> ids; - job_delegate_.SetPolicy(base::Bind( - [](std::set<uint64_t>* ids, PendingRequest* pending_request) { - ids->insert(pending_request->GetRequest()->GetRequestId()); - pending_request->AllowRequest(); + on_request_callback_ = base::Bind( + [](std::set<uint64_t>* ids, const Request* request) { + ids->insert(request->GetRequestId()); }, - &ids)); + &ids); CreateAndCompleteGetJob(GURL("https://example.com"), reply); CreateAndCompleteGetJob(GURL("https://example.com"), reply); @@ -665,14 +522,13 @@ std::string post_data; uint64_t post_data_size; - job_delegate_.SetPolicy(base::Bind( + on_request_callback_ = base::Bind( [](std::string* post_data, uint64_t* post_data_size, - PendingRequest* pending_request) { - *post_data = pending_request->GetRequest()->GetPostData(); - *post_data_size = pending_request->GetRequest()->GetPostDataSize(); - pending_request->AllowRequest(); + const Request* request) { + *post_data = request->GetPostData(); + *post_data_size = request->GetPostDataSize(); }, - &post_data, &post_data_size)); + &post_data, &post_data_size); CreateAndCompletePostJob(GURL("https://example.com"), "payload", reply); @@ -741,14 +597,13 @@ std::string post_data; uint64_t post_data_size; - job_delegate_.SetPolicy(base::Bind( + on_request_callback_ = base::Bind( [](std::string* post_data, uint64_t* post_data_size, - PendingRequest* pending_request) { - *post_data = pending_request->GetRequest()->GetPostData(); - *post_data_size = pending_request->GetRequest()->GetPostDataSize(); - pending_request->AllowRequest(); + const Request* request) { + *post_data = request->GetPostData(); + *post_data_size = request->GetPostDataSize(); }, - &post_data, &post_data_size)); + &post_data, &post_data_size); GURL url("https://example.com"); std::unique_ptr<net::URLRequest> request(url_request_context_.CreateRequest(
diff --git a/headless/public/util/http_url_fetcher.cc b/headless/public/util/http_url_fetcher.cc index eed73af5..20e44ea9 100644 --- a/headless/public/util/http_url_fetcher.cc +++ b/headless/public/util/http_url_fetcher.cc
@@ -4,6 +4,7 @@ #include "headless/public/util/http_url_fetcher.h" +#include "headless/public/util/generic_url_request_job.h" #include "net/base/elements_upload_data_stream.h" #include "net/base/io_buffer.h" #include "net/base/upload_bytes_element_reader.h" @@ -229,14 +230,12 @@ HttpURLFetcher::~HttpURLFetcher() {} -void HttpURLFetcher::StartFetch(const GURL& rewritten_url, - const std::string& method, - const std::string& post_data, - const net::HttpRequestHeaders& request_headers, +void HttpURLFetcher::StartFetch(const Request* request, ResultListener* result_listener) { - delegate_.reset(new Delegate(rewritten_url, method, post_data, - request_headers, url_request_context_, - result_listener)); + delegate_.reset(new Delegate( + request->GetURLRequest()->url(), request->GetURLRequest()->method(), + request->GetPostData(), request->GetHttpRequestHeaders(), + url_request_context_, result_listener)); } } // namespace headless
diff --git a/headless/public/util/http_url_fetcher.h b/headless/public/util/http_url_fetcher.h index c69d9fb2..70bb710b 100644 --- a/headless/public/util/http_url_fetcher.h +++ b/headless/public/util/http_url_fetcher.h
@@ -22,10 +22,7 @@ ~HttpURLFetcher() override; // URLFetcher implementation: - void StartFetch(const GURL& rewritten_url, - const std::string& method, - const std::string& post_data, - const net::HttpRequestHeaders& request_headers, + void StartFetch(const Request* request, ResultListener* result_listener) override; private:
diff --git a/headless/public/util/testing/generic_url_request_mocks.cc b/headless/public/util/testing/generic_url_request_mocks.cc index 844945c0..2d71c85 100644 --- a/headless/public/util/testing/generic_url_request_mocks.cc +++ b/headless/public/util/testing/generic_url_request_mocks.cc
@@ -22,28 +22,6 @@ MockGenericURLRequestJobDelegate::~MockGenericURLRequestJobDelegate() {} -// GenericURLRequestJob::Delegate methods: -void MockGenericURLRequestJobDelegate::OnPendingRequest( - PendingRequest* pending_request) { - // Simulate the client acknowledging the callback from a different thread. - main_thread_task_runner_->PostTask( - FROM_HERE, base::Bind(&MockGenericURLRequestJobDelegate::ApplyPolicy, - base::Unretained(this), pending_request)); -} - -void MockGenericURLRequestJobDelegate::SetPolicy(Policy policy) { - policy_ = std::move(policy); -} - -void MockGenericURLRequestJobDelegate::ApplyPolicy( - PendingRequest* pending_request) { - if (policy_.is_null()) { - pending_request->AllowRequest(); - } else { - policy_.Run(pending_request); - } -} - void MockGenericURLRequestJobDelegate::OnResourceLoadFailed( const Request* request, net::Error error) {}
diff --git a/headless/public/util/testing/generic_url_request_mocks.h b/headless/public/util/testing/generic_url_request_mocks.h index 96b4965..1bfa34b 100644 --- a/headless/public/util/testing/generic_url_request_mocks.h +++ b/headless/public/util/testing/generic_url_request_mocks.h
@@ -26,7 +26,6 @@ ~MockGenericURLRequestJobDelegate() override; // GenericURLRequestJob::Delegate methods: - void OnPendingRequest(PendingRequest* pending_request) override; void OnResourceLoadFailed(const Request* request, net::Error error) override; void OnResourceLoadComplete( const Request* request, @@ -35,14 +34,7 @@ const char* body, size_t body_size) override; - using Policy = base::Callback<void(PendingRequest* pending_request)>; - - void SetPolicy(Policy policy); - private: - void ApplyPolicy(PendingRequest* pending_request); - - Policy policy_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; DISALLOW_COPY_AND_ASSIGN(MockGenericURLRequestJobDelegate);
diff --git a/headless/public/util/url_fetcher.h b/headless/public/util/url_fetcher.h index 59ed86a..7dd7558 100644 --- a/headless/public/util/url_fetcher.h +++ b/headless/public/util/url_fetcher.h
@@ -17,11 +17,11 @@ #include "url/gurl.h" namespace net { -class HttpRequestHeaders; class HttpResponseHeaders; } // namespace net namespace headless { +class Request; // An interface for fetching URLs. Note these are only intended to be used once. class HEADLESS_EXPORT URLFetcher { @@ -62,10 +62,7 @@ DISALLOW_COPY_AND_ASSIGN(ResultListener); }; - virtual void StartFetch(const GURL& url, - const std::string& method, - const std::string& post_data, - const net::HttpRequestHeaders& request_headers, + virtual void StartFetch(const Request* request, ResultListener* result_listener) = 0; private:
diff --git a/ios/chrome/app/main_application_delegate.mm b/ios/chrome/app/main_application_delegate.mm index bb4a6ac..c059ab31a 100644 --- a/ios/chrome/app/main_application_delegate.mm +++ b/ios/chrome/app/main_application_delegate.mm
@@ -4,7 +4,6 @@ #import "ios/chrome/app/main_application_delegate.h" -#include "base/ios/ios_util.h" #include "base/mac/foundation_util.h" #import "ios/chrome/app/application_delegate/app_navigation.h" #import "ios/chrome/app/application_delegate/app_state.h" @@ -245,7 +244,6 @@ BOOL applicationActive = [application applicationState] == UIApplicationStateActive; - DCHECK(applicationActive || !base::ios::IsRunningOnIOS11OrLater()); return [URLOpener openURL:url applicationActive:applicationActive
diff --git a/ios/chrome/browser/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/content_suggestions/content_suggestions_coordinator.mm index b624152c7..6dabf23 100644 --- a/ios/chrome/browser/content_suggestions/content_suggestions_coordinator.mm +++ b/ios/chrome/browser/content_suggestions/content_suggestions_coordinator.mm
@@ -122,6 +122,7 @@ self.headerController = [[ContentSuggestionsHeaderViewController alloc] init]; self.headerController.dispatcher = self.dispatcher; + self.headerController.commandHandler = self; self.headerController.delegate = self; self.headerController.readingListModel = ReadingListModelFactory::GetForBrowserState(self.browserState);
diff --git a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist index 3dcd990e..40104e9 100644 --- a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist +++ b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
@@ -262,6 +262,28 @@ </dict> <dict> <key>Type</key> + <string>PSMultiValueSpecifier</string> + <key>Title</key> + <string>Enable Bookmark Reordering</string> + <key>Key</key> + <string>EnableBookmarkReordering</string> + <key>DefaultValue</key> + <string></string> + <key>Values</key> + <array> + <string></string> + <string>Enabled</string> + <string>Disabled</string> + </array> + <key>Titles</key> + <array> + <string>Default</string> + <string>Enabled</string> + <string>Disabled</string> + </array> + </dict> + <dict> + <key>Type</key> <string>PSGroupSpecifier</string> <key>Title</key> <string>Memory</string> @@ -368,28 +390,6 @@ </dict> <dict> <key>Type</key> - <string>PSMultiValueSpecifier</string> - <key>Title</key> - <string>Enable Bookmark Reordering</string> - <key>Key</key> - <string>EnableBookmarkReordering</string> - <key>DefaultValue</key> - <string></string> - <key>Values</key> - <array> - <string></string> - <string>Enabled</string> - <string>Disabled</string> - </array> - <key>Titles</key> - <array> - <string>Default</string> - <string>Enabled</string> - <string>Disabled</string> - </array> - </dict> - <dict> - <key>Type</key> <string>PSGroupSpecifier</string> <key>Title</key> <string>Web APIs</string>
diff --git a/ios/chrome/browser/tabs/tab_model.h b/ios/chrome/browser/tabs/tab_model.h index 10402a0..c16eb96 100644 --- a/ios/chrome/browser/tabs/tab_model.h +++ b/ios/chrome/browser/tabs/tab_model.h
@@ -235,11 +235,6 @@ // Records tab session metrics. - (void)recordSessionMetrics; -// Purges the web views on all the tabs and reloads the frontmost one if there -// is one. This is used when a userdefault changes and the web views need to be -// re-created to pick it up. -- (void)resetAllWebViews; - // Sets whether the user is primarily interacting with this tab model. - (void)setPrimary:(BOOL)primary;
diff --git a/ios/chrome/browser/tabs/tab_model.mm b/ios/chrome/browser/tabs/tab_model.mm index 7acb8c8..f797749b 100644 --- a/ios/chrome/browser/tabs/tab_model.mm +++ b/ios/chrome/browser/tabs/tab_model.mm
@@ -573,12 +573,6 @@ [_observers tabModel:self didChangeTabSnapshot:tab withImage:image]; } -- (void)resetAllWebViews { - for (Tab* tab in self) { - [tab.webController reinitializeWebViewAndReload:(tab == self.currentTab)]; - } -} - - (void)setWebUsageEnabled:(BOOL)webUsageEnabled { if (_webUsageEnabled == webUsageEnabled) return;
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_collection_view.mm b/ios/chrome/browser/ui/bookmarks/bookmark_collection_view.mm index 04167819..bc49ee6 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_collection_view.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_collection_view.mm
@@ -768,6 +768,11 @@ if (section == 0) return NO; + if (section - 1 == self.promoSection && + experimental_flags::IsSigninPromoEnabled()) { + return NO; + } + if ([self numberOfItemsInSection:(section - 1)] == 0) return NO;
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_signin_promo_cell.mm b/ios/chrome/browser/ui/bookmarks/bookmark_signin_promo_cell.mm index 0e2623b..126b80d 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_signin_promo_cell.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_signin_promo_cell.mm
@@ -5,6 +5,7 @@ #import "ios/chrome/browser/ui/bookmarks/bookmark_signin_promo_cell.h" #import "ios/chrome/browser/ui/authentication/signin_promo_view.h" +#include "ios/chrome/browser/ui/ui_util.h" #import "ios/chrome/browser/ui/util/constraints_ui_util.h" #include "ios/chrome/grit/ios_chromium_strings.h" #include "ui/base/l10n/l10n_util.h" @@ -13,6 +14,10 @@ #error "This file requires ARC support." #endif +namespace { +const NSInteger kSigninPromoMargin = 8; +} + @implementation BookmarkSigninPromoCell { SigninPromoView* _signinPromoView; UIButton* _closeButton; @@ -36,8 +41,16 @@ _signinPromoView = [[SigninPromoView alloc] initWithFrame:self.bounds]; _signinPromoView.translatesAutoresizingMaskIntoConstraints = NO; [contentView addSubview:_signinPromoView]; - AddSameConstraints(_signinPromoView, contentView); - + _signinPromoView.layer.borderColor = + [UIColor colorWithWhite:0.0 alpha:0.08].CGColor; + _signinPromoView.layer.borderWidth = 1.0f; + NSArray* visualConstraints = @[ + @"V:|-0-[signin_promo_view]-(margin)-|", + @"H:|-(margin)-[signin_promo_view]-(margin)-|", + ]; + NSDictionary* views = @{@"signin_promo_view" : _signinPromoView}; + NSDictionary* metrics = @{ @"margin" : @(kSigninPromoMargin) }; + ApplyVisualConstraintsWithMetrics(visualConstraints, views, metrics); _signinPromoView.closeButton.hidden = NO; [_signinPromoView.closeButton addTarget:self action:@selector(closeButtonAction:)
diff --git a/ios/chrome/browser/ui/bubble/BUILD.gn b/ios/chrome/browser/ui/bubble/BUILD.gn index 10e29420..2266f80 100644 --- a/ios/chrome/browser/ui/bubble/BUILD.gn +++ b/ios/chrome/browser/ui/bubble/BUILD.gn
@@ -17,6 +17,9 @@ "//base", "//base:i18n", "//ios/chrome/browser/ui", + "//ios/chrome/browser/ui/colors", + "//ios/chrome/common", + "//ios/third_party/material_components_ios", ] libs = [ "UIKit.framework" ] } @@ -26,7 +29,7 @@ testonly = true sources = [ "bubble_util_unittest.mm", - "bubble_view_controller_unittest.mm", + "bubble_view_unittest.mm", ] deps = [ ":bubble", @@ -34,5 +37,4 @@ "//base:i18n", "//testing/gtest", ] - libs = [ "CoreGraphics.framework" ] }
diff --git a/ios/chrome/browser/ui/bubble/bubble_util_unittest.mm b/ios/chrome/browser/ui/bubble/bubble_util_unittest.mm index 2c53086..a28c67f 100644 --- a/ios/chrome/browser/ui/bubble/bubble_util_unittest.mm +++ b/ios/chrome/browser/ui/bubble/bubble_util_unittest.mm
@@ -14,7 +14,7 @@ #endif namespace { -const CGFloat kTestBubbleAlignmentOffset = 10.0f; +const CGFloat kTestBubbleAlignmentOffset = 40.0f; } // namespace namespace bubble_util { @@ -78,8 +78,8 @@ leftAlignedAnchorPoint_, BubbleArrowDirectionUp, BubbleAlignmentLeading, containerSize_, false /* isRTL */); - EXPECT_TRUE(CGSizeEqualToSize({430.0f + kTestBubbleAlignmentOffset, 350.0f}, - leftAlignedSize)); + EXPECT_FLOAT_EQ(430.0f + kTestBubbleAlignmentOffset, leftAlignedSize.width); + EXPECT_FLOAT_EQ(350.0f, leftAlignedSize.height); } // Test the |BubbleMaxSize| method when the bubble is leading aligned, the @@ -90,8 +90,8 @@ centerAlignedAnchorPoint_, BubbleArrowDirectionDown, BubbleAlignmentLeading, containerSize_, false /* isRTL */); - EXPECT_TRUE(CGSizeEqualToSize({200.0f + kTestBubbleAlignmentOffset, 250.0f}, - centerAlignedSize)); + EXPECT_FLOAT_EQ(200.0f + kTestBubbleAlignmentOffset, centerAlignedSize.width); + EXPECT_FLOAT_EQ(250.0f, centerAlignedSize.height); } // Test the |BubbleMaxSize| method when the bubble is leading aligned, the @@ -102,8 +102,8 @@ rightAlignedAnchorPoint_, BubbleArrowDirectionUp, BubbleAlignmentLeading, containerSize_, false /* isRTL */); - EXPECT_TRUE(CGSizeEqualToSize({50.0f + kTestBubbleAlignmentOffset, 350.0f}, - rightAlignedSize)); + EXPECT_FLOAT_EQ(50.0f + kTestBubbleAlignmentOffset, rightAlignedSize.width); + EXPECT_FLOAT_EQ(350.0f, rightAlignedSize.height); } // Test the |BubbleMaxSize| method when the bubble is center aligned, the target @@ -114,7 +114,8 @@ leftAlignedAnchorPoint_, BubbleArrowDirectionDown, BubbleAlignmentCenter, containerSize_, false /* isRTL */); - EXPECT_TRUE(CGSizeEqualToSize({140.0f, 250.0f}, leftAlignedSize)); + EXPECT_FLOAT_EQ(140.0f, leftAlignedSize.width); + EXPECT_FLOAT_EQ(250.0f, leftAlignedSize.height); } // Test the |BubbleMaxSize| method when the bubble is center aligned, the target @@ -125,7 +126,8 @@ centerAlignedAnchorPoint_, BubbleArrowDirectionUp, BubbleAlignmentCenter, containerSize_, false /* isRTL */); - EXPECT_TRUE(CGSizeEqualToSize({400.0f, 350.0f}, centerAlignedSize)); + EXPECT_FLOAT_EQ(400.0f, centerAlignedSize.width); + EXPECT_FLOAT_EQ(350.0f, centerAlignedSize.height); } // Test the |BubbleMaxSize| method when the bubble is center aligned, the target @@ -136,7 +138,8 @@ rightAlignedAnchorPoint_, BubbleArrowDirectionDown, BubbleAlignmentCenter, containerSize_, false /* isRTL */); - EXPECT_TRUE(CGSizeEqualToSize({100.0f, 250.0f}, rightAlignedSize)); + EXPECT_FLOAT_EQ(100.0f, rightAlignedSize.width); + EXPECT_FLOAT_EQ(250.0f, rightAlignedSize.height); } // Test the |BubbleMaxSize| method when the bubble is trailing aligned, the @@ -147,8 +150,8 @@ leftAlignedAnchorPoint_, BubbleArrowDirectionUp, BubbleAlignmentTrailing, containerSize_, false /* isRTL */); - EXPECT_TRUE(CGSizeEqualToSize({70.0f + kTestBubbleAlignmentOffset, 350.0f}, - leftAlignedSize)); + EXPECT_FLOAT_EQ(70.0f + kTestBubbleAlignmentOffset, leftAlignedSize.width); + EXPECT_FLOAT_EQ(350.0f, leftAlignedSize.height); } // Test the |BubbleMaxSize| method when the bubble is trailing aligned, the @@ -159,8 +162,8 @@ centerAlignedAnchorPoint_, BubbleArrowDirectionDown, BubbleAlignmentTrailing, containerSize_, false /* isRTL */); - EXPECT_TRUE(CGSizeEqualToSize({300.0f + kTestBubbleAlignmentOffset, 250.0f}, - centerAlignedSize)); + EXPECT_FLOAT_EQ(300.0f + kTestBubbleAlignmentOffset, centerAlignedSize.width); + EXPECT_FLOAT_EQ(250.0f, centerAlignedSize.height); } // Test the |BubbleMaxSize| method when the bubble is trailing aligned, the @@ -171,8 +174,8 @@ rightAlignedAnchorPoint_, BubbleArrowDirectionUp, BubbleAlignmentTrailing, containerSize_, false /* isRTL */); - EXPECT_TRUE(CGSizeEqualToSize({450.0f + kTestBubbleAlignmentOffset, 350.0f}, - rightAlignedSize)); + EXPECT_FLOAT_EQ(450.0f + kTestBubbleAlignmentOffset, rightAlignedSize.width); + EXPECT_FLOAT_EQ(350.0f, rightAlignedSize.height); } // Test the |BubbleMaxSize| method when the bubble is leading aligned, the @@ -183,8 +186,8 @@ leftAlignedAnchorPoint_, BubbleArrowDirectionDown, BubbleAlignmentLeading, containerSize_, true /* isRTL */); - EXPECT_TRUE(CGSizeEqualToSize({70.0f + kTestBubbleAlignmentOffset, 250.0f}, - leftAlignedSizeRTL)); + EXPECT_FLOAT_EQ(70.0f + kTestBubbleAlignmentOffset, leftAlignedSizeRTL.width); + EXPECT_FLOAT_EQ(250.0f, leftAlignedSizeRTL.height); } // Test the |BubbleMaxSize| method when the bubble is leading aligned, the @@ -195,8 +198,9 @@ centerAlignedAnchorPoint_, BubbleArrowDirectionUp, BubbleAlignmentLeading, containerSize_, true /* isRTL */); - EXPECT_TRUE(CGSizeEqualToSize({300.0f + kTestBubbleAlignmentOffset, 350.0f}, - centerAlignedSizeRTL)); + EXPECT_FLOAT_EQ(300.0f + kTestBubbleAlignmentOffset, + centerAlignedSizeRTL.width); + EXPECT_FLOAT_EQ(350.0f, centerAlignedSizeRTL.height); } // Test the |BubbleMaxSize| method when the bubble is leading aligned, the @@ -207,8 +211,9 @@ rightAlignedAnchorPoint_, BubbleArrowDirectionDown, BubbleAlignmentLeading, containerSize_, true /* isRTL */); - EXPECT_TRUE(CGSizeEqualToSize({450.0f + kTestBubbleAlignmentOffset, 250.0f}, - rightAlignedSizeRTL)); + EXPECT_FLOAT_EQ(450.0f + kTestBubbleAlignmentOffset, + rightAlignedSizeRTL.width); + EXPECT_FLOAT_EQ(250.0f, rightAlignedSizeRTL.height); } // Test the |BubbleMaxSize| method when the bubble is center aligned, the target @@ -219,7 +224,8 @@ leftAlignedAnchorPoint_, BubbleArrowDirectionUp, BubbleAlignmentCenter, containerSize_, true /* isRTL */); - EXPECT_TRUE(CGSizeEqualToSize({140.0f, 350.0f}, leftAlignedSizeRTL)); + EXPECT_FLOAT_EQ(140.0f, leftAlignedSizeRTL.width); + EXPECT_FLOAT_EQ(350.0f, leftAlignedSizeRTL.height); } // Test the |BubbleMaxSize| method when the bubble is center aligned, the target @@ -230,7 +236,8 @@ centerAlignedAnchorPoint_, BubbleArrowDirectionDown, BubbleAlignmentCenter, containerSize_, true /* isRTL */); - EXPECT_TRUE(CGSizeEqualToSize({400.0f, 250.0f}, centerAlignedSizeRTL)); + EXPECT_FLOAT_EQ(400.0f, centerAlignedSizeRTL.width); + EXPECT_FLOAT_EQ(250.0f, centerAlignedSizeRTL.height); } // Test the |BubbleMaxSize| method when the bubble is center aligned, the target @@ -241,7 +248,8 @@ rightAlignedAnchorPoint_, BubbleArrowDirectionUp, BubbleAlignmentCenter, containerSize_, true /* isRTL */); - EXPECT_TRUE(CGSizeEqualToSize({100.0f, 350.0f}, rightAlignedSizeRTL)); + EXPECT_FLOAT_EQ(100.0f, rightAlignedSizeRTL.width); + EXPECT_FLOAT_EQ(350.0f, rightAlignedSizeRTL.height); } // Test the |BubbleMaxSize| method when the bubble is trailing aligned, the @@ -252,8 +260,9 @@ leftAlignedAnchorPoint_, BubbleArrowDirectionDown, BubbleAlignmentTrailing, containerSize_, true /* isRTL */); - EXPECT_TRUE(CGSizeEqualToSize({430.0f + kTestBubbleAlignmentOffset, 250.0f}, - leftAlignedSizeRTL)); + EXPECT_FLOAT_EQ(430.0f + kTestBubbleAlignmentOffset, + leftAlignedSizeRTL.width); + EXPECT_FLOAT_EQ(250.0f, leftAlignedSizeRTL.height); } // Test the |BubbleMaxSize| method when the bubble is trailing aligned, the @@ -264,8 +273,9 @@ centerAlignedAnchorPoint_, BubbleArrowDirectionUp, BubbleAlignmentTrailing, containerSize_, true /* isRTL */); - EXPECT_TRUE(CGSizeEqualToSize({200.0f + kTestBubbleAlignmentOffset, 350.0f}, - centerAlignedSizeRTL)); + EXPECT_FLOAT_EQ(200.0f + kTestBubbleAlignmentOffset, + centerAlignedSizeRTL.width); + EXPECT_FLOAT_EQ(350.0f, centerAlignedSizeRTL.height); } // Test the |BubbleMaxSize| method when the bubble is trailing aligned, the @@ -276,8 +286,9 @@ rightAlignedAnchorPoint_, BubbleArrowDirectionDown, BubbleAlignmentTrailing, containerSize_, true /* isRTL */); - EXPECT_TRUE(CGSizeEqualToSize({50.0f + kTestBubbleAlignmentOffset, 250.0f}, - rightAlignedSizeRTL)); + EXPECT_FLOAT_EQ(50.0f + kTestBubbleAlignmentOffset, + rightAlignedSizeRTL.width); + EXPECT_FLOAT_EQ(250.0f, rightAlignedSizeRTL.height); } // Test |BubbleFrame| when the bubble's direction is @@ -287,9 +298,10 @@ CGRect bubbleFrame = bubble_util::BubbleFrame( centerAlignedAnchorPoint_, bubbleSize_, BubbleArrowDirectionUp, BubbleAlignmentLeading, containerSize_.width, false /* isRTL */); - EXPECT_EQ(300.0f - kTestBubbleAlignmentOffset, bubbleFrame.origin.x); - EXPECT_EQ(250.0f, bubbleFrame.origin.y); - EXPECT_TRUE(CGSizeEqualToSize(bubbleSize_, bubbleFrame.size)); + EXPECT_FLOAT_EQ(300.0f - kTestBubbleAlignmentOffset, bubbleFrame.origin.x); + EXPECT_FLOAT_EQ(250.0f, bubbleFrame.origin.y); + EXPECT_FLOAT_EQ(bubbleSize_.width, CGRectGetWidth(bubbleFrame)); + EXPECT_FLOAT_EQ(bubbleSize_.height, CGRectGetHeight(bubbleFrame)); } // Test |BubbleFrame| when the bubble's direction is @@ -299,9 +311,10 @@ CGRect bubbleFrame = bubble_util::BubbleFrame( centerAlignedAnchorPoint_, bubbleSize_, BubbleArrowDirectionUp, BubbleAlignmentLeading, containerSize_.width, true /* isRTL */); - EXPECT_EQ(-100.0f + kTestBubbleAlignmentOffset, bubbleFrame.origin.x); - EXPECT_EQ(250.0f, bubbleFrame.origin.y); - EXPECT_TRUE(CGSizeEqualToSize(bubbleSize_, bubbleFrame.size)); + EXPECT_FLOAT_EQ(-100.0f + kTestBubbleAlignmentOffset, bubbleFrame.origin.x); + EXPECT_FLOAT_EQ(250.0f, bubbleFrame.origin.y); + EXPECT_FLOAT_EQ(bubbleSize_.width, CGRectGetWidth(bubbleFrame)); + EXPECT_FLOAT_EQ(bubbleSize_.height, CGRectGetHeight(bubbleFrame)); } // Test |BubbleFrame| when the bubble's direction is @@ -311,9 +324,10 @@ CGRect bubbleFrame = bubble_util::BubbleFrame( centerAlignedAnchorPoint_, bubbleSize_, BubbleArrowDirectionUp, BubbleAlignmentCenter, containerSize_.width, false /* isRTL */); - EXPECT_EQ(150.0f, bubbleFrame.origin.x); - EXPECT_EQ(250.0f, bubbleFrame.origin.y); - EXPECT_TRUE(CGSizeEqualToSize(bubbleSize_, bubbleFrame.size)); + EXPECT_FLOAT_EQ(150.0f, bubbleFrame.origin.x); + EXPECT_FLOAT_EQ(250.0f, bubbleFrame.origin.y); + EXPECT_FLOAT_EQ(bubbleSize_.width, CGRectGetWidth(bubbleFrame)); + EXPECT_FLOAT_EQ(bubbleSize_.height, CGRectGetHeight(bubbleFrame)); } // Test |BubbleFrame| when the bubble's direction is @@ -323,9 +337,10 @@ CGRect bubbleFrame = bubble_util::BubbleFrame( centerAlignedAnchorPoint_, bubbleSize_, BubbleArrowDirectionUp, BubbleAlignmentCenter, containerSize_.width, true /* isRTL */); - EXPECT_EQ(50.0f, bubbleFrame.origin.x); - EXPECT_EQ(250.0f, bubbleFrame.origin.y); - EXPECT_TRUE(CGSizeEqualToSize(bubbleSize_, bubbleFrame.size)); + EXPECT_FLOAT_EQ(50.0f, bubbleFrame.origin.x); + EXPECT_FLOAT_EQ(250.0f, bubbleFrame.origin.y); + EXPECT_FLOAT_EQ(bubbleSize_.width, CGRectGetWidth(bubbleFrame)); + EXPECT_FLOAT_EQ(bubbleSize_.height, CGRectGetHeight(bubbleFrame)); } // Test |BubbleFrame| when the bubble's direction is @@ -335,9 +350,10 @@ CGRect bubbleFrame = bubble_util::BubbleFrame( centerAlignedAnchorPoint_, bubbleSize_, BubbleArrowDirectionUp, BubbleAlignmentTrailing, containerSize_.width, false /* isRTL */); - EXPECT_EQ(kTestBubbleAlignmentOffset, bubbleFrame.origin.x); - EXPECT_EQ(250.0f, bubbleFrame.origin.y); - EXPECT_TRUE(CGSizeEqualToSize(bubbleSize_, bubbleFrame.size)); + EXPECT_FLOAT_EQ(kTestBubbleAlignmentOffset, bubbleFrame.origin.x); + EXPECT_FLOAT_EQ(250.0f, bubbleFrame.origin.y); + EXPECT_FLOAT_EQ(bubbleSize_.width, CGRectGetWidth(bubbleFrame)); + EXPECT_FLOAT_EQ(bubbleSize_.height, CGRectGetHeight(bubbleFrame)); } // Test |BubbleFrame| when the bubble's direction is @@ -347,9 +363,10 @@ CGRect bubbleFrame = bubble_util::BubbleFrame( centerAlignedAnchorPoint_, bubbleSize_, BubbleArrowDirectionUp, BubbleAlignmentTrailing, containerSize_.width, true /* isRTL */); - EXPECT_EQ(200.0f - kTestBubbleAlignmentOffset, bubbleFrame.origin.x); - EXPECT_EQ(250.0f, bubbleFrame.origin.y); - EXPECT_TRUE(CGSizeEqualToSize(bubbleSize_, bubbleFrame.size)); + EXPECT_FLOAT_EQ(200.0f - kTestBubbleAlignmentOffset, bubbleFrame.origin.x); + EXPECT_FLOAT_EQ(250.0f, bubbleFrame.origin.y); + EXPECT_FLOAT_EQ(bubbleSize_.width, CGRectGetWidth(bubbleFrame)); + EXPECT_FLOAT_EQ(bubbleSize_.height, CGRectGetHeight(bubbleFrame)); } // Test |BubbleFrame| when the bubble's direction is @@ -359,9 +376,10 @@ CGRect bubbleFrame = bubble_util::BubbleFrame( centerAlignedAnchorPoint_, bubbleSize_, BubbleArrowDirectionDown, BubbleAlignmentLeading, containerSize_.width, false /* isRTL */); - EXPECT_EQ(300.0f - kTestBubbleAlignmentOffset, bubbleFrame.origin.x); - EXPECT_EQ(150.0f, bubbleFrame.origin.y); - EXPECT_TRUE(CGSizeEqualToSize(bubbleSize_, bubbleFrame.size)); + EXPECT_FLOAT_EQ(300.0f - kTestBubbleAlignmentOffset, bubbleFrame.origin.x); + EXPECT_FLOAT_EQ(150.0f, bubbleFrame.origin.y); + EXPECT_FLOAT_EQ(bubbleSize_.width, CGRectGetWidth(bubbleFrame)); + EXPECT_FLOAT_EQ(bubbleSize_.height, CGRectGetHeight(bubbleFrame)); } // Test |BubbleFrame| when the bubble's direction is @@ -371,9 +389,10 @@ CGRect bubbleFrame = bubble_util::BubbleFrame( centerAlignedAnchorPoint_, bubbleSize_, BubbleArrowDirectionDown, BubbleAlignmentLeading, containerSize_.width, true /* isRTL */); - EXPECT_EQ(-100.0f + kTestBubbleAlignmentOffset, bubbleFrame.origin.x); - EXPECT_EQ(150.0f, bubbleFrame.origin.y); - EXPECT_TRUE(CGSizeEqualToSize(bubbleSize_, bubbleFrame.size)); + EXPECT_FLOAT_EQ(-100.0f + kTestBubbleAlignmentOffset, bubbleFrame.origin.x); + EXPECT_FLOAT_EQ(150.0f, bubbleFrame.origin.y); + EXPECT_FLOAT_EQ(bubbleSize_.width, CGRectGetWidth(bubbleFrame)); + EXPECT_FLOAT_EQ(bubbleSize_.height, CGRectGetHeight(bubbleFrame)); } // Test |BubbleFrame| when the bubble's direction is @@ -383,9 +402,10 @@ CGRect bubbleFrame = bubble_util::BubbleFrame( centerAlignedAnchorPoint_, bubbleSize_, BubbleArrowDirectionDown, BubbleAlignmentCenter, containerSize_.width, false /* isRTL */); - EXPECT_EQ(150.0f, bubbleFrame.origin.x); - EXPECT_EQ(150.0f, bubbleFrame.origin.y); - EXPECT_TRUE(CGSizeEqualToSize(bubbleSize_, bubbleFrame.size)); + EXPECT_FLOAT_EQ(150.0f, bubbleFrame.origin.x); + EXPECT_FLOAT_EQ(150.0f, bubbleFrame.origin.y); + EXPECT_FLOAT_EQ(bubbleSize_.width, CGRectGetWidth(bubbleFrame)); + EXPECT_FLOAT_EQ(bubbleSize_.height, CGRectGetHeight(bubbleFrame)); } // Test |BubbleFrame| when the bubble's direction is @@ -395,9 +415,10 @@ CGRect bubbleFrame = bubble_util::BubbleFrame( centerAlignedAnchorPoint_, bubbleSize_, BubbleArrowDirectionDown, BubbleAlignmentCenter, containerSize_.width, true /* isRTL */); - EXPECT_EQ(50.0f, bubbleFrame.origin.x); - EXPECT_EQ(150.0f, bubbleFrame.origin.y); - EXPECT_TRUE(CGSizeEqualToSize(bubbleSize_, bubbleFrame.size)); + EXPECT_FLOAT_EQ(50.0f, bubbleFrame.origin.x); + EXPECT_FLOAT_EQ(150.0f, bubbleFrame.origin.y); + EXPECT_FLOAT_EQ(bubbleSize_.width, CGRectGetWidth(bubbleFrame)); + EXPECT_FLOAT_EQ(bubbleSize_.height, CGRectGetHeight(bubbleFrame)); } // Test |BubbleFrame| when the bubble's direction is @@ -407,9 +428,10 @@ CGRect bubbleFrame = bubble_util::BubbleFrame( centerAlignedAnchorPoint_, bubbleSize_, BubbleArrowDirectionDown, BubbleAlignmentTrailing, containerSize_.width, false /* isRTL */); - EXPECT_EQ(kTestBubbleAlignmentOffset, bubbleFrame.origin.x); - EXPECT_EQ(150.0f, bubbleFrame.origin.y); - EXPECT_TRUE(CGSizeEqualToSize(bubbleSize_, bubbleFrame.size)); + EXPECT_FLOAT_EQ(kTestBubbleAlignmentOffset, bubbleFrame.origin.x); + EXPECT_FLOAT_EQ(150.0f, bubbleFrame.origin.y); + EXPECT_FLOAT_EQ(bubbleSize_.width, CGRectGetWidth(bubbleFrame)); + EXPECT_FLOAT_EQ(bubbleSize_.height, CGRectGetHeight(bubbleFrame)); } // Test |BubbleFrame| when the bubble's direction is @@ -419,7 +441,8 @@ CGRect bubbleFrame = bubble_util::BubbleFrame( centerAlignedAnchorPoint_, bubbleSize_, BubbleArrowDirectionDown, BubbleAlignmentTrailing, containerSize_.width, true /* isRTL */); - EXPECT_EQ(200.0f - kTestBubbleAlignmentOffset, bubbleFrame.origin.x); - EXPECT_EQ(150.0f, bubbleFrame.origin.y); - EXPECT_TRUE(CGSizeEqualToSize(bubbleSize_, bubbleFrame.size)); + EXPECT_FLOAT_EQ(200.0f - kTestBubbleAlignmentOffset, bubbleFrame.origin.x); + EXPECT_FLOAT_EQ(150.0f, bubbleFrame.origin.y); + EXPECT_FLOAT_EQ(bubbleSize_.width, CGRectGetWidth(bubbleFrame)); + EXPECT_FLOAT_EQ(bubbleSize_.height, CGRectGetHeight(bubbleFrame)); }
diff --git a/ios/chrome/browser/ui/bubble/bubble_view.h b/ios/chrome/browser/ui/bubble/bubble_view.h index 1f83562a..16469e2 100644 --- a/ios/chrome/browser/ui/bubble/bubble_view.h +++ b/ios/chrome/browser/ui/bubble/bubble_view.h
@@ -20,17 +20,20 @@ BubbleArrowDirectionDown, }; -// Alignment of the bubble relative to the arrow. +// Alignment of the bubble's arrow relative to the rest of the bubble. typedef NS_ENUM(NSInteger, BubbleAlignment) { + // Arrow is aligned to the leading edge of the bubble. BubbleAlignmentLeading, + // Arrow is center aligned on the bubble. BubbleAlignmentCenter, + // Arrow is aligned to the trailing edge of the bubble. BubbleAlignmentTrailing, }; // Speech bubble shaped view that displays a message. @interface BubbleView : UIView -// Initializes with the given text, direction that the bubble should point, and +// Initialize with the given text, direction that the bubble should point, and // alignment of the bubble. - (instancetype)initWithText:(NSString*)text arrowDirection:(BubbleArrowDirection)direction
diff --git a/ios/chrome/browser/ui/bubble/bubble_view.mm b/ios/chrome/browser/ui/bubble/bubble_view.mm index b42bc45..5c4f211 100644 --- a/ios/chrome/browser/ui/bubble/bubble_view.mm +++ b/ios/chrome/browser/ui/bubble/bubble_view.mm
@@ -5,34 +5,333 @@ #import "ios/chrome/browser/ui/bubble/bubble_view.h" #include "base/logging.h" +#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" +#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif -const CGFloat kBubbleAlignmentOffset = 10.0f; +const CGFloat kBubbleAlignmentOffset = 40.0f; + +namespace { +// The color of the bubble (both circular background and arrow). +UIColor* BubbleColor() { + return [[MDCPalette cr_bluePalette] tint500]; +} +// The corner radius of the bubble's background, which causes the ends of the +// badge to be circular. +const CGFloat kBubbleCornerRadius = 18.0f; +// The minimum bubble width is two times the bubble alignment offset, which +// causes the bubble to appear center-aligned for short display text. +const CGFloat kMinBubbleWidth = kBubbleAlignmentOffset * 2; +// The maximum label width preserves readability, ensuring that long labels do +// not span across wide screens. +const CGFloat kMaxLabelWidth = 359.0f; +// Font size for the bubble's display text. +const CGFloat kFontSize = 16.0f; + +// Margin between the bubble view's bounds and its content. This margin is on +// all sides of the bubble. +const CGFloat kBubbleMargin = 8.0f; +// Padding between the top and bottom the bubble's background and the top and +// bottom of the label. +const CGFloat kLabelVerticalPadding = 8.0f; +// Padding between the sides of the bubble's background and the sides of the +// label. This has the same value as |kBubbleCornerRadius| to ensure that the +// label is positioned within the non-rounded portion of the bubble. +const CGFloat kLabelHorizontalPadding = kBubbleCornerRadius; + +// The size that the arrow will appear to have. +const CGSize kArrowSize = {14.0f, 10.0f}; +// The factor by which the arrow's size is scaled. Drawing the arrow larger than +// its desired size prevents gaps between the arrow and the background view. +const CGFloat kArrowScaleFactor = 1.5f; + +// The offset of the bubble's drop shadow, which will be slightly below the +// bubble. +const CGSize kShadowOffset = {0.0f, 2.0f}; +// The blur radius of the bubble's drop shadow. +const CGFloat kShadowRadius = 4.0f; +// The opacity of the bubble's drop shadow. +const CGFloat kShadowOpacity = 0.1f; +} // namespace @interface BubbleView () // Label containing the text displayed on the bubble. -@property(nonatomic, weak) UILabel* label; +@property(nonatomic, strong) UILabel* label; +// Pill-shaped view in the background of the bubble. +@property(nonatomic, strong, readonly) UIView* background; +// Triangular arrow that points to the target UI element. +@property(nonatomic, strong, readonly) UIView* arrow; +@property(nonatomic, assign, readonly) BubbleArrowDirection direction; +@property(nonatomic, assign, readonly) BubbleAlignment alignment; +// Indicate whether view properties need to be added as subviews of the bubble. +@property(nonatomic, assign) BOOL needsAddSubviews; @end @implementation BubbleView @synthesize label = _label; +@synthesize background = _background; +@synthesize arrow = _arrow; +@synthesize direction = _direction; +@synthesize alignment = _alignment; +@synthesize needsAddSubviews = _needsAddSubviews; - (instancetype)initWithText:(NSString*)text arrowDirection:(BubbleArrowDirection)direction alignment:(BubbleAlignment)alignment { self = [super initWithFrame:CGRectZero]; + if (self) { + _direction = direction; + _alignment = alignment; + _label = [BubbleView labelWithText:text]; + _needsAddSubviews = YES; + } return self; } +#pragma mark - Property accessors + +// Lazily load the background view. +- (UIView*)background { + // If the instance variable for the background has not been set up, load the + // background view and set the instance variable equal to the background view. + if (!_background) { + UIView* background = [[UIView alloc] initWithFrame:CGRectZero]; + [background setBackgroundColor:BubbleColor()]; + [background.layer setCornerRadius:kBubbleCornerRadius]; + [background setTranslatesAutoresizingMaskIntoConstraints:NO]; + _background = background; + } + return _background; +} + +// Lazily load the arrow view. +- (UIView*)arrow { + // If the instance variable for the arrow has not been set up, load the arrow + // and set the instance variable equal to the arrow. + if (!_arrow) { + // Draw the arrow slightly larger than the desired size in order to prevent + // gaps between the background view and the arrow. + CGFloat width = kArrowSize.width * kArrowScaleFactor; + CGFloat height = kArrowSize.height * kArrowScaleFactor; + UIView* arrow = + [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, width, height)]; + UIBezierPath* path = UIBezierPath.bezierPath; + if (self.direction == BubbleArrowDirectionUp) { + [path moveToPoint:CGPointMake(width / 2.0f, 0.0f)]; + [path addLineToPoint:CGPointMake(0.0f, height)]; + [path addLineToPoint:CGPointMake(width, height)]; + } else { + DCHECK(self.direction == BubbleArrowDirectionDown); + [path moveToPoint:CGPointMake(width / 2.0f, height)]; + [path addLineToPoint:CGPointMake(0.0f, 0.0f)]; + [path addLineToPoint:CGPointMake(width, 0.0f)]; + } + [path closePath]; + + CAShapeLayer* layer = [CAShapeLayer layer]; + [layer setPath:path.CGPath]; + [layer setFillColor:BubbleColor().CGColor]; + [arrow.layer addSublayer:layer]; + [arrow setTranslatesAutoresizingMaskIntoConstraints:NO]; + _arrow = arrow; + } + return _arrow; +} + +#pragma mark - Private class methods + +// Return a label to be used for a BubbleView that displays white text. ++ (UILabel*)labelWithText:(NSString*)text { + DCHECK(text.length); + UILabel* label = [[UILabel alloc] initWithFrame:CGRectZero]; + [label setText:text]; + [label setFont:[[MDCTypography fontLoader] regularFontOfSize:kFontSize]]; + [label setTextColor:[UIColor whiteColor]]; + [label setTextAlignment:NSTextAlignmentCenter]; + [label setNumberOfLines:0]; + [label setLineBreakMode:NSLineBreakByWordWrapping]; + [label setTranslatesAutoresizingMaskIntoConstraints:NO]; + return label; +} + +#pragma mark - Private instance methods + +// Add a drop shadow to the bubble. +- (void)addShadow { + [self.layer setShadowOffset:kShadowOffset]; + [self.layer setShadowRadius:kShadowRadius]; + [self.layer setShadowColor:[UIColor blackColor].CGColor]; + [self.layer setShadowOpacity:kShadowOpacity]; +} + +// Activate Autolayout constraints to properly position the bubble's subviews. +- (void)activateConstraints { + // Add constraints that do not depend on the bubble's direction or alignment. + NSMutableArray<NSLayoutConstraint*>* constraints = + [NSMutableArray arrayWithArray:[self generalConstraints]]; + // Add the constraint that aligns the arrow relative to the bubble. + [constraints addObject:[self arrowAlignmentConstraint]]; + // Add constraints that depend on the bubble's direction. + [constraints addObjectsFromArray:[self arrowDirectionConstraints]]; + [NSLayoutConstraint activateConstraints:constraints]; +} + +// Return an array of constraints that do not depend on the bubble's arrow +// direction or alignment. +- (NSArray<NSLayoutConstraint*>*)generalConstraints { + NSArray<NSLayoutConstraint*>* constraints = @[ + // Center the background view on the bubble view. + [self.background.centerXAnchor constraintEqualToAnchor:self.centerXAnchor], + // Ensure that the background view is less wide than the bubble view, and + // add a margin to the sides of the background. + [self.background.widthAnchor + constraintLessThanOrEqualToAnchor:self.widthAnchor + constant:kBubbleMargin * 2], + // Ensure that the background view is as wide as the label, with added + // padding on the sides of the label. + [self.background.widthAnchor + constraintEqualToAnchor:self.label.widthAnchor + constant:kLabelHorizontalPadding * 2], + // Enforce the minimum width of the background view. + [self.background.widthAnchor + constraintGreaterThanOrEqualToConstant:kMinBubbleWidth - + kBubbleMargin * 2], + // Ensure that the background view is as tall as the label, with added + // padding to the top and bottom of the label. + [self.background.heightAnchor + constraintEqualToAnchor:self.label.heightAnchor + constant:kLabelVerticalPadding * 2], + // Center the label on the background view. + [self.label.centerXAnchor + constraintEqualToAnchor:self.background.centerXAnchor], + [self.label.centerYAnchor + constraintEqualToAnchor:self.background.centerYAnchor], + // Enforce the arrow's size, scaling by |kArrowScaleFactor| to prevent gaps + // between the arrow and the background view. + [self.arrow.widthAnchor + constraintEqualToConstant:kArrowSize.width * kArrowScaleFactor], + [self.arrow.heightAnchor + constraintEqualToConstant:kArrowSize.height * kArrowScaleFactor] + + ]; + return constraints; +} + +// Return the constraint that aligns the arrow to the bubble view. This depends +// on the bubble's alignment. +- (NSLayoutConstraint*)arrowAlignmentConstraint { + // The anchor of the bubble which is aligned with the arrow's center anchor. + NSLayoutAnchor* anchor; + // The constant by which |anchor| is offset from the arrow's center anchor. + CGFloat offset; + switch (self.alignment) { + case BubbleAlignmentLeading: + // The anchor point is at a distance of |kBubbleAlignmentOffset| + // from the bubble's leading edge. Center align the arrow with the anchor + // point by aligning the center of the arrow with the leading edge of the + // bubble view and adding an offset of |kBubbleAlignmentOffset|. + anchor = self.leadingAnchor; + offset = kBubbleAlignmentOffset; + break; + case BubbleAlignmentCenter: + // Since the anchor point is in the center of the bubble view, center the + // arrow on the bubble view. + anchor = self.centerXAnchor; + offset = 0.0f; + break; + case BubbleAlignmentTrailing: + // The anchor point is at a distance of |kBubbleAlignmentOffset| + // from the bubble's trailing edge. Center align the arrow with the anchor + // point by aligning the center of the arrow with the trailing edge of the + // bubble view and adding an offset of |-kBubbleAlignmentOffset|. + anchor = self.trailingAnchor; + offset = -kBubbleAlignmentOffset; + break; + default: + NOTREACHED() << "Invalid bubble alignment " << self.alignment; + return nil; + } + return + [self.arrow.centerXAnchor constraintEqualToAnchor:anchor constant:offset]; +} + +// Return an array of constraints that depend on the bubble's arrow direction. +- (NSArray<NSLayoutConstraint*>*)arrowDirectionConstraints { + NSArray<NSLayoutConstraint*>* constraints; + if (self.direction == BubbleArrowDirectionUp) { + constraints = @[ + [self.background.topAnchor constraintEqualToAnchor:self.arrow.topAnchor + constant:kArrowSize.height], + // Ensure that the top of the arrow is aligned with the top of the bubble + // view and add a margin above the arrow. + [self.arrow.topAnchor constraintEqualToAnchor:self.topAnchor + constant:kBubbleMargin] + ]; + } else { + DCHECK(self.direction == BubbleArrowDirectionDown); + constraints = @[ + [self.arrow.bottomAnchor + constraintEqualToAnchor:self.background.bottomAnchor + constant:kArrowSize.height], + // Ensure that the bottom of the arrow is aligned with the bottom of the + // bubble view and add a margin below the arrow. + [self.bottomAnchor constraintEqualToAnchor:self.arrow.bottomAnchor + constant:kBubbleMargin] + ]; + } + return constraints; +} + #pragma mark - UIView overrides -// Override sizeThatFits to return the bubble's optimal size. +// Override |willMoveToSuperview| to add view properties to the view hierarchy. +- (void)willMoveToSuperview:(UIView*)newSuperview { + // If subviews have not been added to the view hierarchy, add them. + if (self.needsAddSubviews) { + [self addSubview:self.arrow]; + [self addSubview:self.background]; + [self addSubview:self.label]; + // Set |needsAddSubviews| to NO to ensure that the subviews are only added + // to the view hierarchy once. + self.needsAddSubviews = NO; + // Perform additional setup and layout operations, such as activating + // constraints, adding the drop shadow, and setting the accessibility label. + [self activateConstraints]; + [self addShadow]; + [self setAccessibilityLabel:self.label.text]; + } + [super willMoveToSuperview:newSuperview]; +} + +// Override |sizeThatFits| to return the bubble's optimal size. Calculate +// optimal size by finding the label's optimal size, and adding inset distances +// to the label's dimensions. This method also enforces minimum bubble width to +// prevent strange, undesired behaviors, and maximum label width to preserve +// readability. - (CGSize)sizeThatFits:(CGSize)size { - NOTIMPLEMENTED(); - return size; + // The combined horizontal inset distance of the label with respect to the + // bubble. + CGFloat labelHorizontalInset = (kBubbleMargin + kLabelHorizontalPadding) * 2; + // The combined vertical inset distance of the label with respect to the + // bubble. + CGFloat labelVerticalInset = + (kBubbleMargin + kLabelVerticalPadding) * 2 + kArrowSize.height; + // Calculate the maximum width the label is allowed to use, and ensure that + // the label does not exceed the maximum line width. + CGFloat labelMaxWidth = + MIN(size.width - labelHorizontalInset, kMaxLabelWidth); + CGSize labelMaxSize = + CGSizeMake(labelMaxWidth, size.height - labelVerticalInset); + CGSize labelSize = [self.label sizeThatFits:labelMaxSize]; + // Ensure that the bubble is at least as wide as the minimum bubble width. + CGFloat optimalWidth = + MAX(labelSize.width + labelHorizontalInset, kMinBubbleWidth); + CGSize optimalSize = + CGSizeMake(optimalWidth, labelSize.height + labelVerticalInset); + return optimalSize; } @end
diff --git a/ios/chrome/browser/ui/bubble/bubble_view_controller.h b/ios/chrome/browser/ui/bubble/bubble_view_controller.h index dd574fe..7711487 100644 --- a/ios/chrome/browser/ui/bubble/bubble_view_controller.h +++ b/ios/chrome/browser/ui/bubble/bubble_view_controller.h
@@ -11,7 +11,7 @@ // interest. @interface BubbleViewController : UIViewController -// Initializes the bubble with the given text, arrow direction, and alignment. +// Initialize the bubble with the given text, arrow direction, and alignment. - (instancetype)initWithText:(NSString*)text arrowDirection:(BubbleArrowDirection)direction alignment:(BubbleAlignment)alignment @@ -24,10 +24,10 @@ - (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; -// Animates the bubble in with a fade-in. +// Animate the bubble view in with a fade-in and sink-down animation. - (void)animateContentIn; -// Dismisses the bubble. If |animated| is true, the bubble fades out. +// Dismiss the bubble. If |animated| is true, the bubble fades out. - (void)dismissAnimated:(BOOL)animated; @end
diff --git a/ios/chrome/browser/ui/bubble/bubble_view_controller.mm b/ios/chrome/browser/ui/bubble/bubble_view_controller.mm index 38a448f5..e728ef35 100644 --- a/ios/chrome/browser/ui/bubble/bubble_view_controller.mm +++ b/ios/chrome/browser/ui/bubble/bubble_view_controller.mm
@@ -5,19 +5,26 @@ #import "ios/chrome/browser/ui/bubble/bubble_view_controller.h" #include "base/logging.h" +#include "ios/chrome/browser/ui/animation_util.h" +#import "ios/chrome/common/material_timing.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif +namespace { +const CGFloat kAnimationDuration = ios::material::kDuration3; +// The vertical offset distance used in the sink-down animation. +const CGFloat kVerticalOffset = 8.0f; +} // namespace + @interface BubbleViewController () -@property(nonatomic, readonly) NSString* text; -@property(nonatomic, readonly) BubbleArrowDirection arrowDirection; -@property(nonatomic, readonly) BubbleAlignment alignment; +@property(nonatomic, copy, readonly) NSString* text; +@property(nonatomic, assign, readonly) BubbleArrowDirection arrowDirection; +@property(nonatomic, assign, readonly) BubbleAlignment alignment; @end @implementation BubbleViewController - @synthesize text = _text; @synthesize arrowDirection = _arrowDirection; @synthesize alignment = _alignment; @@ -26,9 +33,11 @@ arrowDirection:(BubbleArrowDirection)direction alignment:(BubbleAlignment)alignment { self = [super initWithNibName:nil bundle:nil]; - _text = text; - _arrowDirection = direction; - _alignment = alignment; + if (self) { + _text = text; + _arrowDirection = direction; + _alignment = alignment; + } return self; } @@ -36,14 +45,44 @@ self.view = [[BubbleView alloc] initWithText:self.text arrowDirection:self.arrowDirection alignment:self.alignment]; + // Begin hidden. + [self.view setAlpha:0.0f]; + [self.view setHidden:YES]; } +// Animate the bubble view in with a fade-in and sink-down animation. - (void)animateContentIn { - NOTIMPLEMENTED(); + // Set the frame's origin to be slightly higher on the screen, so that the + // view will be properly positioned once it sinks down. + CGRect frame = self.view.frame; + frame.origin.y = frame.origin.y - kVerticalOffset; + [self.view setFrame:frame]; + [self.view setHidden:NO]; + + // Set the y-coordinate of |frame.origin| to its final value. + frame.origin.y = frame.origin.y + kVerticalOffset; + [UIView animateWithDuration:kAnimationDuration + delay:0.0 + options:UIViewAnimationOptionCurveEaseOut + animations:^{ + [self.view setFrame:frame]; + [self.view setAlpha:1.0f]; + } + completion:nil]; } - (void)dismissAnimated:(BOOL)animated { - NOTIMPLEMENTED(); + NSTimeInterval duration = (animated ? kAnimationDuration : 0.0); + [UIView animateWithDuration:duration + animations:^{ + [self.view setAlpha:0.0f]; + } + completion:^(BOOL finished) { + [self.view setHidden:YES]; + [self willMoveToParentViewController:nil]; + [self.view removeFromSuperview]; + [self removeFromParentViewController]; + }]; } @end
diff --git a/ios/chrome/browser/ui/bubble/bubble_view_controller_unittest.mm b/ios/chrome/browser/ui/bubble/bubble_view_controller_unittest.mm deleted file mode 100644 index f5dc9f9..0000000 --- a/ios/chrome/browser/ui/bubble/bubble_view_controller_unittest.mm +++ /dev/null
@@ -1,30 +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. - -#import "ios/chrome/browser/ui/bubble/bubble_view_controller.h" - -#include "base/logging.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/platform_test.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -// Fixture to test BubbleViewController. -class BubbleViewControllerTest : public PlatformTest {}; - -// Tests the bubble's intrinsic content size given short text. -TEST_F(BubbleViewControllerTest, BubbleSizeShortText) {} - -// Tests that the bubble accommodates text that exceeds the maximum bubble width -// by displaying the text on multiple lines. -TEST_F(BubbleViewControllerTest, BubbleSizeMultipleLineText) {} - -// Tests that the bubble attaches to the UI element when the layout is flipped -// for RTL languages. -TEST_F(BubbleViewControllerTest, RTL) {} - -// Tests that the accessibility label matches the display text. -TEST_F(BubbleViewControllerTest, Accessibility) {}
diff --git a/ios/chrome/browser/ui/bubble/bubble_view_unittest.mm b/ios/chrome/browser/ui/bubble/bubble_view_unittest.mm new file mode 100644 index 0000000..c9c64d71 --- /dev/null +++ b/ios/chrome/browser/ui/bubble/bubble_view_unittest.mm
@@ -0,0 +1,73 @@ +// 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. + +#import "ios/chrome/browser/ui/bubble/bubble_view.h" + +#include "base/logging.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gtest_mac.h" +#include "testing/platform_test.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +// Fixture to test BubbleView. +class BubbleViewTest : public PlatformTest { + public: + BubbleViewTest() + : maxSize_(CGSizeMake(500.0f, 500.0f)), + arrowDirection_(BubbleArrowDirectionUp), + alignment_(BubbleAlignmentCenter), + shortText_(@"I"), + longText_(@"Lorem ipsum dolor sit amet, consectetur adipiscing elit.") { + } + + protected: + // The maximum size of the bubble. + const CGSize maxSize_; + // The direction that the bubble's arrow points. + const BubbleArrowDirection arrowDirection_; + // The alignment of the bubble's arrow relative to the rest of the bubble. + const BubbleAlignment alignment_; + // Text that is shorter than the minimum line width. + NSString* shortText_; + // Text that is longer than the maximum line width. It should wrap onto + // multiple lines. + NSString* longText_; +}; + +// Test |sizeThatFits| given short text. +TEST_F(BubbleViewTest, BubbleSizeShortText) { + BubbleView* bubble = [[BubbleView alloc] initWithText:shortText_ + arrowDirection:arrowDirection_ + alignment:alignment_]; + CGSize bubbleSize = [bubble sizeThatFits:maxSize_]; + // Since the label is shorter than the minimum line width, expect the bubble + // to be the minimum width and accommodate one line of text. + EXPECT_NEAR(80.0f, bubbleSize.width, 1.0f); + EXPECT_NEAR(61.5f, bubbleSize.height, 1.0f); +} + +// Test |sizeThatFits| given text that should wrap onto multiple lines. +TEST_F(BubbleViewTest, BubbleSizeMultipleLineText) { + BubbleView* bubble = [[BubbleView alloc] initWithText:longText_ + arrowDirection:arrowDirection_ + alignment:alignment_]; + CGSize bubbleSize = [bubble sizeThatFits:maxSize_]; + // The bubble should fit the label, which contains two lines of text. + EXPECT_NEAR(349.0f, bubbleSize.width, 1.0f); + EXPECT_NEAR(80.5f, bubbleSize.height, 1.0f); +} + +// Test that the accessibility label matches the display text. +TEST_F(BubbleViewTest, Accessibility) { + BubbleView* bubble = [[BubbleView alloc] initWithText:longText_ + arrowDirection:arrowDirection_ + alignment:alignment_]; + UIView* superview = [[UIView alloc] initWithFrame:CGRectZero]; + // Add the bubble view to the view hierarchy. + [superview addSubview:bubble]; + EXPECT_NSEQ(longText_, bubble.accessibilityLabel); +}
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn index 2db0370..beb7a8c 100644 --- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn +++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -96,7 +96,9 @@ "//base/test:test_support", "//components/keyed_service/ios", "//components/ntp_snippets", + "//components/ntp_snippets:test_support", "//components/reading_list/core", + "//components/strings", "//ios/chrome/app/strings", "//ios/chrome/browser", "//ios/chrome/browser/browser_state", @@ -110,6 +112,7 @@ "//ios/testing/earl_grey:earl_grey_support", "//ios/third_party/earl_grey", "//ios/web/public/test/http_server", + "//testing/gmock", "//ui/strings", ] libs = [
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm index c89384b..528d263 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm
@@ -5,11 +5,19 @@ #import <EarlGrey/EarlGrey.h> #import <XCTest/XCTest.h> +#include <vector> + +#include "base/mac/foundation_util.h" +#include "base/memory/ptr_util.h" +#include "base/strings/utf_string_conversions.h" #include "base/test/scoped_command_line.h" #include "components/keyed_service/ios/browser_state_keyed_service_factory.h" +#include "components/ntp_snippets/content_suggestion.h" #include "components/ntp_snippets/content_suggestions_service.h" +#include "components/ntp_snippets/mock_content_suggestions_provider.h" #include "components/reading_list/core/reading_list_entry.h" #include "components/reading_list/core/reading_list_model.h" +#include "components/strings/grit/components_strings.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/chrome_switches.h" #include "ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.h" @@ -28,14 +36,28 @@ #import "ios/chrome/test/earl_grey/chrome_test_case.h" #import "ios/web/public/test/http_server/http_server.h" #include "ios/web/public/test/http_server/http_server_util.h" +#include "testing/gmock/include/gmock/gmock.h" #include "ui/strings/grit/ui_strings.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif +using namespace ntp_snippets; + namespace { +// Returns a suggestion created from the |category|, |suggestion_id| and the +// |url|. +ContentSuggestion Suggestion(Category category, + std::string suggestion_id, + GURL url) { + ContentSuggestion suggestion(category, suggestion_id, url); + suggestion.set_title(base::UTF8ToUTF16(url.spec())); + + return suggestion; +} + // Select the cell with the |matcher| by scrolling the collection. // 150 is a reasonable scroll displacement that works for all UI elements, while // not being too slow. @@ -48,8 +70,53 @@ [ContentSuggestionsViewController collectionAccessibilityIdentifier])]; } + +} // namespace + +// Singleton allowing to register the provider in the +setup and still access it +// from inside the tests. +@interface ContentSuggestionsTestSingleton : NSObject + +// Shared instance of this singleton. ++ (instancetype)sharedInstance; + +// Returns the provider registered. +- (MockContentSuggestionsProvider*)provider; +// Registers a provider in the |service|. +- (void)registerArticleProvider:(ContentSuggestionsService*)service; + +@end + +@implementation ContentSuggestionsTestSingleton { + MockContentSuggestionsProvider* _provider; } ++ (instancetype)sharedInstance { + static ContentSuggestionsTestSingleton* sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[self alloc] init]; + }); + return sharedInstance; +} + +- (MockContentSuggestionsProvider*)provider { + return _provider; +} + +- (void)registerArticleProvider:(ContentSuggestionsService*)service { + Category articles = Category::FromKnownCategory(KnownCategories::ARTICLES); + std::unique_ptr<MockContentSuggestionsProvider> provider = + base::MakeUnique<MockContentSuggestionsProvider>( + service, std::vector<Category>{articles}); + _provider = provider.get(); + service->RegisterProvider(std::move(provider)); +} + +@end + +#pragma mark - TestCase + // Test case for the ContentSuggestion UI. @interface ContentSuggestionsTestCase : ChromeTestCase { base::test::ScopedCommandLine _scopedCommandLine; @@ -57,6 +124,10 @@ // Current non-incognito browser state. @property(nonatomic, assign, readonly) ios::ChromeBrowserState* browserState; +// Mock provider from the singleton. +@property(nonatomic, assign, readonly) MockContentSuggestionsProvider* provider; +// Article category, used by the singleton. +@property(nonatomic, assign, readonly) Category category; @end @@ -74,12 +145,14 @@ // service with no provider registered, allowing to register fake providers // which do not require internet connection. The previous service is deleted. IOSChromeContentSuggestionsServiceFactory::GetInstance()->SetTestingFactory( - browserState, ntp_snippets::CreateChromeContentSuggestionsService); + browserState, CreateChromeContentSuggestionsService); - ntp_snippets::RegisterReadingListProvider( + ContentSuggestionsService* service = IOSChromeContentSuggestionsServiceFactory::GetForBrowserState( - browserState), - browserState); + browserState); + RegisterReadingListProvider(service, browserState); + [[ContentSuggestionsTestSingleton sharedInstance] + registerArticleProvider:service]; } + (void)tearDown { @@ -91,18 +164,17 @@ // Resets the Service associated with this browserState to a service with // default providers. The previous service is deleted. IOSChromeContentSuggestionsServiceFactory::GetInstance()->SetTestingFactory( - browserState, - ntp_snippets::CreateChromeContentSuggestionsServiceWithProviders); + browserState, CreateChromeContentSuggestionsServiceWithProviders); [super tearDown]; } -#pragma mark - Tests - - (void)setUp { // The command line is set up before [super setUp] in order to have the NTP // opened with the command line already setup. base::CommandLine* commandLine = _scopedCommandLine.GetProcessCommandLine(); commandLine->AppendSwitch(switches::kEnableSuggestionsUI); + self.provider->FireCategoryStatusChanged(self.category, + CategoryStatus::AVAILABLE); ReadingListModel* readingListModel = ReadingListModelFactory::GetForBrowserState(self.browserState); @@ -110,6 +182,48 @@ [super setUp]; } +- (void)tearDown { + self.provider->FireCategoryStatusChanged( + self.category, CategoryStatus::ALL_SUGGESTIONS_EXPLICITLY_DISABLED); + [super tearDown]; +} + +#pragma mark - Tests + +// Tests that a switch for the ContentSuggestions exists in the settings. The +// behavior depends on having a real remote provider, so it cannot be tested +// here. +- (void)testPrivacySwitch { + [ChromeEarlGreyUI openSettingsMenu]; + [ChromeEarlGreyUI + tapSettingsMenuButton:chrome_test_util::SettingsMenuPrivacyButton()]; + [[EarlGrey selectElementWithMatcher: + chrome_test_util::StaticTextWithAccessibilityLabelId( + IDS_IOS_OPTIONS_CONTENT_SUGGESTIONS)] + assertWithMatcher:grey_sufficientlyVisible()]; +} + +// Tests that the section titles are displayed only if there are two sections. +- (void)testSectionTitle { + ReadingListModel* readingListModel = + ReadingListModelFactory::GetForBrowserState(self.browserState); + readingListModel->AddEntry(GURL("http://chromium.org"), "test title", + reading_list::ADDED_VIA_CURRENT_APP); + + [CellWithMatcher(chrome_test_util::StaticTextWithAccessibilityLabelId( + IDS_NTP_READING_LIST_SUGGESTIONS_SECTION_HEADER)) + assertWithMatcher:grey_nil()]; + + std::vector<ContentSuggestion> suggestions; + suggestions.emplace_back( + Suggestion(self.category, "chromium", GURL("http://chromium.org"))); + self.provider->FireSuggestionsChanged(self.category, std::move(suggestions)); + + [CellWithMatcher(chrome_test_util::StaticTextWithAccessibilityLabelId( + IDS_NTP_READING_LIST_SUGGESTIONS_SECTION_HEADER)) + assertWithMatcher:grey_sufficientlyVisible()]; +} + // Tests that the "Learn More" cell is present. - (void)testLearnMore { [CellWithMatcher(grey_accessibilityID( @@ -204,4 +318,12 @@ return chrome_test_util::GetOriginalBrowserState(); } +- (MockContentSuggestionsProvider*)provider { + return [[ContentSuggestionsTestSingleton sharedInstance] provider]; +} + +- (Category)category { + return Category::FromKnownCategory(KnownCategories::ARTICLES); +} + @end
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm index 236111f4..a687ca5 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -295,6 +295,8 @@ insetForSectionAtIndex:section]; if ([self.collectionUpdater isHeaderSection:section]) { parentInset.top = 0; + parentInset.left = 0; + parentInset.right = 0; } else if ([self.collectionUpdater isMostVisitedSection:section] || [self.collectionUpdater isPromoSection:section]) { CGFloat margin = content_suggestions::centeredTilesMarginForWidth(
diff --git a/ios/chrome/browser/ui/ntp/google_landing_view_controller.mm b/ios/chrome/browser/ui/ntp/google_landing_view_controller.mm index cfba1bd..5cad30b 100644 --- a/ios/chrome/browser/ui/ntp/google_landing_view_controller.mm +++ b/ios/chrome/browser/ui/ntp/google_landing_view_controller.mm
@@ -303,6 +303,7 @@ self.leftMargin = content_suggestions::centeredTilesMarginForWidth([self viewWidth]); [self updateConstraintsForWidth:[self viewWidth]]; + [self updateSearchField]; // Invalidate layout to handle the cases where the layout is changed when the // NTP is not presented (e.g. tab backgrounded). [[_mostVisitedView collectionViewLayout] invalidateLayout];
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm b/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm index d7445ad8..1d912e4 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm
@@ -142,6 +142,9 @@ percent = MIN(1, MAX(0, animatingOffset / ntp_header::kAnimationDistance)); } + if (self.bounds.size.height == 0) + return; + CGFloat searchFieldNormalWidth = content_suggestions::searchFieldWidth(self.bounds.size.width);
diff --git a/ios/chrome/browser/web/visible_url_egtest.mm b/ios/chrome/browser/web/visible_url_egtest.mm index 9ea73b5..b44c9568 100644 --- a/ios/chrome/browser/web/visible_url_egtest.mm +++ b/ios/chrome/browser/web/visible_url_egtest.mm
@@ -43,21 +43,17 @@ const char kPage2Link[] = "page-2"; const char kPage3Link[] = "page-3"; -// Purges all cached web view pages, so the next time back navigation will not -// use cached page. Browsers don't have to use fresh version for back forward +// Purges cached web view page, so the next time back navigation will not use +// cached page. Browsers don't have to use fresh version for back forward // navigation for HTTP pages and may serve version from the cache even if // Cache-Control response header says otherwise. void PurgeCachedWebViewPages() { - chrome_test_util::ResetAllWebViews(); - - BOOL reloaded = [[GREYCondition - conditionWithName:@"Wait for reload" - block:^{ - return chrome_test_util::GetCurrentWebState()->IsLoading() - ? NO - : YES; - }] waitWithTimeout:10]; - GREYAssert(reloaded, @"page did not reload"); + chrome_test_util::GetCurrentWebState()->SetWebUsageEnabled(false); + chrome_test_util::GetCurrentWebState()->SetWebUsageEnabled(true); + // TODO(crbug.com/705819): Reload will not happen after purging web view, + // unless WebState::GetView is called. + chrome_test_util::GetCurrentWebState()->GetView(); + [ChromeEarlGrey reload]; } // Response provider which can be paused. When it is paused it buffers all
diff --git a/ios/chrome/common/app_group/OWNERS b/ios/chrome/common/app_group/OWNERS new file mode 100644 index 0000000..ff84a83 --- /dev/null +++ b/ios/chrome/common/app_group/OWNERS
@@ -0,0 +1,2 @@ +lod@chromium.org +olivierrobin@chromium.org
diff --git a/ios/chrome/search_widget_extension/BUILD.gn b/ios/chrome/search_widget_extension/BUILD.gn index ee32aebc..f81491b3 100644 --- a/ios/chrome/search_widget_extension/BUILD.gn +++ b/ios/chrome/search_widget_extension/BUILD.gn
@@ -59,6 +59,7 @@ deps = [ "//base", "//components/open_from_clipboard:open_from_clipboard_impl", + "//ios/chrome/browser/ui/util:constraints_ui", "//ios/chrome/common/app_group", ]
diff --git a/ios/chrome/search_widget_extension/DEPS b/ios/chrome/search_widget_extension/DEPS index 5349816..2547b11 100644 --- a/ios/chrome/search_widget_extension/DEPS +++ b/ios/chrome/search_widget_extension/DEPS
@@ -1,4 +1,5 @@ include_rules = [ "+components/open_from_clipboard", + "+ios/chrome/browser/ui/util", "-url", ]
diff --git a/ios/chrome/search_widget_extension/search_widget_view_controller.mm b/ios/chrome/search_widget_extension/search_widget_view_controller.mm index 311ea6c..870c86b 100644 --- a/ios/chrome/search_widget_extension/search_widget_view_controller.mm +++ b/ios/chrome/search_widget_extension/search_widget_view_controller.mm
@@ -10,10 +10,10 @@ #include "base/mac/foundation_util.h" #include "base/strings/sys_string_conversions.h" #include "components/open_from_clipboard/clipboard_recent_content_impl_ios.h" +#import "ios/chrome/browser/ui/util/constraints_ui_util.h" #include "ios/chrome/common/app_group/app_group_constants.h" #import "ios/chrome/search_widget_extension/copied_url_view.h" #import "ios/chrome/search_widget_extension/search_widget_view.h" -#import "ios/chrome/search_widget_extension/ui_util.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -73,7 +73,7 @@ UIVibrancyEffect* primary; UIVibrancyEffect* secondary; CGFloat height = - self.extensionContext + self.extensionContext && base::ios::IsRunningOnIOS10OrLater() ? [self.extensionContext widgetMaximumSizeForDisplayMode:NCWidgetDisplayModeCompact] .height @@ -93,21 +93,25 @@ primaryVibrancyEffect:primary secondaryVibrancyEffect:secondary compactHeight:height - initiallyCompact:([self.extensionContext + initiallyCompact:(base::ios::IsRunningOnIOS10OrLater() && + [self.extensionContext widgetActiveDisplayMode] == - NCWidgetDisplayModeCompact)]; + NCWidgetDisplayModeCompact)]; self.widgetView = widgetView; [self.view addSubview:self.widgetView]; if (base::ios::IsRunningOnIOS10OrLater()) { self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded; + } else { + self.preferredContentSize = + CGSizeMake([[UIScreen mainScreen] bounds].size.width, + [self.widgetView widgetHeight]); } self.widgetView.translatesAutoresizingMaskIntoConstraints = NO; - [NSLayoutConstraint activateConstraints:ui_util::CreateSameConstraints( - self.view, self.widgetView)]; + AddSameConstraints(self.view, self.widgetView); } - (void)viewWillAppear:(BOOL)animated { @@ -137,8 +141,9 @@ (id<UIViewControllerTransitionCoordinator>)coordinator { [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; - BOOL isCompact = [self.extensionContext widgetActiveDisplayMode] == - NCWidgetDisplayModeCompact; + BOOL isCompact = base::ios::IsRunningOnIOS10OrLater() && + [self.extensionContext widgetActiveDisplayMode] == + NCWidgetDisplayModeCompact; [coordinator animateAlongsideTransition:^( @@ -172,7 +177,7 @@ } #endif -#pragma mark - WidgetViewActionTarget +#pragma mark - SearchWidgetViewActionTarget - (void)openSearch:(id)sender { [self openAppWithCommand:base::SysUTF8ToNSString( @@ -209,8 +214,7 @@ } - (void)openAppWithCommand:(NSString*)command parameter:(NSString*)parameter { - NSUserDefaults* sharedDefaults = - [[NSUserDefaults alloc] initWithSuiteName:app_group::ApplicationGroup()]; + NSUserDefaults* sharedDefaults = app_group::GetGroupUserDefaults(); NSString* defaultsKey = base::SysUTF8ToNSString(app_group::kChromeAppGroupCommandPreference); [sharedDefaults
diff --git a/ios/chrome/test/app/chrome_test_util.h b/ios/chrome/test/app/chrome_test_util.h index ebaeca4..99d1d7f 100644 --- a/ios/chrome/test/app/chrome_test_util.h +++ b/ios/chrome/test/app/chrome_test_util.h
@@ -58,9 +58,6 @@ // Dismisses all presented views and modal dialogs. void ClearPresentedState(); -// Purges and recreates all web views. -void ResetAllWebViews(); - // Sets the value of a boolean local state pref. // TODO(crbug.com/647022): Clean up other tests that use this helper function. void SetBooleanLocalStatePref(const char* pref_name, bool value);
diff --git a/ios/chrome/test/app/chrome_test_util.mm b/ios/chrome/test/app/chrome_test_util.mm index ae040f0..a72f7d7 100644 --- a/ios/chrome/test/app/chrome_test_util.mm +++ b/ios/chrome/test/app/chrome_test_util.mm
@@ -168,13 +168,6 @@ [GetMainController() dismissModalDialogsWithCompletion:nil]; } -void ResetAllWebViews() { - id<BrowserViewInformation> browser_view_info = - [GetMainController() browserViewInformation]; - [[browser_view_info mainTabModel] resetAllWebViews]; - [[browser_view_info otrTabModel] resetAllWebViews]; -} - void SetBooleanLocalStatePref(const char* pref_name, bool value) { DCHECK(GetApplicationContext()); DCHECK(GetApplicationContext()->GetLocalState());
diff --git a/ios/clean/chrome/browser/DEPS b/ios/clean/chrome/browser/DEPS new file mode 100644 index 0000000..dd1a3b6d --- /dev/null +++ b/ios/clean/chrome/browser/DEPS
@@ -0,0 +1,5 @@ +include_rules = [ + "+components/ntp_snippets", + "+components/ntp_tiles", + "+components/reading_list", +]
diff --git a/ios/clean/chrome/browser/ui/ntp/BUILD.gn b/ios/clean/chrome/browser/ui/ntp/BUILD.gn index 1f11d55..bc5d838 100644 --- a/ios/clean/chrome/browser/ui/ntp/BUILD.gn +++ b/ios/clean/chrome/browser/ui/ntp/BUILD.gn
@@ -8,8 +8,8 @@ "ntp_coordinator.mm", "ntp_home_coordinator.h", "ntp_home_coordinator.mm", - "ntp_home_mediator.h", - "ntp_home_mediator.mm", + "ntp_home_header_view_controller.h", + "ntp_home_header_view_controller.mm", "ntp_mediator.h", "ntp_mediator.mm", ] @@ -18,8 +18,21 @@ deps = [ ":ntp_ui", + "//components/ntp_snippets", + "//components/ntp_tiles", + "//components/reading_list/core", + "//components/strings", "//ios/chrome/app/strings:ios_strings_grit", + "//ios/chrome/browser/content_suggestions", + "//ios/chrome/browser/favicon", + "//ios/chrome/browser/ntp_snippets", + "//ios/chrome/browser/ntp_tiles", + "//ios/chrome/browser/reading_list", "//ios/chrome/browser/ui", + "//ios/chrome/browser/ui/alert_coordinator", + "//ios/chrome/browser/ui/content_suggestions", + "//ios/chrome/browser/ui/content_suggestions:content_suggestions_util", + "//ios/chrome/browser/ui/content_suggestions/cells", "//ios/chrome/browser/ui/ntp:ntp_controller", "//ios/chrome/browser/ui/ntp:ntp_internal", "//ios/chrome/browser/ui/toolbar", @@ -62,7 +75,7 @@ sources = [ "ntp_coordinator_unittest.mm", "ntp_home_coordinator_unittest.mm", - "ntp_home_mediator_unittest.mm", + "ntp_home_header_view_controller_unittest.mm", "ntp_mediator_unittest.mm", "ntp_view_controller_unittest.mm", ]
diff --git a/ios/clean/chrome/browser/ui/ntp/ntp_home_coordinator.mm b/ios/clean/chrome/browser/ui/ntp/ntp_home_coordinator.mm index 92484b3..482aca24 100644 --- a/ios/clean/chrome/browser/ui/ntp/ntp_home_coordinator.mm +++ b/ios/clean/chrome/browser/ui/ntp/ntp_home_coordinator.mm
@@ -4,57 +4,323 @@ #import "ios/clean/chrome/browser/ui/ntp/ntp_home_coordinator.h" +#include "base/mac/foundation_util.h" +#include "base/metrics/user_metrics.h" +#include "base/metrics/user_metrics_action.h" +#include "base/strings/sys_string_conversions.h" +#include "components/ntp_snippets/content_suggestions_service.h" +#include "components/ntp_tiles/most_visited_sites.h" +#include "components/reading_list/core/reading_list_model.h" +#include "components/strings/grit/components_strings.h" +#import "ios/chrome/browser/content_suggestions/content_suggestions_alert_factory.h" +#import "ios/chrome/browser/content_suggestions/content_suggestions_header_view_controller_delegate.h" +#import "ios/chrome/browser/content_suggestions/content_suggestions_mediator.h" +#include "ios/chrome/browser/favicon/ios_chrome_large_icon_cache_factory.h" +#include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" +#include "ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.h" +#include "ios/chrome/browser/ntp_tiles/ios_most_visited_sites_factory.h" +#include "ios/chrome/browser/reading_list/reading_list_model_factory.h" +#import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h" +#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_gesture_commands.h" +#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.h" +#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.h" +#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.h" +#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h" +#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.h" +#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h" +#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller_audience.h" +#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller_delegate.h" #import "ios/chrome/browser/ui/ntp/google_landing_mediator.h" #import "ios/chrome/browser/ui/ntp/google_landing_view_controller.h" -#import "ios/clean/chrome/browser/ui/ntp/ntp_home_mediator.h" +#import "ios/chrome/browser/ui/ntp/new_tab_page_header_constants.h" +#import "ios/chrome/browser/ui/ntp/notification_promo_whats_new.h" +#import "ios/chrome/browser/ui/uikit_ui_util.h" +#include "ios/chrome/grit/ios_strings.h" +#import "ios/clean/chrome/browser/ui/ntp/ntp_home_header_view_controller.h" #import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/shared/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h" +#import "ios/third_party/material_components_ios/src/components/Snackbar/src/MaterialSnackbar.h" +#include "ui/base/l10n/l10n_util.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif -@interface NTPHomeCoordinator () -@property(nonatomic, strong) NTPHomeMediator* mediator; +@interface NTPHomeCoordinator ()< + ContentSuggestionsCommands, + ContentSuggestionsGestureCommands, + ContentSuggestionsHeaderViewControllerCommandHandler, + ContentSuggestionsHeaderViewControllerDelegate, + ContentSuggestionsViewControllerAudience, + ContentSuggestionsViewControllerDelegate> + +@property(nonatomic, strong) AlertCoordinator* alertCoordinator; + @property(nonatomic, strong) GoogleLandingMediator* googleLandingMediator; -@property(nonatomic, strong) GoogleLandingViewController* viewController; +@property(nonatomic, strong) ContentSuggestionsMediator* suggestionsMediator; +@property(nonatomic, strong) NTPHomeHeaderViewController* headerViewController; +@property(nonatomic, strong) ContentSuggestionsViewController* viewController; +@property(nonatomic, strong) + ContentSuggestionsHeaderSynchronizer* headerCollectionInteractionHandler; + @end @implementation NTPHomeCoordinator -@synthesize mediator = _mediator; + +@synthesize alertCoordinator = _alertCoordinator; +@synthesize headerViewController = _headerViewController; @synthesize googleLandingMediator = _googleLandingMediator; @synthesize viewController = _viewController; +@synthesize suggestionsMediator = _suggestionsMediator; +@synthesize headerCollectionInteractionHandler = + _headerCollectionInteractionHandler; + +#pragma mark - BrowserCoordinator - (void)start { - // PLACEHOLDER: self.mediator and self.oldMediator should be merged together. - self.mediator = [[NTPHomeMediator alloc] init]; - self.mediator.dispatcher = static_cast<id>(self.browser->dispatcher()); + ntp_snippets::ContentSuggestionsService* contentSuggestionsService = + IOSChromeContentSuggestionsServiceFactory::GetForBrowserState( + self.browser->browser_state()); + contentSuggestionsService->remote_suggestions_scheduler() + ->OnSuggestionsSurfaceOpened(); - // PLACEHOLDER: These will go elsewhere. - [self.browser->dispatcher() startDispatchingToTarget:self.mediator - forProtocol:@protocol(UrlLoader)]; - [self.browser->dispatcher() - startDispatchingToTarget:self.mediator - forProtocol:@protocol(OmniboxFocuser)]; - self.viewController = [[GoogleLandingViewController alloc] init]; - self.viewController.dispatcher = static_cast<id>(self.browser->dispatcher()); + self.headerViewController = [[NTPHomeHeaderViewController alloc] init]; + self.headerViewController.delegate = self; + self.headerViewController.commandHandler = self; + self.googleLandingMediator = [[GoogleLandingMediator alloc] - initWithConsumer:self.viewController + initWithConsumer:self.headerViewController browserState:self.browser->browser_state() dispatcher:static_cast<id>(self.browser->dispatcher()) webStateList:&self.browser->web_state_list()]; - self.viewController.dataSource = self.googleLandingMediator; + + favicon::LargeIconService* largeIconService = + IOSChromeLargeIconServiceFactory::GetForBrowserState( + self.browser->browser_state()); + LargeIconCache* cache = IOSChromeLargeIconCacheFactory::GetForBrowserState( + self.browser->browser_state()); + std::unique_ptr<ntp_tiles::MostVisitedSites> mostVisitedFactory = + IOSMostVisitedSitesFactory::NewForBrowserState( + self.browser->browser_state()); + self.suggestionsMediator = [[ContentSuggestionsMediator alloc] + initWithContentService:contentSuggestionsService + largeIconService:largeIconService + largeIconCache:cache + mostVisitedSite:std::move(mostVisitedFactory)]; + self.suggestionsMediator.commandHandler = self; + self.suggestionsMediator.headerProvider = self.headerViewController; + + self.viewController = [[ContentSuggestionsViewController alloc] + initWithStyle:CollectionViewControllerStyleDefault + dataSource:self.suggestionsMediator]; + self.viewController.suggestionCommandHandler = self; + self.viewController.suggestionsDelegate = self; + self.viewController.audience = self; + + // TODO: Add the header viewController as child of the collection + // viewController. + + self.headerCollectionInteractionHandler = + [[ContentSuggestionsHeaderSynchronizer alloc] + initWithCollectionController:self.viewController + headerController:self.headerViewController]; + + self.viewController.headerCommandHandler = + self.headerCollectionInteractionHandler; + self.headerViewController.collectionSynchronizer = + self.headerCollectionInteractionHandler; + [super start]; } - (void)stop { [super stop]; [self.googleLandingMediator shutdown]; + self.viewController = nil; + self.suggestionsMediator = nil; + self.googleLandingMediator = nil; + self.headerViewController = nil; +} - [self.browser->dispatcher() stopDispatchingForProtocol:@protocol(UrlLoader)]; - [self.browser->dispatcher() - stopDispatchingForProtocol:@protocol(OmniboxFocuser)]; +#pragma mark - ContentSuggestionsCommands + +- (void)openReadingList { + // TODO: implement this. +} + +- (void)openPageForItem:(CollectionViewItem*)item { + // TODO: implement this. +} + +- (void)openMostVisitedItem:(CollectionViewItem*)item + atIndex:(NSInteger)mostVisitedIndex { + // TODO: implement this. +} + +- (void)displayContextMenuForSuggestion:(CollectionViewItem*)item + atPoint:(CGPoint)touchLocation + atIndexPath:(NSIndexPath*)indexPath + readLaterAction:(BOOL)readLaterAction { + ContentSuggestionsItem* suggestionsItem = + base::mac::ObjCCastStrict<ContentSuggestionsItem>(item); + self.alertCoordinator = [ContentSuggestionsAlertFactory + alertCoordinatorForSuggestionItem:suggestionsItem + onViewController:self.viewController + atPoint:touchLocation + atIndexPath:indexPath + readLaterAction:readLaterAction + commandHandler:self]; + + [self.alertCoordinator start]; +} + +- (void)displayContextMenuForMostVisitedItem:(CollectionViewItem*)item + atPoint:(CGPoint)touchLocation + atIndexPath:(NSIndexPath*)indexPath { + ContentSuggestionsMostVisitedItem* mostVisitedItem = + base::mac::ObjCCastStrict<ContentSuggestionsMostVisitedItem>(item); + self.alertCoordinator = [ContentSuggestionsAlertFactory + alertCoordinatorForMostVisitedItem:mostVisitedItem + onViewController:self.viewController + atPoint:touchLocation + atIndexPath:indexPath + commandHandler:self]; + + [self.alertCoordinator start]; +} + +- (void)handlePromoTapped { + // TODO: implement this. +} + +- (void)handleLearnMoreTapped { + // TODO: implement this. +} + +- (void)dismissModals { + [self.alertCoordinator stop]; + self.alertCoordinator = nil; +} + +#pragma mark - ContentSuggestionsGestureCommands + +- (void)openNewTabWithSuggestionsItem:(ContentSuggestionsItem*)item + incognito:(BOOL)incognito { + // TODO: implement this. +} + +- (void)addItemToReadingList:(ContentSuggestionsItem*)item { + base::RecordAction(base::UserMetricsAction("MobileReadingListAdd")); + ReadingListModel* readingModel = ReadingListModelFactory::GetForBrowserState( + self.browser->browser_state()); + readingModel->AddEntry(item.URL, base::SysNSStringToUTF8(item.title), + reading_list::ADDED_VIA_CURRENT_APP); +} + +- (void)dismissSuggestion:(ContentSuggestionsItem*)item + atIndexPath:(NSIndexPath*)indexPath { + NSIndexPath* itemIndexPath = indexPath; + if (!itemIndexPath) { + // If the caller uses a nil |indexPath|, find it from the model. + itemIndexPath = + [self.viewController.collectionViewModel indexPathForItem:item]; + } + + // TODO(crbug.com/691979): Add metrics. + [self.suggestionsMediator dismissSuggestion:item.suggestionIdentifier]; + [self.viewController dismissEntryAtIndexPath:itemIndexPath]; +} + +- (void)openNewTabWithMostVisitedItem:(ContentSuggestionsMostVisitedItem*)item + incognito:(BOOL)incognito + atIndex:(NSInteger)index { + // TODO: implement this. +} + +- (void)openNewTabWithMostVisitedItem:(ContentSuggestionsMostVisitedItem*)item + incognito:(BOOL)incognito { + // TODO: implement this. +} + +- (void)removeMostVisited:(ContentSuggestionsMostVisitedItem*)item { + base::RecordAction(base::UserMetricsAction("MostVisited_UrlBlacklisted")); + [self.suggestionsMediator blacklistMostVisitedURL:item.URL]; + [self showMostVisitedUndoForURL:item.URL]; +} + +#pragma mark - ContentSuggestionsHeaderViewControllerDelegate + +- (BOOL)isContextMenuVisible { + return self.alertCoordinator.isVisible; +} + +- (BOOL)isScrolledToTop { + return self.viewController.scrolledToTop; +} + +#pragma mark - ContentSuggestionsViewControllerDelegate + +- (CGFloat)pinnedOffsetY { + CGFloat headerHeight = content_suggestions::heightForLogoHeader( + self.headerViewController.logoIsShowing, + [self.suggestionsMediator notificationPromo]->CanShow()); + CGFloat offsetY = + headerHeight - ntp_header::kScrolledToTopOmniboxBottomMargin; + if (!IsIPadIdiom()) + offsetY -= ntp_header::kToolbarHeight; + + return offsetY; +} + +- (BOOL)isOmniboxFocused { + return [self.headerViewController isOmniboxFocused]; +} + +- (CGFloat)headerHeight { + return content_suggestions::heightForLogoHeader( + self.headerViewController.logoIsShowing, + [self.suggestionsMediator notificationPromo]->CanShow()); +} + +#pragma mark - ContentSuggestionsViewControllerAudience + +- (void)contentOffsetDidChange { + // TODO: implement this. +} + +- (void)promoShown { + NotificationPromoWhatsNew* notificationPromo = + [self.suggestionsMediator notificationPromo]; + notificationPromo->HandleViewed(); + [self.headerViewController setPromoCanShow:notificationPromo->CanShow()]; +} + +#pragma mark - Private + +// Shows a snackbar with an action to undo the removal of the most visited item +// with a |URL|. +- (void)showMostVisitedUndoForURL:(GURL)URL { + GURL copiedURL = URL; + + MDCSnackbarMessageAction* action = [[MDCSnackbarMessageAction alloc] init]; + __weak NTPHomeCoordinator* weakSelf = self; + action.handler = ^{ + NTPHomeCoordinator* strongSelf = weakSelf; + if (!strongSelf) + return; + [strongSelf.suggestionsMediator whitelistMostVisitedURL:copiedURL]; + }; + action.title = l10n_util::GetNSString(IDS_NEW_TAB_UNDO_THUMBNAIL_REMOVE); + action.accessibilityIdentifier = @"Undo"; + + TriggerHapticFeedbackForNotification(UINotificationFeedbackTypeSuccess); + MDCSnackbarMessage* message = [MDCSnackbarMessage + messageWithText:l10n_util::GetNSString( + IDS_IOS_NEW_TAB_MOST_VISITED_ITEM_REMOVED)]; + message.action = action; + message.category = @"MostVisitedUndo"; + [MDCSnackbarManager showMessage:message]; } @end
diff --git a/ios/clean/chrome/browser/ui/ntp/ntp_home_header_view_controller.h b/ios/clean/chrome/browser/ui/ntp/ntp_home_header_view_controller.h new file mode 100644 index 0000000..5ef1562 --- /dev/null +++ b/ios/clean/chrome/browser/ui/ntp/ntp_home_header_view_controller.h
@@ -0,0 +1,37 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CLEAN_CHROME_BROWSER_UI_NTP_NTP_HOME_HEADER_VIEW_CONTROLLER_H_ +#define IOS_CLEAN_CHROME_BROWSER_UI_NTP_NTP_HOME_HEADER_VIEW_CONTROLLER_H_ + +#import <UIKit/UIKit.h> + +#import "ios/chrome/browser/content_suggestions/content_suggestions_header_provider.h" +#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_header_controlling.h" +#import "ios/chrome/browser/ui/ntp/google_landing_consumer.h" + +@protocol ContentSuggestionsCollectionSynchronizing; +@protocol ContentSuggestionsHeaderViewControllerCommandHandler; +@protocol ContentSuggestionsHeaderViewControllerDelegate; + +// Coordinator handling the header of the NTP home panel. +@interface NTPHomeHeaderViewController + : UIViewController<ContentSuggestionsHeaderControlling, + ContentSuggestionsHeaderProvider, + GoogleLandingConsumer> + +// Whether the Google logo or doodle is being shown. +@property(nonatomic, assign) BOOL logoIsShowing; + +@property(nonatomic, weak) id<ContentSuggestionsHeaderViewControllerDelegate> + delegate; +@property(nonatomic, weak) + id<ContentSuggestionsHeaderViewControllerCommandHandler> + commandHandler; +@property(nonatomic, weak) id<ContentSuggestionsCollectionSynchronizing> + collectionSynchronizer; + +@end + +#endif // IOS_CLEAN_CHROME_BROWSER_UI_NTP_NTP_HOME_HEADER_VIEW_CONTROLLER_H_
diff --git a/ios/clean/chrome/browser/ui/ntp/ntp_home_header_view_controller.mm b/ios/clean/chrome/browser/ui/ntp/ntp_home_header_view_controller.mm new file mode 100644 index 0000000..dbe7494 --- /dev/null +++ b/ios/clean/chrome/browser/ui/ntp/ntp_home_header_view_controller.mm
@@ -0,0 +1,108 @@ +// 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. + +#import "ios/clean/chrome/browser/ui/ntp/ntp_home_header_view_controller.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface NTPHomeHeaderViewController () + +// Redifined as readwrite +@property(nonatomic, assign, getter=isOmniboxFocused, readwrite) + BOOL omniboxFocused; + +#pragma mark properties from GoogleLandingConsumer + +// |YES| if this consumer is has voice search enabled. +@property(nonatomic, assign) BOOL voiceSearchIsEnabled; +// Exposes view and methods to drive the doodle. +@property(nonatomic, weak) id<LogoVendor> logoVendor; + +@end +@implementation NTPHomeHeaderViewController + +@synthesize omniboxFocused = _omniboxFocused; +@synthesize logoIsShowing = _logoIsShowing; +@synthesize voiceSearchIsEnabled = _voiceSearchIsEnabled; +@synthesize logoVendor = _logoVendor; + +@synthesize delegate = _delegate; +@synthesize commandHandler = _commandHandler; +@synthesize collectionSynchronizer = _collectionSynchronizer; + +#pragma mark - ContentSuggestionsHeaderProvider + +- (UIView*)headerForWidth:(CGFloat)width { + return nil; +} + +#pragma mark - ContentSuggestionsHeaderControlling + +- (void)updateSearchFieldForOffset:(CGFloat)offset { + // TODO: implement this. +} + +- (void)unfocusOmnibox { + // TODO: implement this. +} + +- (void)layoutHeader { + // TODO: implement this. +} + +#pragma mark - GoogleLandingConsumer + +- (void)setLogoIsShowing:(BOOL)logoIsShowing { + _logoIsShowing = logoIsShowing; + // TODO: implement this. +} + +- (void)setMaximumMostVisitedSitesShown: + (NSUInteger)maximumMostVisitedSitesShown { + // Do nothing as it is handled elsewhere. +} + +- (void)setPromoText:(NSString*)promoText { + // Do nothing as it is handled elsewhere. +} + +- (void)setPromoIcon:(WhatsNewIcon)promoIcon { + // Do nothing as it is handled elsewhere. +} + +- (void)setPromoCanShow:(BOOL)promoCanShow { + // Do nothing as it is handled elsewhere. +} + +- (void)setTabCount:(int)tabCount { + // Do nothing as it is handled elsewhere. +} + +- (void)setCanGoForward:(BOOL)canGoForward { + // Do nothing as it is handled elsewhere. +} + +- (void)setCanGoBack:(BOOL)canGoBack { + // Do nothing as it is handled elsewhere. +} + +- (void)mostVisitedDataUpdated { + // Do nothing as it is handled elsewhere. +} + +- (void)mostVisitedIconMadeAvailableAtIndex:(NSUInteger)index { + // Do nothing as it is handled elsewhere. +} + +- (void)locationBarResignsFirstResponder { + // TODO: implement this. +} + +- (void)locationBarBecomesFirstResponder { + // TODO: implement this. +} + +@end
diff --git a/ios/clean/chrome/browser/ui/ntp/ntp_home_mediator_unittest.mm b/ios/clean/chrome/browser/ui/ntp/ntp_home_header_view_controller_unittest.mm similarity index 77% rename from ios/clean/chrome/browser/ui/ntp/ntp_home_mediator_unittest.mm rename to ios/clean/chrome/browser/ui/ntp/ntp_home_header_view_controller_unittest.mm index 567a667..5510aa22 100644 --- a/ios/clean/chrome/browser/ui/ntp/ntp_home_mediator_unittest.mm +++ b/ios/clean/chrome/browser/ui/ntp/ntp_home_header_view_controller_unittest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/clean/chrome/browser/ui/ntp/ntp_home_mediator.h" +#import "ios/clean/chrome/browser/ui/ntp/ntp_home_header_view_controller.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support."
diff --git a/ios/clean/chrome/browser/ui/ntp/ntp_home_mediator.h b/ios/clean/chrome/browser/ui/ntp/ntp_home_mediator.h deleted file mode 100644 index 8e14304..0000000 --- a/ios/clean/chrome/browser/ui/ntp/ntp_home_mediator.h +++ /dev/null
@@ -1,24 +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. - -#ifndef IOS_CLEAN_CHROME_BROWSER_UI_NTP_NTP_HOME_MEDIATOR_H_ -#define IOS_CLEAN_CHROME_BROWSER_UI_NTP_NTP_HOME_MEDIATOR_H_ - -#import <UIKit/UIKit.h> - -#import "ios/chrome/browser/ui/toolbar/web_toolbar_controller.h" -#import "ios/chrome/browser/ui/url_loader.h" - -@protocol TabCommands; - -// A mediator object that sets an NTP home view controller's appearance based -// on various data sources. -@interface NTPHomeMediator : NSObject<UrlLoader, OmniboxFocuser> - -// The dispatcher for this mediator. -@property(nonatomic, weak) id<TabCommands> dispatcher; - -@end - -#endif // IOS_CLEAN_CHROME_BROWSER_UI_NTP_NTP_HOME_MEDIATOR_H_
diff --git a/ios/clean/chrome/browser/ui/ntp/ntp_home_mediator.mm b/ios/clean/chrome/browser/ui/ntp/ntp_home_mediator.mm deleted file mode 100644 index 8aea01c2..0000000 --- a/ios/clean/chrome/browser/ui/ntp/ntp_home_mediator.mm +++ /dev/null
@@ -1,69 +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. - -#import "ios/clean/chrome/browser/ui/ntp/ntp_home_mediator.h" - -#import "ios/clean/chrome/browser/ui/commands/tab_commands.h" -#import "ios/web/public/navigation_manager.h" -#include "ui/base/page_transition_types.h" -#include "url/gurl.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface NTPHomeMediator () -@end - -@implementation NTPHomeMediator -@synthesize dispatcher = _dispatcher; - -#pragma mark - UrlLoader - -- (void)loadURL:(const GURL&)url - referrer:(const web::Referrer&)referrer - transition:(ui::PageTransition)transition - rendererInitiated:(BOOL)rendererInitiated { - web::NavigationManager::WebLoadParams params(url); - params.transition_type = transition; - [self.dispatcher loadURL:params]; -} - -- (void)webPageOrderedOpen:(const GURL&)url - referrer:(const web::Referrer&)referrer - inBackground:(BOOL)inBackground - appendTo:(OpenPosition)appendTo { -} - -- (void)webPageOrderedOpen:(const GURL&)url - referrer:(const web::Referrer&)referrer - inIncognito:(BOOL)inIncognito - inBackground:(BOOL)inBackground - appendTo:(OpenPosition)appendTo { -} - -- (void)loadSessionTab:(const sessions::SessionTab*)sessionTab { -} - -- (void)loadJavaScriptFromLocationBar:(NSString*)script { -} - -#pragma mark - OmniboxFocuser - -- (void)focusOmnibox { -} - -- (void)cancelOmniboxEdit { -} - -- (void)focusFakebox { -} - -- (void)onFakeboxBlur { -} - -- (void)onFakeboxAnimationComplete { -} - -@end
diff --git a/ios/showcase/bubble/sc_bubble_coordinator.mm b/ios/showcase/bubble/sc_bubble_coordinator.mm index 56a7364a..de30eeb 100644 --- a/ios/showcase/bubble/sc_bubble_coordinator.mm +++ b/ios/showcase/bubble/sc_bubble_coordinator.mm
@@ -65,10 +65,10 @@ [self.containerViewController addChildViewController:self.bubbleViewController]; self.bubbleViewController.view.frame = bubbleFrame; - self.bubbleViewController.view.backgroundColor = [UIColor blueColor]; [self.containerViewController.view addSubview:self.bubbleViewController.view]; [self.bubbleViewController didMoveToParentViewController:self.containerViewController]; + [self.bubbleViewController animateContentIn]; } @end
diff --git a/ios/web/navigation/navigation_manager_impl_unittest.mm b/ios/web/navigation/navigation_manager_impl_unittest.mm index 9de73ae..937bc786 100644 --- a/ios/web/navigation/navigation_manager_impl_unittest.mm +++ b/ios/web/navigation/navigation_manager_impl_unittest.mm
@@ -1957,6 +1957,126 @@ EXPECT_TRUE(back_items.empty()); } +TEST_P(NavigationManagerTest, VisibleItemIsTransientItemIfPresent) { + navigation_manager()->AddPendingItem( + GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED, + web::NavigationInitiationType::USER_INITIATED, + web::NavigationManager::UserAgentOverrideOption::INHERIT); + navigation_manager()->AddTransientItem(GURL("http://www.url.com/1")); + + ASSERT_TRUE(navigation_manager()->GetVisibleItem()); + EXPECT_EQ("http://www.url.com/1", + navigation_manager()->GetVisibleItem()->GetURL().spec()); + + // Visible item is still transient item even if there is a committed item. + [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"]; + navigation_manager()->CommitPendingItem(); + + navigation_manager()->AddPendingItem( + GURL("http://www.url.com/2"), Referrer(), ui::PAGE_TRANSITION_TYPED, + web::NavigationInitiationType::USER_INITIATED, + web::NavigationManager::UserAgentOverrideOption::INHERIT); + navigation_manager()->AddTransientItem(GURL("http://www.url.com/3")); + + ASSERT_TRUE(navigation_manager()->GetVisibleItem()); + EXPECT_EQ("http://www.url.com/3", + navigation_manager()->GetVisibleItem()->GetURL().spec()); +} + +TEST_P(NavigationManagerTest, PendingItemIsVisibleIfNewAndUserInitiated) { + navigation_manager()->AddPendingItem( + GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED, + web::NavigationInitiationType::USER_INITIATED, + web::NavigationManager::UserAgentOverrideOption::INHERIT); + + ASSERT_TRUE(navigation_manager()->GetVisibleItem()); + EXPECT_EQ("http://www.url.com/0", + navigation_manager()->GetVisibleItem()->GetURL().spec()); + + // Visible item is still the user initiated pending item even if there is a + // committed item. + [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"]; + navigation_manager()->CommitPendingItem(); + + navigation_manager()->AddPendingItem( + GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_TYPED, + web::NavigationInitiationType::USER_INITIATED, + web::NavigationManager::UserAgentOverrideOption::INHERIT); + + ASSERT_TRUE(navigation_manager()->GetVisibleItem()); + EXPECT_EQ("http://www.url.com/1", + navigation_manager()->GetVisibleItem()->GetURL().spec()); +} + +TEST_P(NavigationManagerTest, PendingItemIsNotVisibleIfNotUserInitiated) { + navigation_manager()->AddPendingItem( + GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED, + web::NavigationInitiationType::RENDERER_INITIATED, + web::NavigationManager::UserAgentOverrideOption::INHERIT); + + EXPECT_EQ(nullptr, navigation_manager()->GetVisibleItem()); +} + +TEST_P(NavigationManagerTest, PendingItemIsNotVisibleIfNotNewNavigation) { + navigation_manager()->AddPendingItem( + GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED, + web::NavigationInitiationType::RENDERER_INITIATED, + web::NavigationManager::UserAgentOverrideOption::INHERIT); + + [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"]; + navigation_manager()->CommitPendingItem(); + + navigation_manager()->AddPendingItem( + GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_TYPED, + web::NavigationInitiationType::RENDERER_INITIATED, + web::NavigationManager::UserAgentOverrideOption::INHERIT); + + [mock_wk_list_ setCurrentURL:@"http://www.url.com/1" + backListURLs:@[ @"http://www.url.com/0" ] + forwardListURLs:nil]; + navigation_manager()->CommitPendingItem(); + + // Move pending item back to index 0. + if (GetParam() == TEST_LEGACY_NAVIGATION_MANAGER) { + [session_controller() setPendingItemIndex:0]; + } else { + OCMExpect([mock_web_view_ URL]) + .andReturn([NSURL URLWithString:@"http://www.url.com/0"]); + [mock_wk_list_ setCurrentURL:@"http://www.url.com/0" + backListURLs:nil + forwardListURLs:@[ @"http://www.url.com/1" ]]; + navigation_manager()->AddPendingItem( + GURL("http://www.url.com/0"), Referrer(), + ui::PAGE_TRANSITION_FORWARD_BACK, + web::NavigationInitiationType::USER_INITIATED, + web::NavigationManager::UserAgentOverrideOption::INHERIT); + } + ASSERT_EQ(0, navigation_manager()->GetPendingItemIndex()); + + ASSERT_TRUE(navigation_manager()->GetVisibleItem()); + EXPECT_EQ("http://www.url.com/1", + navigation_manager()->GetVisibleItem()->GetURL().spec()); +} + +TEST_P(NavigationManagerTest, VisibleItemDefaultsToLastCommittedItem) { + navigation_manager()->AddPendingItem( + GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED, + web::NavigationInitiationType::RENDERER_INITIATED, + web::NavigationManager::UserAgentOverrideOption::INHERIT); + + [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"]; + navigation_manager()->CommitPendingItem(); + + navigation_manager()->AddPendingItem( + GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_TYPED, + web::NavigationInitiationType::RENDERER_INITIATED, + web::NavigationManager::UserAgentOverrideOption::INHERIT); + + ASSERT_TRUE(navigation_manager()->GetVisibleItem()); + EXPECT_EQ("http://www.url.com/0", + navigation_manager()->GetVisibleItem()->GetURL().spec()); +} + INSTANTIATE_TEST_CASE_P( ProgrammaticNavigationManagerTest, NavigationManagerTest,
diff --git a/ios/web/navigation/wk_based_navigation_manager_impl.h b/ios/web/navigation/wk_based_navigation_manager_impl.h index 2ed66b7..e19a581 100644 --- a/ios/web/navigation/wk_based_navigation_manager_impl.h +++ b/ios/web/navigation/wk_based_navigation_manager_impl.h
@@ -113,6 +113,9 @@ // NavigationManagerImpl methods used by SessionStorageBuilder. NavigationItemImpl* GetNavigationItemImplAtIndex(size_t index) const override; + // NavigationManagerImpl version of GetPendingItem(). + NavigationItemImpl* GetPendingItemImpl() const; + // Returns the absolute index of WKBackForwardList's |currentItem|. Returns -1 // if |currentItem| is nil. int GetWKCurrentItemIndex() const;
diff --git a/ios/web/navigation/wk_based_navigation_manager_impl.mm b/ios/web/navigation/wk_based_navigation_manager_impl.mm index 51c29be8..0b29968d 100644 --- a/ios/web/navigation/wk_based_navigation_manager_impl.mm +++ b/ios/web/navigation/wk_based_navigation_manager_impl.mm
@@ -210,8 +210,23 @@ } NavigationItem* WKBasedNavigationManagerImpl::GetVisibleItem() const { - DLOG(WARNING) << "Not yet implemented."; - return nullptr; + NavigationItem* transient_item = GetTransientItem(); + if (transient_item) { + return transient_item; + } + + // Only return pending_item_ for new (non-history), user-initiated + // navigations in order to prevent URL spoof attacks. + NavigationItemImpl* pending_item = GetPendingItemImpl(); + if (pending_item) { + bool is_user_initiated = pending_item->NavigationInitiationType() == + NavigationInitiationType::USER_INITIATED; + bool safe_to_show_pending = is_user_initiated && pending_item_index_ == -1; + if (safe_to_show_pending) { + return pending_item; + } + } + return GetLastCommittedItem(); } NavigationItem* WKBasedNavigationManagerImpl::GetLastCommittedItem() const { @@ -220,8 +235,7 @@ } NavigationItem* WKBasedNavigationManagerImpl::GetPendingItem() const { - return (pending_item_index_ == -1) ? pending_item_.get() - : GetItemAtIndex(pending_item_index_); + return GetPendingItemImpl(); } NavigationItem* WKBasedNavigationManagerImpl::GetTransientItem() const { @@ -388,6 +402,12 @@ return GetNavigationItemFromWKItem(wk_item); } +NavigationItemImpl* WKBasedNavigationManagerImpl::GetPendingItemImpl() const { + return (pending_item_index_ == -1) + ? pending_item_.get() + : GetNavigationItemImplAtIndex(pending_item_index_); +} + int WKBasedNavigationManagerImpl::GetWKCurrentItemIndex() const { id<CRWWebViewNavigationProxy> proxy = delegate_->GetWebViewNavigationProxy(); if (proxy.backForwardList.currentItem) {
diff --git a/ios/web/web_state/ui/crw_web_controller.h b/ios/web/web_state/ui/crw_web_controller.h index bf4e1d8e53..2f55229a 100644 --- a/ios/web/web_state/ui/crw_web_controller.h +++ b/ios/web/web_state/ui/crw_web_controller.h
@@ -198,13 +198,8 @@ // Requires that the next load rebuild the web view. This is expensive, and // should be used only in the case where something has changed that the web view // only checks on creation, such that the whole object needs to be rebuilt. -// TODO(crbug.com/736102): Merge this and reinitializeWebViewAndReload:. They -// are currently subtly different in terms of implementation, but are for -// fundamentally the same purpose. - (void)requirePageReconstruction; -- (void)reinitializeWebViewAndReload:(BOOL)reload; - // Requires that the next display reload the page, using a placeholder while // loading. This could be used, e.g., to handle a crash in a WebController that // is not currently visible.
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index 1befb1a8..01c4f3f 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -1130,21 +1130,6 @@ _containerView.reset(); } -- (void)reinitializeWebViewAndReload:(BOOL)reload { - if (_webView) { - [self removeWebViewAllowingCachedReconstruction:NO]; - if (reload) { - [self loadCurrentURLInWebView]; - } else { - // Clear the space for the web view to lazy load when needed. - _usePlaceholderOverlay = YES; - _touchTrackingRecognizer.get().touchTrackingDelegate = nil; - _touchTrackingRecognizer.reset(); - [self resetContainerView]; - } - } -} - - (BOOL)isViewAlive { return !_webProcessCrashed && [_containerView isViewAlive]; } @@ -1431,6 +1416,7 @@ - (id<CRWWebViewNavigationProxy>)webViewNavigationProxy { DCHECK( + !self.webView || [self.webView conformsToProtocol:@protocol(CRWWebViewNavigationProxy)]); return static_cast<id<CRWWebViewNavigationProxy>>(self.webView); } @@ -1854,7 +1840,11 @@ // Mark pending item as created from hash change if necessary. This is needed // because window.hashchange message may not arrive on time. - web::NavigationItemImpl* pendingItem = self.sessionController.pendingItem; + // TODO(crbug.com/738020) Using static_cast for down-cast is not safe in the + // long run. Move this block to NavigationManager if the nav experiment is + // successful. + web::NavigationItemImpl* pendingItem = static_cast<web::NavigationItemImpl*>( + self.navigationManagerImpl->GetPendingItem()); if (pendingItem) { GURL lastCommittedURL = _webStateImpl->GetLastCommittedURL(); GURL pendingURL = pendingItem->GetURL(); @@ -1910,7 +1900,7 @@ // WebUI URLs can not be opened by DOM to prevent cross-site scripting as // they have increased power. WebUI URLs may only be opened when the user // types in the URL or use bookmarks. - [[self sessionController] discardNonCommittedItems]; + self.navigationManagerImpl->DiscardNonCommittedItems(); return; } else { [self createWebUIForURL:currentURL]; @@ -3155,7 +3145,7 @@ - (void)handleCancelledError:(NSError*)error { if ([self shouldCancelLoadForCancelledError:error]) { [self loadCancelled]; - [[self sessionController] discardNonCommittedItems]; + self.navigationManagerImpl->DiscardNonCommittedItems(); // If discarding the non-committed entries results in native content URL, // reload it in its native view. if (!self.nativeController) { @@ -4186,7 +4176,7 @@ base::RecordAction(UserMetricsAction("Stop")); // Discard the pending and transient entried before notifying the tab model // observers of the change via |-abortLoad|. - [[self sessionController] discardNonCommittedItems]; + self.navigationManagerImpl->DiscardNonCommittedItems(); [self abortLoad]; web::NavigationItem* item = self.currentNavItem; GURL navigationURL = item ? item->GetVirtualURL() : GURL::EmptyGURL(); @@ -4398,7 +4388,7 @@ BOOL previousItemWasLoadedInNativeView = [self shouldLoadURLInNativeView:lastCommittedURL]; if (!isFirstLoad && !previousItemWasLoadedInNativeView) - [self.sessionController discardNonCommittedItems]; + self.navigationManagerImpl->DiscardNonCommittedItems(); } handler(allowNavigation ? WKNavigationResponsePolicyAllow @@ -5184,7 +5174,8 @@ return; } - BOOL isBack = pendingIndex < self.sessionController.lastCommittedItemIndex; + BOOL isBack = + pendingIndex < self.navigationManagerImpl->GetLastCommittedItemIndex(); BackForwardNavigationType type = BackForwardNavigationType::FAST_BACK; if (isBack) { type = isFast ? BackForwardNavigationType::FAST_BACK
diff --git a/ios/web_view/internal/web_view_browser_state.mm b/ios/web_view/internal/web_view_browser_state.mm index 145e073..81e8693 100644 --- a/ios/web_view/internal/web_view_browser_state.mm +++ b/ios/web_view/internal/web_view_browser_state.mm
@@ -46,8 +46,7 @@ request_context_getter_ = new WebViewURLRequestContextGetter( GetStatePath(), - web::WebThread::GetTaskRunnerForThread(web::WebThread::IO), - web::WebThread::GetTaskRunnerForThread(web::WebThread::FILE)); + web::WebThread::GetTaskRunnerForThread(web::WebThread::IO)); BrowserState::Initialize(this, path_);
diff --git a/ios/web_view/internal/web_view_url_request_context_getter.h b/ios/web_view/internal/web_view_url_request_context_getter.h index 3837094b..d1bed19 100644 --- a/ios/web_view/internal/web_view_url_request_context_getter.h +++ b/ios/web_view/internal/web_view_url_request_context_getter.h
@@ -29,8 +29,7 @@ public: WebViewURLRequestContextGetter( const base::FilePath& base_path, - const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner, - const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner); + const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner); // net::URLRequestContextGetter implementation. net::URLRequestContext* GetURLRequestContext() override; @@ -42,7 +41,6 @@ private: base::FilePath base_path_; - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; std::unique_ptr<net::ProxyConfigService> proxy_config_service_; std::unique_ptr<net::NetworkDelegate> network_delegate_;
diff --git a/ios/web_view/internal/web_view_url_request_context_getter.mm b/ios/web_view/internal/web_view_url_request_context_getter.mm index 1cd02d6..ca4cb5d 100644 --- a/ios/web_view/internal/web_view_url_request_context_getter.mm +++ b/ios/web_view/internal/web_view_url_request_context_getter.mm
@@ -45,10 +45,8 @@ WebViewURLRequestContextGetter::WebViewURLRequestContextGetter( const base::FilePath& base_path, - const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner, - const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner) + const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner) : base_path_(base_path), - file_task_runner_(file_task_runner), network_task_runner_(network_task_runner), proxy_config_service_(new net::ProxyConfigServiceIOS), net_log_(new net::NetLog()) {} @@ -103,7 +101,9 @@ base::WrapUnique(new net::CTPolicyEnforcer)); transport_security_persister_.reset(new net::TransportSecurityPersister( url_request_context_->transport_security_state(), base_path_, - file_task_runner_, false)); + base::CreateSequencedTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::BACKGROUND}), + false)); storage_->set_channel_id_service(base::MakeUnique<net::ChannelIDService>( new net::DefaultChannelIDStore(nullptr))); storage_->set_http_server_properties(
diff --git a/ipc/handle_attachment_win.cc b/ipc/handle_attachment_win.cc index 9249a5a..6f6fc34 100644 --- a/ipc/handle_attachment_win.cc +++ b/ipc/handle_attachment_win.cc
@@ -9,29 +9,21 @@ namespace IPC { namespace internal { -HandleAttachmentWin::HandleAttachmentWin(const HANDLE& handle, - HandleWin::Permissions permissions) - : handle_(INVALID_HANDLE_VALUE), - permissions_(HandleWin::INVALID), - owns_handle_(true) { +HandleAttachmentWin::HandleAttachmentWin(const HANDLE& handle) { HANDLE duplicated_handle; BOOL result = ::DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), &duplicated_handle, 0, FALSE, DUPLICATE_SAME_ACCESS); if (result) { - handle_ = duplicated_handle; - permissions_ = permissions; + handle_.Set(duplicated_handle); } } HandleAttachmentWin::HandleAttachmentWin(const HANDLE& handle, FromWire from_wire) - : handle_(handle), permissions_(HandleWin::INVALID), owns_handle_(true) {} + : handle_(handle) {} -HandleAttachmentWin::~HandleAttachmentWin() { - if (handle_ != INVALID_HANDLE_VALUE && owns_handle_) - ::CloseHandle(handle_); -} +HandleAttachmentWin::~HandleAttachmentWin() {} MessageAttachment::Type HandleAttachmentWin::GetType() const { return Type::WIN_HANDLE;
diff --git a/ipc/handle_attachment_win.h b/ipc/handle_attachment_win.h index ef3b8965..3ee9f43 100644 --- a/ipc/handle_attachment_win.h +++ b/ipc/handle_attachment_win.h
@@ -7,7 +7,7 @@ #include <stdint.h> -#include "base/process/process_handle.h" +#include "base/win/scoped_handle.h" #include "ipc/handle_win.h" #include "ipc/ipc_export.h" #include "ipc/ipc_message_attachment.h" @@ -20,7 +20,7 @@ public: // This constructor makes a copy of |handle| and takes ownership of the // result. Should only be called by the sender of a Chrome IPC message. - HandleAttachmentWin(const HANDLE& handle, HandleWin::Permissions permissions); + explicit HandleAttachmentWin(const HANDLE& handle); enum FromWire { FROM_WIRE, @@ -29,27 +29,15 @@ // receiver of a Chrome IPC message. HandleAttachmentWin(const HANDLE& handle, FromWire from_wire); + // MessageAttachment interface. Type GetType() const override; - HANDLE get_handle() const { return handle_; } - - // The caller of this method has taken ownership of |handle_|. - void reset_handle_ownership() { - owns_handle_ = false; - handle_ = INVALID_HANDLE_VALUE; - } + HANDLE Take() { return handle_.Take(); } private: ~HandleAttachmentWin() override; - HANDLE handle_; - HandleWin::Permissions permissions_; - // In the sender process, the attachment owns the HANDLE of a newly created - // message. The attachment broker will eventually take ownership, and set - // this member to |false|. - // In the destination process, the attachment owns the Mach port until a call - // to ParamTraits<HandleWin>::Read() takes ownership. - bool owns_handle_; + base::win::ScopedHandle handle_; }; } // namespace internal
diff --git a/ipc/handle_win.cc b/ipc/handle_win.cc index c8511e2..ba981c1a5 100644 --- a/ipc/handle_win.cc +++ b/ipc/handle_win.cc
@@ -15,16 +15,14 @@ namespace IPC { -HandleWin::HandleWin() : handle_(nullptr), permissions_(INVALID) {} +HandleWin::HandleWin() : handle_(INVALID_HANDLE_VALUE) {} -HandleWin::HandleWin(const HANDLE& handle, Permissions permissions) - : handle_(handle), permissions_(permissions) {} +HandleWin::HandleWin(const HANDLE& handle) : handle_(handle) {} // static void ParamTraits<HandleWin>::Write(base::Pickle* m, const param_type& p) { scoped_refptr<IPC::internal::HandleAttachmentWin> attachment( - new IPC::internal::HandleAttachmentWin(p.get_handle(), - p.get_permissions())); + new IPC::internal::HandleAttachmentWin(p.get_handle())); if (!m->WriteAttachment(std::move(attachment))) NOTREACHED(); } @@ -42,15 +40,13 @@ return false; IPC::internal::HandleAttachmentWin* handle_attachment = static_cast<IPC::internal::HandleAttachmentWin*>(attachment); - r->set_handle(handle_attachment->get_handle()); - handle_attachment->reset_handle_ownership(); + r->set_handle(handle_attachment->Take()); return true; } // static void ParamTraits<HandleWin>::Log(const param_type& p, std::string* l) { l->append(base::StringPrintf("0x%p", p.get_handle())); - l->append(base::IntToString(p.get_permissions())); } } // namespace IPC
diff --git a/ipc/handle_win.h b/ipc/handle_win.h index 96c1b0b42..0120597c 100644 --- a/ipc/handle_win.h +++ b/ipc/handle_win.h
@@ -28,28 +28,15 @@ // discussion. class IPC_EXPORT HandleWin { public: - enum Permissions { - // A placeholder value to be used by the receiving IPC channel, since the - // permissions information is only used by the broker process. - INVALID, - // The new HANDLE will have the same permissions as the old HANDLE. - DUPLICATE, - // The new HANDLE will have file read and write permissions. - FILE_READ_WRITE, - MAX_PERMISSIONS = FILE_READ_WRITE - }; - // Default constructor makes an invalid HANDLE. HandleWin(); - HandleWin(const HANDLE& handle, Permissions permissions); + explicit HandleWin(const HANDLE& handle); HANDLE get_handle() const { return handle_; } void set_handle(HANDLE handle) { handle_ = handle; } - Permissions get_permissions() const { return permissions_; } private: HANDLE handle_; - Permissions permissions_; }; template <>
diff --git a/ipc/ipc_channel_mojo.cc b/ipc/ipc_channel_mojo.cc index ba6b8edf..006a9ab6 100644 --- a/ipc/ipc_channel_mojo.cc +++ b/ipc/ipc_channel_mojo.cc
@@ -159,10 +159,9 @@ DCHECK_EQ(attachment->GetType(), MessageAttachment::Type::WIN_HANDLE); internal::HandleAttachmentWin& handle_attachment = static_cast<internal::HandleAttachmentWin&>(*attachment); - MojoResult result = WrapPlatformHandle( - handle_attachment.get_handle(), - mojom::SerializedHandle::Type::WIN_HANDLE, serialized); - handle_attachment.reset_handle_ownership(); + MojoResult result = + WrapPlatformHandle(handle_attachment.Take(), + mojom::SerializedHandle::Type::WIN_HANDLE, serialized); return result; #else NOTREACHED();
diff --git a/ipc/ipc_message_utils.cc b/ipc/ipc_message_utils.cc index c851d8a..a0c61d5 100644 --- a/ipc/ipc_message_utils.cc +++ b/ipc/ipc_message_utils.cc
@@ -712,7 +712,7 @@ MachPortMac mach_port_mac(p.GetMemoryObject()); WriteParam(m, mach_port_mac); #elif defined(OS_WIN) - HandleWin handle_win(p.GetHandle(), HandleWin::DUPLICATE); + HandleWin handle_win(p.GetHandle()); WriteParam(m, handle_win); #else if (p.OwnershipPassesToIPC()) { @@ -830,7 +830,7 @@ const param_type& p) { m->WriteBool(p.IsValid()); if (p.IsValid()) { - HandleWin handle_win(p.GetHandle(), HandleWin::DUPLICATE); + HandleWin handle_win(p.GetHandle()); ParamTraits<HandleWin>::Write(m, handle_win); ::CloseHandle(p.GetHandle()); }
diff --git a/ipc/ipc_mojo_perftest.cc b/ipc/ipc_mojo_perftest.cc index 366e5f8b..45f5203 100644 --- a/ipc/ipc_mojo_perftest.cc +++ b/ipc/ipc_mojo_perftest.cc
@@ -22,7 +22,9 @@ #include "mojo/edk/embedder/platform_channel_pair.h" #include "mojo/edk/test/mojo_test_base.h" #include "mojo/edk/test/multiprocess_test_helper.h" +#include "mojo/public/cpp/bindings/associated_binding_set.h" #include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/system/message_pipe.h" #define IPC_MESSAGE_IMPL @@ -93,7 +95,7 @@ static_cast<unsigned>(msg_size_)); perf_logger_.reset(new base::PerfTimeLogger(test_name.c_str())); if (sync_) { - for (int i = 0; i < count_down_; ++i) { + for (; count_down_ > 0; --count_down_) { std::string response; sender_->Send(new TestMsg_SyncPing(payload_, &response)); DCHECK_EQ(response, payload_); @@ -243,15 +245,29 @@ int message_count_; }; -std::vector<PingPongTestParams> GetDefaultTestParams() { -// Test several sizes. We use 12^N for message size, and limit the message -// count to keep the test duration reasonable. +class InterfacePassingTestParams { + public: + InterfacePassingTestParams(size_t rounds, size_t num_interfaces) + : rounds_(rounds), num_interfaces_(num_interfaces) {} + + size_t rounds() const { return rounds_; } + size_t num_interfaces() const { return num_interfaces_; } + + private: + size_t rounds_; + size_t num_interfaces_; +}; + #ifdef NDEBUG - const int kMultiplier = 100; +const int kMultiplier = 100; #else // Debug builds on Windows run these tests orders of magnitude more slowly. - const int kMultiplier = 1; +const int kMultiplier = 1; #endif + +std::vector<PingPongTestParams> GetDefaultTestParams() { + // Test several sizes. We use 12^N for message size, and limit the message + // count to keep the test duration reasonable. std::vector<PingPongTestParams> list; list.push_back(PingPongTestParams(12, 500 * kMultiplier)); list.push_back(PingPongTestParams(144, 500 * kMultiplier)); @@ -261,6 +277,16 @@ return list; } +std::vector<InterfacePassingTestParams> GetDefaultInterfacePassingTestParams() { + std::vector<InterfacePassingTestParams> list; + list.push_back({500 * kMultiplier, 0}); + list.push_back({500 * kMultiplier, 1}); + list.push_back({500 * kMultiplier, 2}); + list.push_back({500 * kMultiplier, 4}); + list.push_back({500 * kMultiplier, 8}); + return list; +} + // Avoid core 0 due to conflicts with Intel's Power Gadget. // Setting thread affinity will fail harmlessly on single/dual core machines. const int kSharedCore = 2; @@ -501,16 +527,198 @@ DISALLOW_COPY_AND_ASSIGN(MojoInterfacePerfTest); }; +class InterfacePassingTestDriverImpl : public mojom::InterfacePassingTestDriver, + public mojom::PingReceiver { + public: + InterfacePassingTestDriverImpl(mojo::ScopedMessagePipeHandle handle, + const base::Closure& quit_closure) + : binding_(this, + mojom::InterfacePassingTestDriverRequest(std::move(handle))), + quit_closure_(quit_closure) {} + ~InterfacePassingTestDriverImpl() override { + ignore_result(binding_.Unbind().PassMessagePipe().release()); + } + + private: + // mojom::InterfacePassingTestDriver implementation: + void Init(InitCallback callback) override { std::move(callback).Run(); } + + void GetPingReceiver(std::vector<mojom::PingReceiverRequest> requests, + GetPingReceiverCallback callback) override { + for (auto& request : requests) + ping_receiver_bindings_.AddBinding(this, std::move(request)); + ping_receiver_bindings_.CloseAllBindings(); + std::move(callback).Run(); + } + + void GetAssociatedPingReceiver( + std::vector<mojom::PingReceiverAssociatedRequest> requests, + GetAssociatedPingReceiverCallback callback) override { + for (auto& request : requests) + ping_receiver_associated_bindings_.AddBinding(this, std::move(request)); + ping_receiver_associated_bindings_.CloseAllBindings(); + std::move(callback).Run(); + } + + void Quit() override { + if (quit_closure_) + quit_closure_.Run(); + } + + // mojom::PingReceiver implementation: + void Ping(PingCallback callback) override { std::move(callback).Run(); } + + mojo::BindingSet<mojom::PingReceiver> ping_receiver_bindings_; + mojo::AssociatedBindingSet<mojom::PingReceiver> + ping_receiver_associated_bindings_; + mojo::Binding<mojom::InterfacePassingTestDriver> binding_; + + base::Closure quit_closure_; +}; + +class MojoInterfacePassingPerfTest : public mojo::edk::test::MojoTestBase { + public: + MojoInterfacePassingPerfTest() = default; + + protected: + void RunInterfacePassingServer(MojoHandle mp, + const std::string& label, + bool associated) { + label_ = label; + associated_ = associated; + + mojo::MessagePipeHandle mp_handle(mp); + mojo::ScopedMessagePipeHandle scoped_mp(mp_handle); + driver_ptr_.Bind( + mojom::InterfacePassingTestDriverPtrInfo(std::move(scoped_mp), 0u)); + + auto params = GetDefaultInterfacePassingTestParams(); + + LockThreadAffinity thread_locker(kSharedCore); + for (size_t i = 0; i < params.size(); ++i) { + driver_ptr_->Init( + base::Bind(&MojoInterfacePassingPerfTest::OnInitCallback, + base::Unretained(this))); + rounds_ = count_down_ = params[i].rounds(); + num_interfaces_ = params[i].num_interfaces(); + + base::RunLoop run_loop; + quit_closure_ = run_loop.QuitWhenIdleClosure(); + run_loop.Run(); + } + + driver_ptr_->Quit(); + + ignore_result(driver_ptr_.PassInterface().PassHandle().release()); + } + + void OnInitCallback() { + DCHECK(!perf_logger_.get()); + std::string test_name = base::StringPrintf( + "IPC_%s_Perf_%zux_%zu", label_.c_str(), rounds_, num_interfaces_); + perf_logger_.reset(new base::PerfTimeLogger(test_name.c_str())); + + DoNextRound(); + } + + void DoNextRound() { + if (associated_) { + std::vector<mojom::PingReceiverAssociatedPtr> associated_interfaces( + num_interfaces_); + + std::vector<mojom::PingReceiverAssociatedRequest> requests( + num_interfaces_); + for (size_t i = 0; i < num_interfaces_; ++i) { + requests[i] = mojo::MakeRequest(&associated_interfaces[i]); + // Force the interface pointer to do full initialization. + associated_interfaces[i].get(); + } + + driver_ptr_->GetAssociatedPingReceiver( + std::move(requests), + base::Bind(&MojoInterfacePassingPerfTest::OnGetReceiverCallback, + base::Unretained(this))); + } else { + std::vector<mojom::PingReceiverPtr> interfaces(num_interfaces_); + + std::vector<mojom::PingReceiverRequest> requests(num_interfaces_); + for (size_t i = 0; i < num_interfaces_; ++i) { + requests[i] = mojo::MakeRequest(&interfaces[i]); + // Force the interface pointer to do full initialization. + interfaces[i].get(); + } + + driver_ptr_->GetPingReceiver( + std::move(requests), + base::Bind(&MojoInterfacePassingPerfTest::OnGetReceiverCallback, + base::Unretained(this))); + } + } + + void OnGetReceiverCallback() { + CHECK_GT(count_down_, 0u); + count_down_--; + + if (count_down_ == 0) { + perf_logger_.reset(); + quit_closure_.Run(); + return; + } + + DoNextRound(); + } + + static int RunInterfacePassingClient(MojoHandle mp) { + mojo::MessagePipeHandle mp_handle(mp); + mojo::ScopedMessagePipeHandle scoped_mp(mp_handle); + + // In single process mode, this is running in a task and by default other + // tasks (in particular, the binding) won't run. To keep the single process + // and multi-process code paths the same, enable nestable tasks. + base::MessageLoop::ScopedNestableTaskAllower nest_loop( + base::MessageLoop::current()); + + LockThreadAffinity thread_locker(kSharedCore); + base::RunLoop run_loop; + InterfacePassingTestDriverImpl impl(std::move(scoped_mp), + run_loop.QuitWhenIdleClosure()); + run_loop.Run(); + return 0; + } + + private: + size_t rounds_ = 0; + size_t count_down_ = 0; + size_t num_interfaces_ = 0; + std::string label_; + bool associated_ = false; + std::unique_ptr<base::PerfTimeLogger> perf_logger_; + + mojom::InterfacePassingTestDriverPtr driver_ptr_; + + base::Closure quit_closure_; + + DISALLOW_COPY_AND_ASSIGN(MojoInterfacePassingPerfTest); +}; + +DEFINE_TEST_CLIENT_WITH_PIPE(InterfacePassingClient, + MojoInterfacePassingPerfTest, + h) { + base::MessageLoop main_message_loop; + return RunInterfacePassingClient(h); +} + enum class InProcessMessageMode { kSerialized, kUnserialized, }; -class MojoInProcessInterfacePerfTest - : public MojoInterfacePerfTest, +template <class TestBase> +class InProcessPerfTest + : public TestBase, public testing::WithParamInterface<InProcessMessageMode> { public: - MojoInProcessInterfacePerfTest() { + InProcessPerfTest() { switch (GetParam()) { case InProcessMessageMode::kSerialized: mojo::Connector::OverrideDefaultSerializationBehaviorForTesting( @@ -526,6 +734,10 @@ } }; +using MojoInProcessInterfacePerfTest = InProcessPerfTest<MojoInterfacePerfTest>; +using MojoInProcessInterfacePassingPerfTest = + InProcessPerfTest<MojoInterfacePassingPerfTest>; + DEFINE_TEST_CLIENT_WITH_PIPE(PingPongClient, MojoInterfacePerfTest, h) { base::MessageLoop main_message_loop; return RunPingPongClient(h); @@ -548,6 +760,21 @@ }); } +TEST_F(MojoInterfacePassingPerfTest, MultiprocessInterfacePassing) { + RunTestClient("InterfacePassingClient", [&](MojoHandle h) { + base::MessageLoop main_message_loop; + RunInterfacePassingServer(h, "InterfacePassing", false /* associated */); + }); +} + +TEST_F(MojoInterfacePassingPerfTest, MultiprocessAssociatedInterfacePassing) { + RunTestClient("InterfacePassingClient", [&](MojoHandle h) { + base::MessageLoop main_message_loop; + RunInterfacePassingServer(h, "AssociatedInterfacePassing", + true /* associated*/); + }); +} + // A single process version of the above test. TEST_P(MojoInProcessInterfacePerfTest, MultiThreadPingPong) { MojoHandle server_handle, client_handle; @@ -581,6 +808,71 @@ testing::Values(InProcessMessageMode::kSerialized, InProcessMessageMode::kUnserialized)); +TEST_P(MojoInProcessInterfacePassingPerfTest, MultiThreadInterfacePassing) { + MojoHandle server_handle, client_handle; + CreateMessagePipe(&server_handle, &client_handle); + + base::Thread client_thread("InterfacePassingClient"); + client_thread.Start(); + client_thread.task_runner()->PostTask( + FROM_HERE, base::Bind(base::IgnoreResult(&RunInterfacePassingClient), + client_handle)); + + base::MessageLoop main_message_loop; + RunInterfacePassingServer(server_handle, "SingleProcess", + false /* associated */); +} + +TEST_P(MojoInProcessInterfacePassingPerfTest, + MultiThreadAssociatedInterfacePassing) { + MojoHandle server_handle, client_handle; + CreateMessagePipe(&server_handle, &client_handle); + + base::Thread client_thread("InterfacePassingClient"); + client_thread.Start(); + client_thread.task_runner()->PostTask( + FROM_HERE, base::Bind(base::IgnoreResult(&RunInterfacePassingClient), + client_handle)); + + base::MessageLoop main_message_loop; + RunInterfacePassingServer(server_handle, "SingleProcess", + true /* associated */); +} + +TEST_P(MojoInProcessInterfacePassingPerfTest, SingleThreadInterfacePassing) { + MojoHandle server_handle, client_handle; + CreateMessagePipe(&server_handle, &client_handle); + + base::MessageLoop main_message_loop; + mojo::MessagePipeHandle mp_handle(client_handle); + mojo::ScopedMessagePipeHandle scoped_mp(mp_handle); + LockThreadAffinity thread_locker(kSharedCore); + InterfacePassingTestDriverImpl impl(std::move(scoped_mp), base::Closure()); + + RunInterfacePassingServer(server_handle, "SingleProcess", + false /* associated */); +} + +TEST_P(MojoInProcessInterfacePassingPerfTest, + SingleThreadAssociatedInterfacePassing) { + MojoHandle server_handle, client_handle; + CreateMessagePipe(&server_handle, &client_handle); + + base::MessageLoop main_message_loop; + mojo::MessagePipeHandle mp_handle(client_handle); + mojo::ScopedMessagePipeHandle scoped_mp(mp_handle); + LockThreadAffinity thread_locker(kSharedCore); + InterfacePassingTestDriverImpl impl(std::move(scoped_mp), base::Closure()); + + RunInterfacePassingServer(server_handle, "SingleProcess", + true /* associated */); +} + +INSTANTIATE_TEST_CASE_P(, + MojoInProcessInterfacePassingPerfTest, + testing::Values(InProcessMessageMode::kSerialized, + InProcessMessageMode::kUnserialized)); + class CallbackPerfTest : public testing::Test { public: CallbackPerfTest()
diff --git a/ipc/ipc_test.mojom b/ipc/ipc_test.mojom index 33181b8..2af9128 100644 --- a/ipc/ipc_test.mojom +++ b/ipc/ipc_test.mojom
@@ -39,3 +39,10 @@ interface AssociatedInterfaceVendor { GetTestInterface(associated SimpleTestDriver& interface_reqest); }; + +interface InterfacePassingTestDriver { + Init() => (); + GetPingReceiver(array<PingReceiver&> request) => (); + GetAssociatedPingReceiver(array<associated PingReceiver&> request) => (); + Quit(); +};
diff --git a/media/audio/alsa/audio_manager_alsa.cc b/media/audio/alsa/audio_manager_alsa.cc index 33fc0b2..5f5bc6d 100644 --- a/media/audio/alsa/audio_manager_alsa.cc +++ b/media/audio/alsa/audio_manager_alsa.cc
@@ -7,14 +7,10 @@ #include <stddef.h> #include "base/command_line.h" -#include "base/environment.h" -#include "base/files/file_path.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/free_deleter.h" #include "base/metrics/histogram.h" -#include "base/nix/xdg_util.h" -#include "base/process/launch.h" #include "base/stl_util.h" #include "media/audio/audio_device_description.h" #include "media/audio/audio_output_dispatcher.h" @@ -44,40 +40,10 @@ // real devices, we remove them from the list to avoiding duplicate counting. // In addition, note that we support no more than 2 channels for recording, // hence surround devices are not stored in the list. -static const char* kInvalidAudioInputDevices[] = { - "default", - "dmix", - "null", - "pulse", - "surround", +static const char* const kInvalidAudioInputDevices[] = { + "default", "dmix", "null", "pulse", "surround", }; -// static -void AudioManagerAlsa::ShowLinuxAudioInputSettings() { - std::unique_ptr<base::Environment> env(base::Environment::Create()); - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - switch (base::nix::GetDesktopEnvironment(env.get())) { - case base::nix::DESKTOP_ENVIRONMENT_GNOME: - command_line.SetProgram(base::FilePath("gnome-volume-control")); - break; - case base::nix::DESKTOP_ENVIRONMENT_KDE3: - case base::nix::DESKTOP_ENVIRONMENT_KDE4: - case base::nix::DESKTOP_ENVIRONMENT_KDE5: - command_line.SetProgram(base::FilePath("kmix")); - break; - case base::nix::DESKTOP_ENVIRONMENT_UNITY: - command_line.SetProgram(base::FilePath("gnome-control-center")); - command_line.AppendArg("sound"); - command_line.AppendArg("input"); - break; - default: - LOG(ERROR) << "Failed to show audio input settings: we don't know " - << "what command to use for your desktop environment."; - return; - } - base::LaunchProcess(command_line, base::LaunchOptions()); -} - AudioManagerAlsa::AudioManagerAlsa(std::unique_ptr<AudioThread> audio_thread, AudioLogFactory* audio_log_factory) : AudioManagerBase(std::move(audio_thread), audio_log_factory), @@ -95,10 +61,6 @@ return HasAnyAlsaAudioDevice(kStreamCapture); } -void AudioManagerAlsa::ShowAudioInputSettings() { - ShowLinuxAudioInputSettings(); -} - void AudioManagerAlsa::GetAudioInputDeviceNames( AudioDeviceNames* device_names) { DCHECK(device_names->empty()); @@ -219,17 +181,16 @@ return false; } return true; - } else { - DCHECK_EQ(kStreamPlayback, type); - // We prefer the device type that maps straight to hardware but - // goes through software conversion if needed (e.g. incompatible - // sample rate). - // TODO(joi): Should we prefer "hw" instead? - static const char kDeviceTypeDesired[] = "plughw"; - return strncmp(kDeviceTypeDesired, - device_name, - arraysize(kDeviceTypeDesired) - 1) == 0; } + + DCHECK_EQ(kStreamPlayback, type); + // We prefer the device type that maps straight to hardware but + // goes through software conversion if needed (e.g. incompatible + // sample rate). + // TODO(joi): Should we prefer "hw" instead? + static const char kDeviceTypeDesired[] = "plughw"; + return strncmp(kDeviceTypeDesired, device_name, + arraysize(kDeviceTypeDesired) - 1) == 0; } // static
diff --git a/media/audio/alsa/audio_manager_alsa.h b/media/audio/alsa/audio_manager_alsa.h index a5c57dc..ab146785 100644 --- a/media/audio/alsa/audio_manager_alsa.h +++ b/media/audio/alsa/audio_manager_alsa.h
@@ -24,12 +24,9 @@ AudioLogFactory* audio_log_factory); ~AudioManagerAlsa() override; - static void ShowLinuxAudioInputSettings(); - // Implementation of AudioManager. bool HasAudioOutputDevices() override; bool HasAudioInputDevices() override; - void ShowAudioInputSettings() override; void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override; void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override; AudioParameters GetInputStreamParameters(
diff --git a/media/audio/audio_manager.h b/media/audio/audio_manager.h index f91f6bd..bd98efa 100644 --- a/media/audio/audio_manager.h +++ b/media/audio/audio_manager.h
@@ -214,12 +214,6 @@ // input device for this computer. virtual base::string16 GetAudioInputDeviceModel() = 0; - // Opens the platform default audio input settings UI. - // Note: This could invoke an external application/preferences pane, so - // ideally must not be called from the UI thread or other time sensitive - // threads to avoid blocking the rest of the application. - virtual void ShowAudioInputSettings() = 0; - // Appends a list of available input devices to |device_descriptions|, // which must initially be empty. It is not guaranteed that all the // devices in the list support all formats and sample rates for
diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc index bddfe892..2c5739fb 100644 --- a/media/audio/audio_manager_base.cc +++ b/media/audio/audio_manager_base.cc
@@ -323,9 +323,6 @@ return output_dispatchers_.back()->dispatcher->CreateStreamProxy(); } -void AudioManagerBase::ShowAudioInputSettings() { -} - void AudioManagerBase::GetAudioInputDeviceNames( AudioDeviceNames* device_names) { }
diff --git a/media/audio/audio_manager_base.h b/media/audio/audio_manager_base.h index 8e2fc15b..b165d06 100644 --- a/media/audio/audio_manager_base.h +++ b/media/audio/audio_manager_base.h
@@ -107,7 +107,6 @@ // AudioManager: void ShutdownOnAudioThread() override; base::string16 GetAudioInputDeviceModel() override; - void ShowAudioInputSettings() override; void GetAudioInputDeviceDescriptions( AudioDeviceDescriptions* device_descriptions) final;
diff --git a/media/audio/audio_output_controller_unittest.cc b/media/audio/audio_output_controller_unittest.cc index 2919808..b61b48f 100644 --- a/media/audio/audio_output_controller_unittest.cc +++ b/media/audio/audio_output_controller_unittest.cc
@@ -212,7 +212,7 @@ void ReadDuplicatedAudioData(const std::vector<MockAudioPushSink*>& sinks) { for (size_t i = 0; i < sinks.size(); i++) { - EXPECT_CALL(*sinks[i], OnDataCheck(kBufferNonZeroData)); + EXPECT_CALL(*sinks[i], OnDataCheck(kBufferNonZeroData)).Times(AtLeast(1)); } std::unique_ptr<AudioBus> dest = AudioBus::Create(params_);
diff --git a/media/audio/audio_output_proxy_unittest.cc b/media/audio/audio_output_proxy_unittest.cc index bb137ed..5d93213 100644 --- a/media/audio/audio_output_proxy_unittest.cc +++ b/media/audio/audio_output_proxy_unittest.cc
@@ -140,7 +140,6 @@ MOCK_METHOD0(HasAudioOutputDevices, bool()); MOCK_METHOD0(HasAudioInputDevices, bool()); MOCK_METHOD0(GetAudioInputDeviceModel, base::string16()); - MOCK_METHOD0(ShowAudioInputSettings, void()); MOCK_METHOD1(GetAudioInputDeviceNames, void(media::AudioDeviceNames* device_name)); MOCK_METHOD2(GetPreferredOutputStreamParameters, AudioParameters(
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc index 1029ebe..9faa5e0 100644 --- a/media/audio/cras/audio_manager_cras.cc +++ b/media/audio/cras/audio_manager_cras.cc
@@ -165,10 +165,6 @@ AudioManagerCras::~AudioManagerCras() = default; -void AudioManagerCras::ShowAudioInputSettings() { - NOTIMPLEMENTED(); -} - void AudioManagerCras::GetAudioDeviceNamesImpl(bool is_input, AudioDeviceNames* device_names) { DCHECK(device_names->empty());
diff --git a/media/audio/cras/audio_manager_cras.h b/media/audio/cras/audio_manager_cras.h index 7cf1200..67aa4f0 100644 --- a/media/audio/cras/audio_manager_cras.h +++ b/media/audio/cras/audio_manager_cras.h
@@ -27,7 +27,6 @@ // AudioManager implementation. bool HasAudioOutputDevices() override; bool HasAudioInputDevices() override; - void ShowAudioInputSettings() override; void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override; void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override; AudioParameters GetInputStreamParameters(
diff --git a/media/audio/fuchsia/audio_manager_fuchsia.cc b/media/audio/fuchsia/audio_manager_fuchsia.cc index 661e681..7bc5d23 100644 --- a/media/audio/fuchsia/audio_manager_fuchsia.cc +++ b/media/audio/fuchsia/audio_manager_fuchsia.cc
@@ -26,10 +26,6 @@ return false; } -void AudioManagerFuchsia::ShowAudioInputSettings() { - NOTIMPLEMENTED(); -} - void AudioManagerFuchsia::GetAudioInputDeviceNames( AudioDeviceNames* device_names) { device_names->clear();
diff --git a/media/audio/fuchsia/audio_manager_fuchsia.h b/media/audio/fuchsia/audio_manager_fuchsia.h index 9ab3a17..7ce59254 100644 --- a/media/audio/fuchsia/audio_manager_fuchsia.h +++ b/media/audio/fuchsia/audio_manager_fuchsia.h
@@ -18,7 +18,6 @@ // Implementation of AudioManager. bool HasAudioOutputDevices() override; bool HasAudioInputDevices() override; - void ShowAudioInputSettings() override; void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override; void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override; AudioParameters GetInputStreamParameters(
diff --git a/media/audio/mock_audio_manager.cc b/media/audio/mock_audio_manager.cc index d05921c..74fe7fe 100644 --- a/media/audio/mock_audio_manager.cc +++ b/media/audio/mock_audio_manager.cc
@@ -34,9 +34,6 @@ return base::string16(); } -void MockAudioManager::ShowAudioInputSettings() { -} - void MockAudioManager::GetAudioInputDeviceDescriptions( AudioDeviceDescriptions* device_descriptions) { DCHECK(GetTaskRunner()->BelongsToCurrentThread());
diff --git a/media/audio/mock_audio_manager.h b/media/audio/mock_audio_manager.h index 18cc3c9..0d7b19e 100644 --- a/media/audio/mock_audio_manager.h +++ b/media/audio/mock_audio_manager.h
@@ -76,8 +76,6 @@ base::string16 GetAudioInputDeviceModel() override; - void ShowAudioInputSettings() override; - void GetAudioInputDeviceDescriptions( media::AudioDeviceDescriptions* device_descriptions) override;
diff --git a/media/audio/pulse/audio_manager_pulse.cc b/media/audio/pulse/audio_manager_pulse.cc index 6fa330f0..8cd8711 100644 --- a/media/audio/pulse/audio_manager_pulse.cc +++ b/media/audio/pulse/audio_manager_pulse.cc
@@ -9,9 +9,6 @@ #include "base/logging.h" #include "base/nix/xdg_util.h" #include "base/stl_util.h" -#if defined(USE_ALSA) -#include "media/audio/alsa/audio_manager_alsa.h" -#endif #include "media/audio/audio_device_description.h" #include "media/audio/pulse/pulse_input.h" #include "media/audio/pulse/pulse_output.h" @@ -70,12 +67,6 @@ return !devices.empty(); } -void AudioManagerPulse::ShowAudioInputSettings() { -#if defined(USE_ALSA) - AudioManagerAlsa::ShowLinuxAudioInputSettings(); -#endif -} - void AudioManagerPulse::GetAudioDeviceNames( bool input, media::AudioDeviceNames* device_names) { DCHECK(device_names->empty());
diff --git a/media/audio/pulse/audio_manager_pulse.h b/media/audio/pulse/audio_manager_pulse.h index bb1d1c0..316eec4 100644 --- a/media/audio/pulse/audio_manager_pulse.h +++ b/media/audio/pulse/audio_manager_pulse.h
@@ -26,7 +26,6 @@ // Implementation of AudioManager. bool HasAudioOutputDevices() override; bool HasAudioInputDevices() override; - void ShowAudioInputSettings() override; void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override; void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override; AudioParameters GetInputStreamParameters(
diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc index fa38c58d..0443071e 100644 --- a/media/audio/win/audio_manager_win.cc +++ b/media/audio/win/audio_manager_win.cc
@@ -16,11 +16,8 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/command_line.h" -#include "base/files/file_path.h" #include "base/message_loop/message_loop.h" #include "base/metrics/histogram_macros.h" -#include "base/path_service.h" -#include "base/process/launch.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/win/windows_version.h" @@ -237,15 +234,6 @@ return base::string16(); } -void AudioManagerWin::ShowAudioInputSettings() { - base::FilePath path; - PathService::Get(base::DIR_SYSTEM, &path); - path = path.Append(L"control.exe"); - base::CommandLine command_line(path); - command_line.AppendArg("mmsys.cpl,,1"); - base::LaunchProcess(command_line, base::LaunchOptions()); -} - void AudioManagerWin::GetAudioDeviceNamesImpl(bool input, AudioDeviceNames* device_names) { DCHECK(device_names->empty());
diff --git a/media/audio/win/audio_manager_win.h b/media/audio/win/audio_manager_win.h index da15a39f..3f65fe3d 100644 --- a/media/audio/win/audio_manager_win.h +++ b/media/audio/win/audio_manager_win.h
@@ -28,7 +28,6 @@ bool HasAudioOutputDevices() override; bool HasAudioInputDevices() override; base::string16 GetAudioInputDeviceModel() override; - void ShowAudioInputSettings() override; void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override; void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override; AudioParameters GetInputStreamParameters(
diff --git a/media/base/scoped_callback_runner.h b/media/base/scoped_callback_runner.h index 0a6227e..bbdfbef 100644 --- a/media/base/scoped_callback_runner.h +++ b/media/base/scoped_callback_runner.h
@@ -23,6 +23,14 @@ // ScopedCallbackRunner(base::BindOnce(&Foo::OnResult, this), false)); // // If the callback is destructed without running, it'll be run with "false". +// +// If you want to make sure a base::RepeatingCallback is always run, consider +// switching to use base::OnceCallback. If that is not possible, you can use +// ToOnceCallback() to convert it to a OnceCallback. +// +// Example: +// foo->DoWorkAndReturnResult( +// ScopedCallbackRunner(ToOnceCallback(repeating_cb), false)); namespace media { namespace internal { @@ -70,8 +78,6 @@ } // namespace internal -// Currently ScopedCallbackRunner only supports base::OnceCallback. If needed, -// we can easily add a specialization to support base::RepeatingCallback too. template <typename T, typename... Args> inline base::OnceCallback<T> ScopedCallbackRunner(base::OnceCallback<T> cb, Args&&... args) { @@ -81,6 +87,13 @@ std::move(cb), std::forward<Args>(args)...)); } +// Converts a repeating callback to a once callback with the same signature so +// that it can be used with ScopedCallbackRunner. +template <typename T> +base::OnceCallback<T> ToOnceCallback(const base::RepeatingCallback<T>& cb) { + return static_cast<base::OnceCallback<T>>(cb); +} + } // namespace media #endif // MEDIA_BASE_SCOPED_CALLBACK_RUNNER_H_
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc index 126f496..4ff5fb8 100644 --- a/media/base/video_frame.cc +++ b/media/base/video_frame.cc
@@ -641,6 +641,19 @@ return !mailbox_holders_[0].mailbox.IsZero(); } +size_t VideoFrame::NumTextures() const { + if (!HasTextures()) + return 0; + + size_t i = 0; + for (; i < NumPlanes(format_); ++i) { + if (mailbox_holders_[i].mailbox.IsZero()) { + return i; + } + } + return i; +} + gfx::ColorSpace VideoFrame::ColorSpace() const { if (color_space_ == gfx::ColorSpace()) { int videoframe_color_space;
diff --git a/media/base/video_frame.h b/media/base/video_frame.h index dae64a2..a61cce26 100644 --- a/media/base/video_frame.h +++ b/media/base/video_frame.h
@@ -295,6 +295,9 @@ // accessed via data(), visible_data() etc. bool HasTextures() const; + // Returns the number of native textures. + size_t NumTextures() const; + // Returns the color space of this frame's content. gfx::ColorSpace ColorSpace() const; void set_color_space(const gfx::ColorSpace& color_space);
diff --git a/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc b/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc index 232c333..e98c8e2e 100644 --- a/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc +++ b/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc
@@ -699,8 +699,12 @@ DVLOG(1) << __func__; // Trigger a crash on purpose for testing purpose. - if (key_system_ == kExternalClearKeyCrashKeySystem) + // Only do this after a session has been created since the test also checks + // that the session is properly closed. + if (!last_session_id_.empty() && + key_system_ == kExternalClearKeyCrashKeySystem) { CHECK(false); + } scoped_refptr<media::DecoderBuffer> buffer; cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer);
diff --git a/media/gpu/android/codec_image_unittest.cc b/media/gpu/android/codec_image_unittest.cc index 05cf00e..d0f362e 100644 --- a/media/gpu/android/codec_image_unittest.cc +++ b/media/gpu/android/codec_image_unittest.cc
@@ -75,7 +75,7 @@ ImageKind kind, CodecImage::DestructionCb destruction_cb = kNoop) { std::unique_ptr<CodecOutputBuffer> buffer; - wrapper_->DequeueOutputBuffer(base::TimeDelta(), nullptr, nullptr, &buffer); + wrapper_->DequeueOutputBuffer(nullptr, nullptr, &buffer); return new CodecImage(std::move(buffer), kind == kSurfaceTexture ? surface_texture_ : nullptr, std::move(destruction_cb));
diff --git a/media/gpu/android/codec_wrapper.cc b/media/gpu/android/codec_wrapper.cc index 398a156..4dce5a3 100644 --- a/media/gpu/android/codec_wrapper.cc +++ b/media/gpu/android/codec_wrapper.cc
@@ -47,9 +47,8 @@ const EncryptionScheme& encryption_scheme, base::TimeDelta presentation_time); void QueueEOS(int input_buffer_index); - MediaCodecStatus DequeueInputBuffer(base::TimeDelta timeout, int* index); + MediaCodecStatus DequeueInputBuffer(int* index); MediaCodecStatus DequeueOutputBuffer( - base::TimeDelta timeout, base::TimeDelta* presentation_time, bool* end_of_stream, std::unique_ptr<CodecOutputBuffer>* codec_buffer); @@ -237,19 +236,17 @@ state_ = State::kDraining; } -MediaCodecStatus CodecWrapperImpl::DequeueInputBuffer(base::TimeDelta timeout, - int* index) { +MediaCodecStatus CodecWrapperImpl::DequeueInputBuffer(int* index) { DVLOG(4) << __func__; base::AutoLock l(lock_); DCHECK(codec_ && state_ != State::kError); - auto status = codec_->DequeueInputBuffer(timeout, index); + auto status = codec_->DequeueInputBuffer(base::TimeDelta(), index); if (status == MEDIA_CODEC_ERROR) state_ = State::kError; return status; } MediaCodecStatus CodecWrapperImpl::DequeueOutputBuffer( - base::TimeDelta timeout, base::TimeDelta* presentation_time, bool* end_of_stream, std::unique_ptr<CodecOutputBuffer>* codec_buffer) { @@ -267,9 +264,9 @@ size_t unused_offset = 0; size_t unused_size = 0; bool* unused_key_frame = nullptr; - auto status = codec_->DequeueOutputBuffer(timeout, &index, &unused_offset, - &unused_size, presentation_time, - end_of_stream, unused_key_frame); + auto status = codec_->DequeueOutputBuffer( + base::TimeDelta(), &index, &unused_offset, &unused_size, + presentation_time, end_of_stream, unused_key_frame); switch (status) { case MEDIA_CODEC_OK: { if (end_of_stream && *end_of_stream) @@ -409,17 +406,15 @@ impl_->QueueEOS(input_buffer_index); } -MediaCodecStatus CodecWrapper::DequeueInputBuffer(base::TimeDelta timeout, - int* index) { - return impl_->DequeueInputBuffer(timeout, index); +MediaCodecStatus CodecWrapper::DequeueInputBuffer(int* index) { + return impl_->DequeueInputBuffer(index); } MediaCodecStatus CodecWrapper::DequeueOutputBuffer( - base::TimeDelta timeout, base::TimeDelta* presentation_time, bool* end_of_stream, std::unique_ptr<CodecOutputBuffer>* codec_buffer) { - return impl_->DequeueOutputBuffer(timeout, presentation_time, end_of_stream, + return impl_->DequeueOutputBuffer(presentation_time, end_of_stream, codec_buffer); }
diff --git a/media/gpu/android/codec_wrapper.h b/media/gpu/android/codec_wrapper.h index 64f31e2..5207934 100644 --- a/media/gpu/android/codec_wrapper.h +++ b/media/gpu/android/codec_wrapper.h
@@ -112,7 +112,7 @@ const EncryptionScheme& encryption_scheme, base::TimeDelta presentation_time); void QueueEOS(int input_buffer_index); - MediaCodecStatus DequeueInputBuffer(base::TimeDelta timeout, int* index); + MediaCodecStatus DequeueInputBuffer(int* index); // Like MediaCodecBridge::DequeueOutputBuffer() but it outputs a // CodecOutputBuffer instead of an index. And it's guaranteed to not return @@ -120,7 +120,6 @@ // MEDIA_CODEC_OUTPUT_FORMAT_CHANGED. It will try to dequeue another // buffer instead. |*codec_buffer| must be null. MediaCodecStatus DequeueOutputBuffer( - base::TimeDelta timeout, base::TimeDelta* presentation_time, bool* end_of_stream, std::unique_ptr<CodecOutputBuffer>* codec_buffer);
diff --git a/media/gpu/android/codec_wrapper_unittest.cc b/media/gpu/android/codec_wrapper_unittest.cc index e0b77f8d..a666999d 100644 --- a/media/gpu/android/codec_wrapper_unittest.cc +++ b/media/gpu/android/codec_wrapper_unittest.cc
@@ -46,8 +46,7 @@ std::unique_ptr<CodecOutputBuffer> DequeueCodecOutputBuffer() { std::unique_ptr<CodecOutputBuffer> codec_buffer; bool eos = false; - wrapper_->DequeueOutputBuffer(base::TimeDelta(), nullptr, &eos, - &codec_buffer); + wrapper_->DequeueOutputBuffer(nullptr, &eos, &codec_buffer); return codec_buffer; } @@ -166,8 +165,7 @@ .WillOnce(Return(MEDIA_CODEC_OUTPUT_FORMAT_CHANGED)) .WillOnce(Return(MEDIA_CODEC_TRY_AGAIN_LATER)); std::unique_ptr<CodecOutputBuffer> codec_buffer; - auto status = wrapper_->DequeueOutputBuffer(base::TimeDelta(), nullptr, - nullptr, &codec_buffer); + auto status = wrapper_->DequeueOutputBuffer(nullptr, nullptr, &codec_buffer); ASSERT_EQ(status, MEDIA_CODEC_TRY_AGAIN_LATER); } @@ -176,8 +174,7 @@ .WillOnce(Return(MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED)) .WillOnce(Return(MEDIA_CODEC_TRY_AGAIN_LATER)); std::unique_ptr<CodecOutputBuffer> codec_buffer; - auto status = wrapper_->DequeueOutputBuffer(base::TimeDelta(), nullptr, - nullptr, &codec_buffer); + auto status = wrapper_->DequeueOutputBuffer(nullptr, nullptr, &codec_buffer); ASSERT_EQ(status, MEDIA_CODEC_TRY_AGAIN_LATER); } @@ -185,8 +182,7 @@ EXPECT_CALL(*codec_, DequeueOutputBuffer(_, _, _, _, _, _, _)) .WillRepeatedly(Return(MEDIA_CODEC_OUTPUT_FORMAT_CHANGED)); std::unique_ptr<CodecOutputBuffer> codec_buffer; - auto status = wrapper_->DequeueOutputBuffer(base::TimeDelta(), nullptr, - nullptr, &codec_buffer); + auto status = wrapper_->DequeueOutputBuffer(nullptr, nullptr, &codec_buffer); ASSERT_EQ(status, MEDIA_CODEC_ERROR); }
diff --git a/media/gpu/android/media_codec_video_decoder.cc b/media/gpu/android/media_codec_video_decoder.cc index 7d38680..ef9e49db 100644 --- a/media/gpu/android/media_codec_video_decoder.cc +++ b/media/gpu/android/media_codec_video_decoder.cc
@@ -419,8 +419,7 @@ return false; int input_buffer = -1; - MediaCodecStatus status = - codec_->DequeueInputBuffer(base::TimeDelta(), &input_buffer); + MediaCodecStatus status = codec_->DequeueInputBuffer(&input_buffer); if (status == MEDIA_CODEC_ERROR) { DVLOG(1) << "DequeueInputBuffer() error"; HandleError(); @@ -480,8 +479,8 @@ base::TimeDelta presentation_time; bool eos = false; std::unique_ptr<CodecOutputBuffer> output_buffer; - MediaCodecStatus status = codec_->DequeueOutputBuffer( - base::TimeDelta(), &presentation_time, &eos, &output_buffer); + MediaCodecStatus status = + codec_->DequeueOutputBuffer(&presentation_time, &eos, &output_buffer); if (status == MEDIA_CODEC_ERROR) { DVLOG(1) << "DequeueOutputBuffer() error"; HandleError();
diff --git a/media/gpu/vaapi_wrapper.cc b/media/gpu/vaapi_wrapper.cc index 0739e56..97ed997 100644 --- a/media/gpu/vaapi_wrapper.cc +++ b/media/gpu/vaapi_wrapper.cc
@@ -548,7 +548,7 @@ VA_LOG_ON_ERROR(va_res, "vaCreateContext failed"); if (va_res != VA_STATUS_SUCCESS) { - DestroySurfaces(); + DestroySurfaces_Locked(); return false; } @@ -561,6 +561,12 @@ base::AutoLock auto_lock(*va_lock_); DVLOG(2) << "Destroying " << va_surface_ids_.size() << " surfaces"; + DestroySurfaces_Locked(); +} + +void VaapiWrapper::DestroySurfaces_Locked() { + va_lock_->AssertAcquired(); + if (va_context_id_ != VA_INVALID_ID) { VAStatus va_res = vaDestroyContext(va_display_, va_context_id_); VA_LOG_ON_ERROR(va_res, "vaDestroyContext failed");
diff --git a/media/gpu/vaapi_wrapper.h b/media/gpu/vaapi_wrapper.h index 22c7feb..dade7161 100644 --- a/media/gpu/vaapi_wrapper.h +++ b/media/gpu/vaapi_wrapper.h
@@ -281,6 +281,9 @@ bool VaInitialize(const base::Closure& report_error_to_uma_cb); bool GetSupportedVaProfiles(std::vector<VAProfile>* profiles); + // Free all memory allocated in CreateSurfaces. + void DestroySurfaces_Locked(); + // Check if |va_profile| supports |entrypoint| or not. |va_lock_| must be // held on entry. bool IsEntrypointSupported_Locked(VAProfile va_profile,
diff --git a/media/mojo/clients/mojo_cdm.cc b/media/mojo/clients/mojo_cdm.cc index 5639adf..d227b5b 100644 --- a/media/mojo/clients/mojo_cdm.cc +++ b/media/mojo/clients/mojo_cdm.cc
@@ -280,7 +280,6 @@ if (!decryptor_task_runner_) decryptor_task_runner_ = base::ThreadTaskRunnerHandle::Get(); - DCHECK(decryptor_task_runner_->BelongsToCurrentThread()); // Can be called on a different thread.
diff --git a/media/mojo/clients/mojo_cdm_factory.cc b/media/mojo/clients/mojo_cdm_factory.cc index 408fdad..91d140d 100644 --- a/media/mojo/clients/mojo_cdm_factory.cc +++ b/media/mojo/clients/mojo_cdm_factory.cc
@@ -13,15 +13,15 @@ #include "media/cdm/aes_decryptor.h" #include "media/mojo/clients/mojo_cdm.h" #include "media/mojo/features.h" -#include "services/service_manager/public/cpp/connect.h" -#include "services/service_manager/public/interfaces/interface_provider.mojom.h" +#include "media/mojo/interfaces/interface_factory.mojom.h" +#include "mojo/public/cpp/bindings/interface_request.h" namespace media { MojoCdmFactory::MojoCdmFactory( - service_manager::mojom::InterfaceProvider* interface_provider) - : interface_provider_(interface_provider) { - DCHECK(interface_provider_); + media::mojom::InterfaceFactory* interface_factory) + : interface_factory_(interface_factory) { + DCHECK(interface_factory_); } MojoCdmFactory::~MojoCdmFactory() {} @@ -60,8 +60,7 @@ #endif mojom::ContentDecryptionModulePtr cdm_ptr; - service_manager::GetInterface<mojom::ContentDecryptionModule>( - interface_provider_, &cdm_ptr); + interface_factory_->CreateCdm(mojo::MakeRequest(&cdm_ptr)); MojoCdm::Create(key_system, security_origin, cdm_config, std::move(cdm_ptr), session_message_cb, session_closed_cb, session_keys_change_cb,
diff --git a/media/mojo/clients/mojo_cdm_factory.h b/media/mojo/clients/mojo_cdm_factory.h index 41561623..d53987f0 100644 --- a/media/mojo/clients/mojo_cdm_factory.h +++ b/media/mojo/clients/mojo_cdm_factory.h
@@ -8,18 +8,15 @@ #include "base/macros.h" #include "media/base/cdm_factory.h" -namespace service_manager { -namespace mojom { -class InterfaceProvider; -} -} - namespace media { +namespace mojom { +class InterfaceFactory; +} + class MojoCdmFactory : public CdmFactory { public: - explicit MojoCdmFactory( - service_manager::mojom::InterfaceProvider* interface_provider); + explicit MojoCdmFactory(media::mojom::InterfaceFactory* interface_factory); ~MojoCdmFactory() final; // CdmFactory implementation. @@ -33,7 +30,7 @@ const CdmCreatedCB& cdm_created_cb) final; private: - service_manager::mojom::InterfaceProvider* interface_provider_; + media::mojom::InterfaceFactory* interface_factory_; DISALLOW_COPY_AND_ASSIGN(MojoCdmFactory); };
diff --git a/media/mojo/clients/mojo_decoder_factory.cc b/media/mojo/clients/mojo_decoder_factory.cc index 1a9e6e8b..bd80141 100644 --- a/media/mojo/clients/mojo_decoder_factory.cc +++ b/media/mojo/clients/mojo_decoder_factory.cc
@@ -10,14 +10,15 @@ #include "media/mojo/clients/mojo_video_decoder.h" #include "media/mojo/features.h" #include "media/mojo/interfaces/audio_decoder.mojom.h" -#include "services/service_manager/public/cpp/connect.h" +#include "media/mojo/interfaces/interface_factory.mojom.h" +#include "mojo/public/cpp/bindings/interface_request.h" namespace media { MojoDecoderFactory::MojoDecoderFactory( - service_manager::mojom::InterfaceProvider* interface_provider) - : interface_provider_(interface_provider) { - DCHECK(interface_provider_); + media::mojom::InterfaceFactory* interface_factory) + : interface_factory_(interface_factory) { + DCHECK(interface_factory_); } MojoDecoderFactory::~MojoDecoderFactory() {} @@ -27,8 +28,7 @@ std::vector<std::unique_ptr<AudioDecoder>>* audio_decoders) { #if BUILDFLAG(ENABLE_MOJO_AUDIO_DECODER) mojom::AudioDecoderPtr audio_decoder_ptr; - service_manager::GetInterface<mojom::AudioDecoder>(interface_provider_, - &audio_decoder_ptr); + interface_factory_->CreateAudioDecoder(mojo::MakeRequest(&audio_decoder_ptr)); audio_decoders->push_back(base::MakeUnique<MojoAudioDecoder>( task_runner, std::move(audio_decoder_ptr))); @@ -41,11 +41,11 @@ MediaLog* media_log, std::vector<std::unique_ptr<VideoDecoder>>* video_decoders) { #if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) - mojom::VideoDecoderPtr remote_decoder; - service_manager::GetInterface<mojom::VideoDecoder>(interface_provider_, - &remote_decoder); + mojom::VideoDecoderPtr video_decoder_ptr; + interface_factory_->CreateVideoDecoder(mojo::MakeRequest(&video_decoder_ptr)); + video_decoders->push_back(base::MakeUnique<MojoVideoDecoder>( - task_runner, gpu_factories, media_log, std::move(remote_decoder))); + task_runner, gpu_factories, media_log, std::move(video_decoder_ptr))); #endif }
diff --git a/media/mojo/clients/mojo_decoder_factory.h b/media/mojo/clients/mojo_decoder_factory.h index cd6725ed..37b32dc5 100644 --- a/media/mojo/clients/mojo_decoder_factory.h +++ b/media/mojo/clients/mojo_decoder_factory.h
@@ -8,14 +8,17 @@ #include "base/macros.h" #include "base/single_thread_task_runner.h" #include "media/base/decoder_factory.h" -#include "services/service_manager/public/interfaces/interface_provider.mojom.h" namespace media { +namespace mojom { +class InterfaceFactory; +} + class MojoDecoderFactory : public DecoderFactory { public: explicit MojoDecoderFactory( - service_manager::mojom::InterfaceProvider* interface_provider); + media::mojom::InterfaceFactory* interface_factory); ~MojoDecoderFactory() final; void CreateAudioDecoders( @@ -29,7 +32,7 @@ std::vector<std::unique_ptr<VideoDecoder>>* video_decoders) final; private: - service_manager::mojom::InterfaceProvider* interface_provider_; + media::mojom::InterfaceFactory* interface_factory_; DISALLOW_COPY_AND_ASSIGN(MojoDecoderFactory); };
diff --git a/media/mojo/clients/mojo_decryptor.cc b/media/mojo/clients/mojo_decryptor.cc index 7baecf4c..60c6b6c6 100644 --- a/media/mojo/clients/mojo_decryptor.cc +++ b/media/mojo/clients/mojo_decryptor.cc
@@ -13,6 +13,7 @@ #include "base/numerics/safe_conversions.h" #include "media/base/audio_buffer.h" #include "media/base/decoder_buffer.h" +#include "media/base/scoped_callback_runner.h" #include "media/base/video_frame.h" #include "media/mojo/common/media_type_converters.h" #include "media/mojo/common/mojo_decoder_buffer_converter.h" @@ -86,8 +87,9 @@ remote_decryptor_->Decrypt( stream_type, std::move(mojo_buffer), - base::Bind(&MojoDecryptor::OnBufferDecrypted, weak_factory_.GetWeakPtr(), - decrypt_cb)); + base::BindOnce( + &MojoDecryptor::OnBufferDecrypted, weak_factory_.GetWeakPtr(), + ScopedCallbackRunner(ToOnceCallback(decrypt_cb), kError, nullptr))); } void MojoDecryptor::CancelDecrypt(StreamType stream_type) { @@ -102,7 +104,8 @@ DVLOG(1) << __func__; DCHECK(thread_checker_.CalledOnValidThread()); - remote_decryptor_->InitializeAudioDecoder(config, init_cb); + remote_decryptor_->InitializeAudioDecoder( + config, ScopedCallbackRunner(ToOnceCallback(init_cb), false)); } void MojoDecryptor::InitializeVideoDecoder(const VideoDecoderConfig& config, @@ -110,7 +113,8 @@ DVLOG(1) << __func__; DCHECK(thread_checker_.CalledOnValidThread()); - remote_decryptor_->InitializeVideoDecoder(config, init_cb); + remote_decryptor_->InitializeVideoDecoder( + config, ScopedCallbackRunner(ToOnceCallback(init_cb), false)); } void MojoDecryptor::DecryptAndDecodeAudio( @@ -128,8 +132,9 @@ remote_decryptor_->DecryptAndDecodeAudio( std::move(mojo_buffer), - base::Bind(&MojoDecryptor::OnAudioDecoded, weak_factory_.GetWeakPtr(), - audio_decode_cb)); + base::BindOnce(&MojoDecryptor::OnAudioDecoded, weak_factory_.GetWeakPtr(), + ScopedCallbackRunner(ToOnceCallback(audio_decode_cb), + kError, AudioFrames()))); } void MojoDecryptor::DecryptAndDecodeVideo( @@ -147,8 +152,9 @@ remote_decryptor_->DecryptAndDecodeVideo( std::move(mojo_buffer), - base::Bind(&MojoDecryptor::OnVideoDecoded, weak_factory_.GetWeakPtr(), - video_decode_cb)); + base::BindOnce(&MojoDecryptor::OnVideoDecoded, weak_factory_.GetWeakPtr(), + ScopedCallbackRunner(ToOnceCallback(video_decode_cb), + kError, nullptr))); } void MojoDecryptor::ResetDecoder(StreamType stream_type) { @@ -176,7 +182,7 @@ new_video_key_cb_.Run(); } -void MojoDecryptor::OnBufferDecrypted(const DecryptCB& decrypt_cb, +void MojoDecryptor::OnBufferDecrypted(DecryptOnceCB decrypt_cb, Status status, mojom::DecoderBufferPtr buffer) { DVLOG_IF(1, status != kSuccess) << __func__ << "(" << status << ")"; @@ -184,29 +190,29 @@ DCHECK(thread_checker_.CalledOnValidThread()); if (buffer.is_null()) { - decrypt_cb.Run(status, nullptr); + std::move(decrypt_cb).Run(status, nullptr); return; } mojo_decoder_buffer_reader_->ReadDecoderBuffer( std::move(buffer), base::BindOnce(&MojoDecryptor::OnBufferRead, weak_factory_.GetWeakPtr(), - decrypt_cb, status)); + std::move(decrypt_cb), status)); } -void MojoDecryptor::OnBufferRead(const DecryptCB& decrypt_cb, +void MojoDecryptor::OnBufferRead(DecryptOnceCB decrypt_cb, Status status, scoped_refptr<DecoderBuffer> buffer) { if (!buffer) { - decrypt_cb.Run(kError, nullptr); + std::move(decrypt_cb).Run(kError, nullptr); return; } - decrypt_cb.Run(status, buffer); + std::move(decrypt_cb).Run(status, buffer); } void MojoDecryptor::OnAudioDecoded( - const AudioDecodeCB& audio_decode_cb, + AudioDecodeOnceCB audio_decode_cb, Status status, std::vector<mojom::AudioBufferPtr> audio_buffers) { DVLOG_IF(1, status != kSuccess) << __func__ << "(" << status << ")"; @@ -217,10 +223,10 @@ for (size_t i = 0; i < audio_buffers.size(); ++i) audio_frames.push_back(audio_buffers[i].To<scoped_refptr<AudioBuffer>>()); - audio_decode_cb.Run(status, audio_frames); + std::move(audio_decode_cb).Run(status, audio_frames); } -void MojoDecryptor::OnVideoDecoded(const VideoDecodeCB& video_decode_cb, +void MojoDecryptor::OnVideoDecoded(VideoDecodeOnceCB video_decode_cb, Status status, const scoped_refptr<VideoFrame>& video_frame, mojom::FrameResourceReleaserPtr releaser) { @@ -235,7 +241,7 @@ base::Bind(&ReleaseFrameResource, base::Passed(&releaser))); } - video_decode_cb.Run(status, video_frame); + std::move(video_decode_cb).Run(status, video_frame); } } // namespace media
diff --git a/media/mojo/clients/mojo_decryptor.h b/media/mojo/clients/mojo_decryptor.h index e51ba71..c8484bf 100644 --- a/media/mojo/clients/mojo_decryptor.h +++ b/media/mojo/clients/mojo_decryptor.h
@@ -51,17 +51,28 @@ void OnKeyAdded(); private: + // These are once callbacks corresponding to repeating callbacks DecryptCB, + // DecoderInitCB, AudioDecodeCB and VideoDecodeCB. They are needed so that we + // can use ScopedCallbackRunner to make sure callbacks always run. + // TODO(xhwang): Update Decryptor to use OnceCallback. The change is easy, + // but updating tests is hard given gmock doesn't support move-only types. + // See http://crbug.com/751838 + using DecryptOnceCB = base::OnceCallback<DecryptCB::RunType>; + using DecoderInitOnceCB = base::OnceCallback<DecoderInitCB::RunType>; + using AudioDecodeOnceCB = base::OnceCallback<AudioDecodeCB::RunType>; + using VideoDecodeOnceCB = base::OnceCallback<VideoDecodeCB::RunType>; + // Called when a buffer is decrypted. - void OnBufferDecrypted(const DecryptCB& decrypt_cb, + void OnBufferDecrypted(DecryptOnceCB decrypt_cb, Status status, mojom::DecoderBufferPtr buffer); - void OnBufferRead(const DecryptCB& decrypt_cb, + void OnBufferRead(DecryptOnceCB decrypt_cb, Status status, scoped_refptr<DecoderBuffer> buffer); - void OnAudioDecoded(const AudioDecodeCB& audio_decode_cb, + void OnAudioDecoded(AudioDecodeOnceCB audio_decode_cb, Status status, std::vector<mojom::AudioBufferPtr> audio_buffers); - void OnVideoDecoded(const VideoDecodeCB& video_decode_cb, + void OnVideoDecoded(VideoDecodeOnceCB video_decode_cb, Status status, const scoped_refptr<VideoFrame>& video_frame, mojom::FrameResourceReleaserPtr releaser);
diff --git a/media/mojo/clients/mojo_renderer_factory.cc b/media/mojo/clients/mojo_renderer_factory.cc index a63947c..a9ae33b 100644 --- a/media/mojo/clients/mojo_renderer_factory.cc +++ b/media/mojo/clients/mojo_renderer_factory.cc
@@ -7,7 +7,9 @@ #include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "media/mojo/clients/mojo_renderer.h" +#include "media/mojo/interfaces/interface_factory.mojom.h" #include "media/renderers/video_overlay_factory.h" +#include "mojo/public/cpp/bindings/interface_request.h" #include "services/service_manager/public/cpp/connect.h" #include "services/service_manager/public/interfaces/interface_provider.mojom.h" @@ -15,10 +17,20 @@ MojoRendererFactory::MojoRendererFactory( const GetGpuFactoriesCB& get_gpu_factories_cb, + media::mojom::InterfaceFactory* interface_factory) + : get_gpu_factories_cb_(get_gpu_factories_cb), + interface_factory_(interface_factory) { + DCHECK(interface_factory_); + DCHECK(!interface_provider_); +} + +MojoRendererFactory::MojoRendererFactory( + const GetGpuFactoriesCB& get_gpu_factories_cb, service_manager::mojom::InterfaceProvider* interface_provider) : get_gpu_factories_cb_(get_gpu_factories_cb), interface_provider_(interface_provider) { DCHECK(interface_provider_); + DCHECK(!interface_factory_); } MojoRendererFactory::~MojoRendererFactory() {} @@ -38,13 +50,25 @@ base::MakeUnique<VideoOverlayFactory>(get_gpu_factories_cb_.Run()); } - mojom::RendererPtr renderer_ptr; - service_manager::GetInterface<mojom::Renderer>(interface_provider_, - &renderer_ptr); - return std::unique_ptr<Renderer>( new MojoRenderer(media_task_runner, std::move(overlay_factory), - video_renderer_sink, std::move(renderer_ptr))); + video_renderer_sink, GetRendererPtr())); +} + +mojom::RendererPtr MojoRendererFactory::GetRendererPtr() { + mojom::RendererPtr renderer_ptr; + + if (interface_factory_) { + interface_factory_->CreateRenderer(std::string(), + mojo::MakeRequest(&renderer_ptr)); + } else if (interface_provider_) { + service_manager::GetInterface<mojom::Renderer>(interface_provider_, + &renderer_ptr); + } else { + NOTREACHED(); + } + + return renderer_ptr; } } // namespace media
diff --git a/media/mojo/clients/mojo_renderer_factory.h b/media/mojo/clients/mojo_renderer_factory.h index 4990dcb1..c4a4cd2 100644 --- a/media/mojo/clients/mojo_renderer_factory.h +++ b/media/mojo/clients/mojo_renderer_factory.h
@@ -19,6 +19,10 @@ namespace media { +namespace mojom { +class InterfaceFactory; +} + class GpuVideoAcceleratorFactories; // The default factory class for creating MojoRenderer. @@ -26,9 +30,12 @@ public: using GetGpuFactoriesCB = base::Callback<GpuVideoAcceleratorFactories*()>; + MojoRendererFactory(const GetGpuFactoriesCB& get_gpu_factories_cb, + media::mojom::InterfaceFactory* interface_factory); MojoRendererFactory( const GetGpuFactoriesCB& get_gpu_factories_cb, service_manager::mojom::InterfaceProvider* interface_provider); + ~MojoRendererFactory() final; std::unique_ptr<Renderer> CreateRenderer( @@ -39,8 +46,14 @@ const RequestOverlayInfoCB& request_overlay_info_cb) final; private: + mojom::RendererPtr GetRendererPtr(); + GetGpuFactoriesCB get_gpu_factories_cb_; - service_manager::mojom::InterfaceProvider* interface_provider_; + + // InterfaceFactory or InterfaceProvider used to create or connect to remote + // renderer. + media::mojom::InterfaceFactory* interface_factory_ = nullptr; + service_manager::mojom::InterfaceProvider* interface_provider_ = nullptr; DISALLOW_COPY_AND_ASSIGN(MojoRendererFactory); };
diff --git a/media/remoting/renderer_controller_unittest.cc b/media/remoting/renderer_controller_unittest.cc index 77e80da..5358f661 100644 --- a/media/remoting/renderer_controller_unittest.cc +++ b/media/remoting/renderer_controller_unittest.cc
@@ -9,6 +9,7 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/test/simple_test_tick_clock.h" +#include "build/build_config.h" #include "media/base/audio_decoder_config.h" #include "media/base/cdm_config.h" #include "media/base/limits.h" @@ -274,6 +275,8 @@ ExpectInLocalRendering(); } +#if !defined(OS_ANDROID) + TEST_F(RendererControllerTest, WithVP9VideoCodec) { const scoped_refptr<SharedSession> shared_session = FakeRemoterFactory::CreateSharedSession(false); @@ -383,6 +386,8 @@ ExpectInRemoting(); // All requirements now satisfied. } +#endif // OS_ANDROID + TEST_F(RendererControllerTest, StartFailed) { const scoped_refptr<SharedSession> shared_session = FakeRemoterFactory::CreateSharedSession(true);
diff --git a/media/remoting/shared_session.cc b/media/remoting/shared_session.cc index b3909038..bd48b07 100644 --- a/media/remoting/shared_session.cc +++ b/media/remoting/shared_session.cc
@@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/logging.h" +#include "build/build_config.h" #include "build/buildflag.h" #include "media/media_features.h" @@ -40,16 +41,24 @@ bool SharedSession::HasVideoCapability( mojom::RemotingSinkVideoCapability capability) const { +#if defined(OS_ANDROID) + return true; +#else return std::find(std::begin(sink_metadata_.video_capabilities), std::end(sink_metadata_.video_capabilities), capability) != std::end(sink_metadata_.video_capabilities); +#endif } bool SharedSession::HasAudioCapability( mojom::RemotingSinkAudioCapability capability) const { +#if defined(OS_ANDROID) + return true; +#else return std::find(std::begin(sink_metadata_.audio_capabilities), std::end(sink_metadata_.audio_capabilities), capability) != std::end(sink_metadata_.audio_capabilities); +#endif } bool SharedSession::HasFeatureCapability(
diff --git a/media/renderers/skcanvas_video_renderer.cc b/media/renderers/skcanvas_video_renderer.cc index f42a114..fc09ade 100644 --- a/media/renderers/skcanvas_video_renderer.cc +++ b/media/renderers/skcanvas_video_renderer.cc
@@ -831,21 +831,27 @@ // value down to get the expected result. // "flip_y == true" means to reverse the video orientation while // "flip_y == false" means to keep the intrinsic orientation. - - // Must reallocate the destination texture and copy only a sub-portion. - gfx::Rect dest_rect = video_frame->visible_rect(); + if (video_frame->visible_rect().size() != video_frame->coded_size()) { + // Must reallocate the destination texture and copy only a sub-portion. + gfx::Rect dest_rect = video_frame->visible_rect(); #if DCHECK_IS_ON() - // There should always be enough data in the source texture to - // cover this copy. - DCHECK_LE(dest_rect.width(), video_frame->coded_size().width()); - DCHECK_LE(dest_rect.height(), video_frame->coded_size().height()); + // There should always be enough data in the source texture to + // cover this copy. + DCHECK_LE(dest_rect.width(), video_frame->coded_size().width()); + DCHECK_LE(dest_rect.height(), video_frame->coded_size().height()); #endif - gl->TexImage2D(target, level, internal_format, dest_rect.width(), - dest_rect.height(), 0, format, type, nullptr); - gl->CopySubTextureCHROMIUM(source_texture, 0, target, texture, level, 0, 0, - dest_rect.x(), dest_rect.y(), dest_rect.width(), - dest_rect.height(), flip_y, premultiply_alpha, - false); + gl->TexImage2D(target, level, internal_format, dest_rect.width(), + dest_rect.height(), 0, format, type, nullptr); + gl->CopySubTextureCHROMIUM(source_texture, 0, target, texture, level, 0, 0, + dest_rect.x(), dest_rect.y(), dest_rect.width(), + dest_rect.height(), flip_y, premultiply_alpha, + false); + + } else { + gl->CopyTextureCHROMIUM(source_texture, 0, target, texture, level, + internal_format, type, flip_y, premultiply_alpha, + false); + } gl->DeleteTextures(1, &source_texture); gl->Flush(); @@ -903,21 +909,9 @@ destination_gl->CreateAndConsumeTextureCHROMIUM( mailbox_holder.texture_target, mailbox_holder.mailbox.name); - // Reallocate destination texture and copy only valid region. - gfx::Rect dest_rect = video_frame->visible_rect(); -#if DCHECK_IS_ON() - // There should always be enough data in the source texture to - // cover this copy. - DCHECK_LE(dest_rect.width(), video_frame->coded_size().width()); - DCHECK_LE(dest_rect.height(), video_frame->coded_size().height()); -#endif - destination_gl->TexImage2D(target, level, internal_format, - dest_rect.width(), dest_rect.height(), 0, format, - type, nullptr); - destination_gl->CopySubTextureCHROMIUM( - intermediate_texture, 0, target, texture, level, 0, 0, dest_rect.x(), - dest_rect.y(), dest_rect.width(), dest_rect.height(), flip_y, - premultiply_alpha, false); + destination_gl->CopyTextureCHROMIUM(intermediate_texture, 0, target, + texture, level, internal_format, type, + flip_y, premultiply_alpha, false); destination_gl->DeleteTextures(1, &intermediate_texture);
diff --git a/media/renderers/skcanvas_video_renderer.h b/media/renderers/skcanvas_video_renderer.h index 76a2cc1..8c7110e 100644 --- a/media/renderers/skcanvas_video_renderer.h +++ b/media/renderers/skcanvas_video_renderer.h
@@ -69,12 +69,10 @@ void* rgb_pixels, size_t row_bytes); - // Copy the contents of texture of |video_frame| to texture |texture|. - // |level|, |internal_format|, |type| specify target texture |texture|. - // The format of |video_frame| must be VideoFrame::NATIVE_TEXTURE. - // |copy_mode| alters how the copy is done, and takes into consideration - // whether the caller will clip the texture to the frame's |visible_rect|, - // or expects this to be done internally. + // Copy the visible rect size contents of texture of |video_frame| to + // texture |texture|. |level|, |internal_format|, |type| specify target + // texture |texture|. The format of |video_frame| must be + // VideoFrame::NATIVE_TEXTURE. static void CopyVideoFrameSingleTextureToGLTexture( gpu::gles2::GLES2Interface* gl, VideoFrame* video_frame, @@ -92,7 +90,8 @@ // |level|, |internal_format|, |type| specify target texture |texture|. // The format of |video_frame| must be VideoFrame::NATIVE_TEXTURE. // |context_3d| has a GrContext that may be used during the copy. - // Returns true on success. + // CorrectLastImageDimensions() insures that the source texture will be + // cropped to |visible_rect|. Returns true on success. bool CopyVideoFrameTexturesToGLTexture( const Context3D& context_3d, gpu::gles2::GLES2Interface* destination_gl,
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl index d6ef1436..8af6a7a 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl
@@ -13,10 +13,13 @@ static {{constant|format_constant_declaration(nested=True)}}; {%- endfor %} +{%- set in_place_marker = "WTF::in_place" + if for_blink else "base::in_place" %} + template <typename... Args> static {{struct.name}}Ptr New(Args&&... args) { return {{struct.name}}Ptr( - base::in_place, + {{in_place_marker}}, std::forward<Args>(args)...); } @@ -112,4 +115,3 @@ DISALLOW_COPY_AND_ASSIGN({{struct.name}}); {%- endif %} }; -
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl index 4a768a9f..c545d74 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl
@@ -4,8 +4,11 @@ using Data_ = internal::{{union.name}}_Data; using Tag = Data_::{{union.name}}_Tag; +{%- set in_place_marker = "WTF::in_place" + if for_blink else "base::in_place" %} + static {{union.name}}Ptr New() { - return {{union.name}}Ptr(base::in_place); + return {{union.name}}Ptr({{in_place_marker}}); } {%- for field in union.fields %} @@ -13,7 +16,7 @@ static {{union.name}}Ptr New{{field.name|under_to_camel}}( {{field.kind|cpp_wrapper_param_type}} {{field.name}}) { - auto result = {{union.name}}Ptr(base::in_place); + auto result = {{union.name}}Ptr({{in_place_marker}}); result->set_{{field.name}}(std::move({{field.name}})); return result; }
diff --git a/native_client_sdk/src/build_tools/build_sdk.py b/native_client_sdk/src/build_tools/build_sdk.py index 7213502..dcdda41 100755 --- a/native_client_sdk/src/build_tools/build_sdk.py +++ b/native_client_sdk/src/build_tools/build_sdk.py
@@ -813,12 +813,12 @@ # needed to be able to run sel_ldr_arm under qemu. arm_libs = [ 'lib/arm-linux-gnueabihf/librt.so.1', + 'lib/arm-linux-gnueabihf/libdl.so.2', 'lib/arm-linux-gnueabihf/libpthread.so.0', 'lib/arm-linux-gnueabihf/libgcc_s.so.1', 'lib/arm-linux-gnueabihf/libc.so.6', 'lib/arm-linux-gnueabihf/ld-linux-armhf.so.3', 'lib/arm-linux-gnueabihf/libm.so.6', - 'usr/lib/arm-linux-gnueabihf/libstdc++.so.6' ] arm_lib_dir = os.path.join(pepperdir, 'tools', 'lib', 'arm_trusted', 'lib') buildbot_common.MakeDir(arm_lib_dir)
diff --git a/native_client_sdk/src/build_tools/sdk_files.list b/native_client_sdk/src/build_tools/sdk_files.list index 2b526dc..4022d8e 100644 --- a/native_client_sdk/src/build_tools/sdk_files.list +++ b/native_client_sdk/src/build_tools/sdk_files.list
@@ -463,11 +463,11 @@ tools/irt_core_x86_64.nexe [linux]tools/lib/arm_trusted/lib/ld-linux-armhf.so.3 [linux]tools/lib/arm_trusted/lib/libc.so.6 +[linux]tools/lib/arm_trusted/lib/libdl.so.2 [linux]tools/lib/arm_trusted/lib/libgcc_s.so.1 [linux]tools/lib/arm_trusted/lib/libm.so.6 [linux]tools/lib/arm_trusted/lib/libpthread.so.0 [linux]tools/lib/arm_trusted/lib/librt.so.1 -[linux]tools/lib/arm_trusted/lib/libstdc++.so.6 tools/lib/elf.py tools/lib/get_shared_deps.py tools/lib/quote.py
diff --git a/net/BUILD.gn b/net/BUILD.gn index 866a0f2..b5931635 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -4703,6 +4703,7 @@ "cert/x509_cert_types_unittest.cc", "cert/x509_certificate_unittest.cc", "cert/x509_util_ios_and_mac_unittest.cc", + "cert/x509_util_nss_unittest.cc", "cert/x509_util_unittest.cc", "cert_net/cert_net_fetcher_impl_unittest.cc", "cert_net/nss_ocsp_unittest.cc", @@ -5349,6 +5350,7 @@ sources -= [ "cert/internal/trust_store_nss_unittest.cc", "cert/nss_cert_database_unittest.cc", + "cert/x509_util_nss_unittest.cc", "ssl/client_cert_store_nss_unittest.cc", "ssl/ssl_platform_key_nss_unittest.cc", ]
diff --git a/net/cert/x509_certificate.h b/net/cert/x509_certificate.h index 792180d3..eef7454 100644 --- a/net/cert/x509_certificate.h +++ b/net/cert/x509_certificate.h
@@ -17,7 +17,6 @@ #include "base/strings/string_piece.h" #include "base/time/time.h" #include "net/base/net_export.h" -#include "net/cert/cert_type.h" #include "net/cert/x509_cert_types.h" #include "net/net_features.h" @@ -154,12 +153,6 @@ static scoped_refptr<X509Certificate> CreateFromBytes(const char* data, size_t length); -#if defined(USE_NSS_CERTS) - // The default nickname of the certificate, based on the certificate type - // passed in. - std::string GetDefaultNickname(CertType type) const; -#endif - // Create an X509Certificate from the representation stored in the given // pickle. The data for this object is found relative to the given // pickle_iter, which should be passed to the pickle's various Read* methods.
diff --git a/net/cert/x509_certificate_nss.cc b/net/cert/x509_certificate_nss.cc index 4f5baa3..19f0f98 100644 --- a/net/cert/x509_certificate_nss.cc +++ b/net/cert/x509_certificate_nss.cc
@@ -211,58 +211,6 @@ ParseDate(&cert_handle_->validity.notAfter, &valid_expiry_)); } -std::string X509Certificate::GetDefaultNickname(CertType type) const { - std::string result; - if (type == USER_CERT && cert_handle_->slot) { - // Find the private key for this certificate and see if it has a - // nickname. If there is a private key, and it has a nickname, then - // return that nickname. - SECKEYPrivateKey* private_key = PK11_FindPrivateKeyFromCert( - cert_handle_->slot, - cert_handle_, - NULL); // wincx - if (private_key) { - char* private_key_nickname = PK11_GetPrivateKeyNickname(private_key); - if (private_key_nickname) { - result = private_key_nickname; - PORT_Free(private_key_nickname); - SECKEY_DestroyPrivateKey(private_key); - return result; - } - SECKEY_DestroyPrivateKey(private_key); - } - } - - switch (type) { - case CA_CERT: { - char* nickname = CERT_MakeCANickname(cert_handle_); - result = nickname; - PORT_Free(nickname); - break; - } - case USER_CERT: { - std::string subject_name = subject_.GetDisplayName(); - if (subject_name.empty()) { - const char* email = CERT_GetFirstEmailAddress(cert_handle_); - if (email) - subject_name = email; - } - // TODO(gspencer): Internationalize this. It's wrong to assume English - // here. - result = base::StringPrintf("%s's %s ID", subject_name.c_str(), - issuer_.GetDisplayName().c_str()); - break; - } - case SERVER_CERT: - result = subject_.GetDisplayName(); - break; - case OTHER_CERT: - default: - break; - } - return result; -} - bool X509Certificate::GetSubjectAltName( std::vector<std::string>* dns_names, std::vector<std::string>* ip_addrs) const {
diff --git a/net/cert/x509_certificate_unittest.cc b/net/cert/x509_certificate_unittest.cc index 91bdefc4..8d6ee47 100644 --- a/net/cert/x509_certificate_unittest.cc +++ b/net/cert/x509_certificate_unittest.cc
@@ -942,20 +942,6 @@ X509Certificate::FreeOSCertHandle(NULL); } -#if defined(USE_NSS_CERTS) -TEST(X509CertificateTest, GetDefaultNickname) { - base::FilePath certs_dir = GetTestCertsDirectory(); - - scoped_refptr<X509Certificate> test_cert( - ImportCertFromFile(certs_dir, "no_subject_common_name_cert.pem")); - ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get()); - - std::string nickname = test_cert->GetDefaultNickname(USER_CERT); - EXPECT_EQ("wtc@google.com's COMODO Client Authentication and " - "Secure Email CA ID", nickname); -} -#endif - const struct CertificateFormatTestData { const char* file_name; X509Certificate::Format format;
diff --git a/net/cert/x509_util_nss.cc b/net/cert/x509_util_nss.cc index 13d7e36..c60e886 100644 --- a/net/cert/x509_util_nss.cc +++ b/net/cert/x509_util_nss.cc
@@ -20,17 +20,115 @@ namespace net { +namespace x509_util { + namespace { // Microsoft User Principal Name: 1.3.6.1.4.1.311.20.2.3 const uint8_t kUpnOid[] = {0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0x37, 0x14, 0x2, 0x3}; +std::string DecodeAVAValue(CERTAVA* ava) { + SECItem* decode_item = CERT_DecodeAVAValue(&ava->value); + if (!decode_item) + return std::string(); + std::string value(reinterpret_cast<char*>(decode_item->data), + decode_item->len); + SECITEM_FreeItem(decode_item, PR_TRUE); + return value; +} + +// Generates a unique nickname for |slot|, returning |nickname| if it is +// already unique. +// +// Note: The nickname returned will NOT include the token name, thus the +// token name must be prepended if calling an NSS function that expects +// <token>:<nickname>. +// TODO(gspencer): Internationalize this: it's wrong to hard-code English. +std::string GetUniqueNicknameForSlot(const std::string& nickname, + const SECItem* subject, + PK11SlotInfo* slot) { + int index = 2; + std::string new_name = nickname; + std::string temp_nickname = new_name; + std::string token_name; + + if (!slot) + return new_name; + + if (!PK11_IsInternalKeySlot(slot)) { + token_name.assign(PK11_GetTokenName(slot)); + token_name.append(":"); + + temp_nickname = token_name + new_name; + } + + while (SEC_CertNicknameConflict(temp_nickname.c_str(), + const_cast<SECItem*>(subject), + CERT_GetDefaultCertDB())) { + base::SStringPrintf(&new_name, "%s #%d", nickname.c_str(), index++); + temp_nickname = token_name + new_name; + } + + return new_name; +} + +// The default nickname of the certificate, based on the certificate type +// passed in. +std::string GetDefaultNickname(CERTCertificate* nss_cert, CertType type) { + std::string result; + if (type == USER_CERT && nss_cert->slot) { + // Find the private key for this certificate and see if it has a + // nickname. If there is a private key, and it has a nickname, then + // return that nickname. + SECKEYPrivateKey* private_key = + PK11_FindPrivateKeyFromCert(nss_cert->slot, nss_cert, NULL /*wincx*/); + if (private_key) { + char* private_key_nickname = PK11_GetPrivateKeyNickname(private_key); + if (private_key_nickname) { + result = private_key_nickname; + PORT_Free(private_key_nickname); + SECKEY_DestroyPrivateKey(private_key); + return result; + } + SECKEY_DestroyPrivateKey(private_key); + } + } + + switch (type) { + case CA_CERT: { + char* nickname = CERT_MakeCANickname(nss_cert); + result = nickname; + PORT_Free(nickname); + break; + } + case USER_CERT: { + std::string subject_name = GetCERTNameDisplayName(&nss_cert->subject); + if (subject_name.empty()) { + const char* email = CERT_GetFirstEmailAddress(nss_cert); + if (email) + subject_name = email; + } + // TODO(gspencer): Internationalize this. It's wrong to assume English + // here. + result = + base::StringPrintf("%s's %s ID", subject_name.c_str(), + GetCERTNameDisplayName(&nss_cert->issuer).c_str()); + break; + } + case SERVER_CERT: { + result = GetCERTNameDisplayName(&nss_cert->subject); + break; + } + case OTHER_CERT: + default: + break; + } + return result; +} + } // namespace -namespace x509_util { - - void GetRFC822SubjectAltNames(CERTCertificate* cert_handle, std::vector<std::string>* names) { crypto::ScopedSECItem alt_name(SECITEM_AllocItem(NULL, NULL, 0)); @@ -99,32 +197,39 @@ } } -std::string GetUniqueNicknameForSlot(const std::string& nickname, - const SECItem* subject, +std::string GetDefaultUniqueNickname(CERTCertificate* nss_cert, + CertType type, PK11SlotInfo* slot) { - int index = 2; - std::string new_name = nickname; - std::string temp_nickname = new_name; - std::string token_name; + return GetUniqueNicknameForSlot(GetDefaultNickname(nss_cert, type), + &nss_cert->derSubject, slot); +} - if (!slot) - return new_name; - - if (!PK11_IsInternalKeySlot(slot)) { - token_name.assign(PK11_GetTokenName(slot)); - token_name.append(":"); - - temp_nickname = token_name + new_name; +std::string GetCERTNameDisplayName(CERTName* name) { + // Search for attributes in the Name, in this order: CN, O and OU. + CERTAVA* ou_ava = nullptr; + CERTAVA* o_ava = nullptr; + CERTRDN** rdns = name->rdns; + for (size_t rdn = 0; rdns[rdn]; ++rdn) { + CERTAVA** avas = rdns[rdn]->avas; + for (size_t pair = 0; avas[pair] != 0; ++pair) { + SECOidTag tag = CERT_GetAVATag(avas[pair]); + if (tag == SEC_OID_AVA_COMMON_NAME) { + // If CN is found, return immediately. + return DecodeAVAValue(avas[pair]); + } + // If O or OU is found, save the first one of each so that it can be + // returned later if no CN attribute is found. + if (tag == SEC_OID_AVA_ORGANIZATION_NAME && !o_ava) + o_ava = avas[pair]; + if (tag == SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME && !ou_ava) + ou_ava = avas[pair]; + } } - - while (SEC_CertNicknameConflict(temp_nickname.c_str(), - const_cast<SECItem*>(subject), - CERT_GetDefaultCertDB())) { - base::SStringPrintf(&new_name, "%s #%d", nickname.c_str(), index++); - temp_nickname = token_name + new_name; - } - - return new_name; + if (o_ava) + return DecodeAVAValue(o_ava); + if (ou_ava) + return DecodeAVAValue(ou_ava); + return std::string(); } } // namespace x509_util
diff --git a/net/cert/x509_util_nss.h b/net/cert/x509_util_nss.h index 7acabdf29..291aba5b 100644 --- a/net/cert/x509_util_nss.h +++ b/net/cert/x509_util_nss.h
@@ -11,8 +11,10 @@ #include <vector> #include "net/base/net_export.h" +#include "net/cert/cert_type.h" typedef struct CERTCertificateStr CERTCertificate; +typedef struct CERTNameStr CERTName; typedef struct PK11SlotInfoStr PK11SlotInfo; typedef struct SECItemStr SECItem; @@ -49,16 +51,15 @@ NET_EXPORT void GetUPNSubjectAltNames(CERTCertificate* cert_handle, std::vector<std::string>* names); -// Generates a unique nickname for |slot|, returning |nickname| if it is -// already unique. -// -// Note: The nickname returned will NOT include the token name, thus the -// token name must be prepended if calling an NSS function that expects -// <token>:<nickname>. -// TODO(gspencer): Internationalize this: it's wrong to hard-code English. -std::string GetUniqueNicknameForSlot(const std::string& nickname, - const SECItem* subject, - PK11SlotInfo* slot); +// Generates a unique nickname for |nss_cert| based on the |type| and |slot|. +NET_EXPORT std::string GetDefaultUniqueNickname(CERTCertificate* nss_cert, + CertType type, + PK11SlotInfo* slot); + +// Returns a name that can be used to represent the principal. It tries in +// this order: CN, O and OU and returns the first non-empty one found. +// This mirrors net::CertPrincipal::GetDisplayName. +NET_EXPORT std::string GetCERTNameDisplayName(CERTName* name); } // namespace x509_util
diff --git a/net/cert/x509_util_nss_unittest.cc b/net/cert/x509_util_nss_unittest.cc new file mode 100644 index 0000000..49c0f57a --- /dev/null +++ b/net/cert/x509_util_nss_unittest.cc
@@ -0,0 +1,63 @@ +// 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 "net/cert/x509_util_nss.h" + +#include "net/cert/scoped_nss_types.h" +#include "net/cert/x509_certificate.h" +#include "net/test/cert_test_util.h" +#include "net/test/test_data_directory.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +TEST(X509UtilNSSTest, GetDefaultNickname) { + base::FilePath certs_dir = GetTestCertsDirectory(); + + scoped_refptr<X509Certificate> test_cert( + ImportCertFromFile(certs_dir, "no_subject_common_name_cert.pem")); + ASSERT_TRUE(test_cert); + + std::string nickname = x509_util::GetDefaultUniqueNickname( + test_cert->os_cert_handle(), USER_CERT, nullptr /*slot*/); + EXPECT_EQ( + "wtc@google.com's COMODO Client Authentication and " + "Secure Email CA ID", + nickname); +} + +TEST(X509UtilNSSTest, GetCERTNameDisplayName_CN) { + base::FilePath certs_dir = GetTestCertsDirectory(); + + scoped_refptr<X509Certificate> test_cert( + ImportCertFromFile(certs_dir, "ok_cert.pem")); + ASSERT_TRUE(test_cert); + + std::string name = + x509_util::GetCERTNameDisplayName(&test_cert->os_cert_handle()->subject); + EXPECT_EQ("127.0.0.1", name); + EXPECT_EQ(test_cert->subject().GetDisplayName(), name); +} + +TEST(X509UtilNSSTest, GetCERTNameDisplayName_O) { + base::FilePath certs_dir = + GetTestNetDataDirectory().AppendASCII("parse_certificate_unittest"); + + scoped_refptr<X509Certificate> test_cert( + ImportCertFromFile(certs_dir, "subject_t61string.pem")); + ASSERT_TRUE(test_cert); + + std::string name = + x509_util::GetCERTNameDisplayName(&test_cert->os_cert_handle()->subject); + EXPECT_EQ( + " !\"#$%&'()*+,-./" + "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" + "abcdefghijklmnopqrstuvwxyz{|}~" + " ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæç" + "èéêëìíîïðñòóôõö÷øùúûüýþÿ", + name); + EXPECT_EQ(test_cert->subject().GetDisplayName(), name); +} + +} // namespace net
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 49b5ded6..5fb69cbd 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -8381,7 +8381,7 @@ spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush( - nullptr, 0, 2, 1, "https://myproxy:70/foo.dat")); + nullptr, 0, 2, 1, "http://www.example.org/foo.dat")); SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
diff --git a/net/interfaces/ip_address.mojom b/net/interfaces/ip_address.mojom index 012b81c..aec5dbfb 100644 --- a/net/interfaces/ip_address.mojom +++ b/net/interfaces/ip_address.mojom
@@ -8,5 +8,5 @@ struct IPAddress { // IP address as a numeric value from most to least significant byte. // Will be of length 4 for IPv4 addresses and 16 for IPv6. - array<uint8> address; + array<uint8> address_bytes; };
diff --git a/net/interfaces/ip_address_struct_traits.cc b/net/interfaces/ip_address_struct_traits.cc index e93b13e5..5a0c8aa 100644 --- a/net/interfaces/ip_address_struct_traits.cc +++ b/net/interfaces/ip_address_struct_traits.cc
@@ -10,7 +10,7 @@ net::interfaces::IPAddressDataView data, net::IPAddress* out) { std::vector<uint8_t> bytes; - if (!data.ReadAddress(&bytes)) + if (!data.ReadAddressBytes(&bytes)) return false; *out = net::IPAddress(bytes.data(), bytes.size());
diff --git a/net/interfaces/ip_address_struct_traits.h b/net/interfaces/ip_address_struct_traits.h index 9c7b48e..e1b8684 100644 --- a/net/interfaces/ip_address_struct_traits.h +++ b/net/interfaces/ip_address_struct_traits.h
@@ -12,9 +12,10 @@ namespace mojo { template <> struct StructTraits<net::interfaces::IPAddressDataView, net::IPAddress> { - static const std::vector<uint8_t> address(const net::IPAddress& ip_address) { - // TODO(rch): avoid creating a vector here. - return ip_address.CopyBytesToVector(); + static mojo::ConstCArray<uint8_t> address_bytes( + const net::IPAddress& ip_address) { + return mojo::ConstCArray<uint8_t>(ip_address.bytes().size(), + ip_address.bytes().data()); } static bool Read(net::interfaces::IPAddressDataView obj, net::IPAddress* out);
diff --git a/net/nqe/network_quality_estimator.cc b/net/nqe/network_quality_estimator.cc index e0b0f94..6e39d433 100644 --- a/net/nqe/network_quality_estimator.cc +++ b/net/nqe/network_quality_estimator.cc
@@ -1233,6 +1233,23 @@ if (!GetRecentTransportRTT(start_time, transport_rtt)) *transport_rtt = nqe::internal::InvalidRTT(); + if (*http_rtt != nqe::internal::InvalidRTT() && + *transport_rtt != nqe::internal::InvalidRTT()) { + // Use transport RTT to clamp the HTTP RTT between lower and upper bounds. + if (params_->lower_bound_http_rtt_transport_rtt_multiplier() > 0) { + *http_rtt = std::max( + *http_rtt, + *transport_rtt * + params_->lower_bound_http_rtt_transport_rtt_multiplier()); + } + if (params_->upper_bound_http_rtt_transport_rtt_multiplier() > 0) { + *http_rtt = std::min( + *http_rtt, + *transport_rtt * + params_->upper_bound_http_rtt_transport_rtt_multiplier()); + } + } + if (!GetRecentDownlinkThroughputKbps(start_time, downstream_throughput_kbps)) *downstream_throughput_kbps = nqe::internal::kInvalidThroughput;
diff --git a/net/nqe/network_quality_estimator_params.cc b/net/nqe/network_quality_estimator_params.cc index ee581308..c2e46f4 100644 --- a/net/nqe/network_quality_estimator_params.cc +++ b/net/nqe/network_quality_estimator_params.cc
@@ -403,9 +403,27 @@ persistent_cache_reading_enabled_( GetPersistentCacheReadingEnabled(params_)), min_socket_watcher_notification_interval_( - GetMinSocketWatcherNotificationInterval(params_)) { + GetMinSocketWatcherNotificationInterval(params_)), + lower_bound_http_rtt_transport_rtt_multiplier_( + GetDoubleValueForVariationParamWithDefaultValue( + params_, + "lower_bound_http_rtt_transport_rtt_multiplier", + -1)), + upper_bound_http_rtt_transport_rtt_multiplier_( + GetDoubleValueForVariationParamWithDefaultValue( + params_, + "upper_bound_http_rtt_transport_rtt_multiplier", + -1)) { DCHECK_LE(0.0, correlation_uma_logging_probability_); DCHECK_GE(1.0, correlation_uma_logging_probability_); + DCHECK(lower_bound_http_rtt_transport_rtt_multiplier_ == -1 || + lower_bound_http_rtt_transport_rtt_multiplier_ > 0); + DCHECK(upper_bound_http_rtt_transport_rtt_multiplier_ == -1 || + upper_bound_http_rtt_transport_rtt_multiplier_ > 0); + DCHECK(lower_bound_http_rtt_transport_rtt_multiplier_ == -1 || + upper_bound_http_rtt_transport_rtt_multiplier_ == -1 || + lower_bound_http_rtt_transport_rtt_multiplier_ < + upper_bound_http_rtt_transport_rtt_multiplier_); const auto algorithm_it = params_.find("effective_connection_type_algorithm"); effective_connection_type_algorithm_ =
diff --git a/net/nqe/network_quality_estimator_params.h b/net/nqe/network_quality_estimator_params.h index 32adc77..9a0ccaf 100644 --- a/net/nqe/network_quality_estimator_params.h +++ b/net/nqe/network_quality_estimator_params.h
@@ -137,6 +137,24 @@ effective_connection_type_algorithm_ = algorithm; } + // Returns the multiplier by which the transport RTT should be multipled when + // computing the HTTP RTT. The multiplied value of the transport RTT serves + // as a lower bound to the HTTP RTT estimate. e.g., if the multiplied + // transport RTT is 100 msec., then HTTP RTT estimate can't be lower than + // 100 msec. Returns a negative value if the param is not set. + double lower_bound_http_rtt_transport_rtt_multiplier() const { + return lower_bound_http_rtt_transport_rtt_multiplier_; + } + + // Returns the multiplier by which the transport RTT should be multipled when + // computing the HTTP RTT. The multiplied value of the transport RTT serves + // as an upper bound to the HTTP RTT estimate. e.g., if the multiplied + // transport RTT is 100 msec., then HTTP RTT estimate can't be more than + // 100 msec. Returns a negative value if the param is not set. + double upper_bound_http_rtt_transport_rtt_multiplier() const { + return upper_bound_http_rtt_transport_rtt_multiplier_; + } + private: // Map containing all field trial parameters related to // NetworkQualityEstimator field trial. @@ -149,6 +167,8 @@ base::Optional<EffectiveConnectionType> forced_effective_connection_type_; bool persistent_cache_reading_enabled_; const base::TimeDelta min_socket_watcher_notification_interval_; + const double lower_bound_http_rtt_transport_rtt_multiplier_; + const double upper_bound_http_rtt_transport_rtt_multiplier_; EffectiveConnectionTypeAlgorithm effective_connection_type_algorithm_;
diff --git a/net/nqe/network_quality_estimator_unittest.cc b/net/nqe/network_quality_estimator_unittest.cc index 989143b..263c3da 100644 --- a/net/nqe/network_quality_estimator_unittest.cc +++ b/net/nqe/network_quality_estimator_unittest.cc
@@ -1777,6 +1777,124 @@ EXPECT_EQ(0U, observer_3.effective_connection_types().size()); } +// Tests that the transport RTT is used for computing the HTTP RTT. +TEST(NetworkQualityEstimatorTest, TestTransportRttUsedForHttpRttComputation) { + const struct { + base::TimeDelta http_rtt; + base::TimeDelta transport_rtt; + std::string lower_bound_http_rtt_transport_rtt_multiplier; + std::string upper_bound_http_rtt_transport_rtt_multiplier; + base::TimeDelta expected_http_rtt; + EffectiveConnectionType expected_type; + } tests[] = { + { + base::TimeDelta::FromMilliseconds(100), + base::TimeDelta::FromMilliseconds(200), "", "", + base::TimeDelta::FromMilliseconds(100), EFFECTIVE_CONNECTION_TYPE_4G, + }, + { + base::TimeDelta::FromMilliseconds(100), + base::TimeDelta::FromMilliseconds(200), "0.01", "", + base::TimeDelta::FromMilliseconds(100), EFFECTIVE_CONNECTION_TYPE_4G, + }, + { + base::TimeDelta::FromMilliseconds(100), + base::TimeDelta::FromMilliseconds(200), "1.0", "", + base::TimeDelta::FromMilliseconds(200), EFFECTIVE_CONNECTION_TYPE_4G, + }, + { + base::TimeDelta::FromMilliseconds(100), + base::TimeDelta::FromMilliseconds(200), "1.5", "", + base::TimeDelta::FromMilliseconds(300), EFFECTIVE_CONNECTION_TYPE_3G, + }, + { + base::TimeDelta::FromMilliseconds(100), + base::TimeDelta::FromMilliseconds(200), "2.0", "", + base::TimeDelta::FromMilliseconds(400), EFFECTIVE_CONNECTION_TYPE_3G, + }, + { + base::TimeDelta::FromMilliseconds(100), + base::TimeDelta::FromMilliseconds(200), "2.0", "5.0", + base::TimeDelta::FromMilliseconds(400), EFFECTIVE_CONNECTION_TYPE_3G, + }, + { + base::TimeDelta::FromMilliseconds(100), + base::TimeDelta::FromMilliseconds(200), "10.0", "", + base::TimeDelta::FromMilliseconds(2000), EFFECTIVE_CONNECTION_TYPE_2G, + }, + { + base::TimeDelta::FromMilliseconds(200), + base::TimeDelta::FromMilliseconds(100), "10.0", "", + base::TimeDelta::FromMilliseconds(1000), EFFECTIVE_CONNECTION_TYPE_3G, + }, + { + base::TimeDelta::FromMilliseconds(200), + base::TimeDelta::FromMilliseconds(5), "10.0", "", + base::TimeDelta::FromMilliseconds(200), EFFECTIVE_CONNECTION_TYPE_4G, + }, + { + base::TimeDelta::FromMilliseconds(200), + base::TimeDelta::FromMilliseconds(5), "10.0", "20.0", + base::TimeDelta::FromMilliseconds(100), EFFECTIVE_CONNECTION_TYPE_4G, + }, + { + base::TimeDelta::FromMilliseconds(100), + base::TimeDelta::FromMilliseconds(200), "foobar", "", + base::TimeDelta::FromMilliseconds(100), EFFECTIVE_CONNECTION_TYPE_4G, + }, + { + base::TimeDelta::FromMilliseconds(100), + base::TimeDelta::FromMilliseconds(4000), "", "", + base::TimeDelta::FromMilliseconds(100), EFFECTIVE_CONNECTION_TYPE_4G, + }, + { + base::TimeDelta::FromMilliseconds(100), + base::TimeDelta::FromMilliseconds(4000), "1.0", "10.0", + base::TimeDelta::FromMilliseconds(4000), + EFFECTIVE_CONNECTION_TYPE_SLOW_2G, + }, + { + base::TimeDelta::FromMilliseconds(4000), + base::TimeDelta::FromMilliseconds(100), "", "", + base::TimeDelta::FromMilliseconds(4000), + EFFECTIVE_CONNECTION_TYPE_SLOW_2G, + }, + { + base::TimeDelta::FromMilliseconds(4000), + base::TimeDelta::FromMilliseconds(100), "1.0", "10.0", + base::TimeDelta::FromMilliseconds(1000), EFFECTIVE_CONNECTION_TYPE_3G, + }, + { + base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromMilliseconds(100), "1.0", "10.0", + base::TimeDelta::FromMilliseconds(100), EFFECTIVE_CONNECTION_TYPE_4G, + }, + { + base::TimeDelta::FromMilliseconds(500), + base::TimeDelta::FromMilliseconds(100), "1.0", "10.0", + base::TimeDelta::FromMilliseconds(500), EFFECTIVE_CONNECTION_TYPE_3G, + }, + }; + + for (const auto& test : tests) { + std::map<std::string, std::string> variation_params; + variation_params["lower_bound_http_rtt_transport_rtt_multiplier"] = + test.lower_bound_http_rtt_transport_rtt_multiplier; + variation_params["upper_bound_http_rtt_transport_rtt_multiplier"] = + test.upper_bound_http_rtt_transport_rtt_multiplier; + TestNetworkQualityEstimator estimator(variation_params); + + estimator.set_start_time_null_http_rtt(test.http_rtt); + estimator.set_start_time_null_transport_rtt(test.transport_rtt); + + estimator.RunOneRequest(); + EXPECT_EQ(test.expected_http_rtt, estimator.GetHttpRTT()); + EXPECT_EQ(test.transport_rtt, estimator.GetTransportRTT()); + EXPECT_EQ(test.expected_type, estimator.GetEffectiveConnectionType()) + << test.lower_bound_http_rtt_transport_rtt_multiplier; + } +} + // Tests that the network quality is computed at the specified interval, and // that the network quality observers are notified of any change. TEST(NetworkQualityEstimatorTest, TestRTTAndThroughputEstimatesObserver) {
diff --git a/net/spdy/chromium/spdy_session.cc b/net/spdy/chromium/spdy_session.cc index d9f28806..fcc1779 100644 --- a/net/spdy/chromium/spdy_session.cc +++ b/net/spdy/chromium/spdy_session.cc
@@ -1575,15 +1575,13 @@ DCHECK(gurl.is_valid()); - // Check that the pushed stream advertises the same origin as its associated - // stream. Bypass this check if and only if this session is with a SPDY proxy - // that is trusted explicitly as determined by the |proxy_delegate_| or if the - // proxy is pushing same-origin resources. - if (!HostPortPair::FromURL(gurl).Equals(host_port_pair())) { + // Cross-origin push validation. + GURL associated_url(associated_it->second->GetUrlFromHeaders()); + if (associated_url.GetOrigin() != gurl.GetOrigin()) { if (proxy_delegate_ && proxy_delegate_->IsTrustedSpdyProxy( ProxyServer(ProxyServer::SCHEME_HTTPS, host_port_pair()))) { - // Disallow pushing of HTTPS content. + // Disallow pushing of HTTPS content by trusted proxy. if (gurl.SchemeIs("https")) { EnqueueResetStreamFrame( stream_id, request_priority, ERROR_CODE_REFUSED_STREAM, @@ -1593,29 +1591,25 @@ return; } } else { - GURL associated_url(associated_it->second->GetUrlFromHeaders()); - if (associated_url.SchemeIs("https")) { - SSLInfo ssl_info; - CHECK(GetSSLInfo(&ssl_info)); - if (!gurl.SchemeIs("https") || - !CanPool(transport_security_state_, ssl_info, associated_url.host(), - gurl.host())) { - EnqueueResetStreamFrame( - stream_id, request_priority, ERROR_CODE_REFUSED_STREAM, - SpdyStringPrintf("Rejected push stream %d on secure connection", - associated_stream_id)); - return; - } - } else { - // TODO(bnc): Change SpdyNetworkTransactionTests to use secure sockets. - if (associated_url.GetOrigin() != gurl.GetOrigin()) { - EnqueueResetStreamFrame( - stream_id, request_priority, ERROR_CODE_REFUSED_STREAM, - SpdyStringPrintf( - "Rejected cross origin push stream %d on insecure connection", - associated_stream_id)); - return; - } + if (!gurl.SchemeIs("https") || !associated_url.SchemeIs("https")) { + EnqueueResetStreamFrame( + stream_id, request_priority, ERROR_CODE_REFUSED_STREAM, + SpdyStringPrintf("Rejected cross origin pushed stream %d: " + "both pushed URL and associated URL " + "must have https scheme.", + associated_stream_id)); + return; + } + SSLInfo ssl_info; + CHECK(GetSSLInfo(&ssl_info)); + if (!CanPool(transport_security_state_, ssl_info, associated_url.host(), + gurl.host())) { + EnqueueResetStreamFrame( + stream_id, request_priority, ERROR_CODE_REFUSED_STREAM, + SpdyStringPrintf("Rejected pushed stream %d because certificate " + "does not match pushed URL.", + associated_stream_id)); + return; } } }
diff --git a/net/test/cert_test_util_nss.cc b/net/test/cert_test_util_nss.cc index 4105e9b885..f8c9152 100644 --- a/net/test/cert_test_util_nss.cc +++ b/net/test/cert_test_util_nss.cc
@@ -13,6 +13,7 @@ #include "crypto/nss_util.h" #include "crypto/scoped_nss_types.h" #include "net/cert/cert_type.h" +#include "net/cert/x509_util_nss.h" namespace net { @@ -42,7 +43,8 @@ bool ImportClientCertToSlot(const scoped_refptr<X509Certificate>& cert, PK11SlotInfo* slot) { - std::string nickname = cert->GetDefaultNickname(USER_CERT); + std::string nickname = x509_util::GetDefaultUniqueNickname( + cert->os_cert_handle(), USER_CERT, slot); SECStatus rv = PK11_ImportCert(slot, cert->os_cert_handle(), CK_INVALID_HANDLE, nickname.c_str(), PR_FALSE); if (rv != SECSuccess) {
diff --git a/net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp b/net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp index a79d52e..c6c47913 100644 --- a/net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp +++ b/net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp
@@ -86,15 +86,12 @@ // Mozilla uses CERT_AddTempCertToPerm, however it is privately exported, // and it doesn't take the slot as an argument either. Instead, we use // PK11_ImportCert and CERT_ChangeCertTrust. - SECStatus srv = PK11_ImportCert( - slot, - root->os_cert_handle(), - CK_INVALID_HANDLE, - net::x509_util::GetUniqueNicknameForSlot( - root->GetDefaultNickname(net::CA_CERT), - &root->os_cert_handle()->derSubject, - slot).c_str(), - PR_FALSE /* includeTrust (unused) */); + SECStatus srv = + PK11_ImportCert(slot, root->os_cert_handle(), CK_INVALID_HANDLE, + net::x509_util::GetDefaultUniqueNickname( + root->os_cert_handle(), net::CA_CERT, slot) + .c_str(), + PR_FALSE /* includeTrust (unused) */); if (srv != SECSuccess) { LOG(ERROR) << "PK11_ImportCert failed with error " << PORT_GetError(); return false; @@ -146,15 +143,12 @@ // Mozilla uses CERT_ImportCerts, which doesn't take a slot arg. We use // PK11_ImportCert instead. - SECStatus srv = PK11_ImportCert( - slot, - cert->os_cert_handle(), - CK_INVALID_HANDLE, - net::x509_util::GetUniqueNicknameForSlot( - cert->GetDefaultNickname(net::CA_CERT), - &cert->os_cert_handle()->derSubject, - slot).c_str(), - PR_FALSE /* includeTrust (unused) */); + SECStatus srv = + PK11_ImportCert(slot, cert->os_cert_handle(), CK_INVALID_HANDLE, + net::x509_util::GetDefaultUniqueNickname( + cert->os_cert_handle(), net::CA_CERT, slot) + .c_str(), + PR_FALSE /* includeTrust (unused) */); if (srv != SECSuccess) { LOG(ERROR) << "PK11_ImportCert failed with error " << PORT_GetError(); // TODO(mattm): Should we bail or continue on error here? Mozilla doesn't @@ -182,15 +176,12 @@ // Mozilla uses CERT_ImportCerts, which doesn't take a slot arg. We use // PK11_ImportCert instead. - SECStatus srv = PK11_ImportCert( - slot, - cert->os_cert_handle(), - CK_INVALID_HANDLE, - net::x509_util::GetUniqueNicknameForSlot( - cert->GetDefaultNickname(net::SERVER_CERT), - &cert->os_cert_handle()->derSubject, - slot).c_str(), - PR_FALSE /* includeTrust (unused) */); + SECStatus srv = + PK11_ImportCert(slot, cert->os_cert_handle(), CK_INVALID_HANDLE, + net::x509_util::GetDefaultUniqueNickname( + cert->os_cert_handle(), net::SERVER_CERT, slot) + .c_str(), + PR_FALSE /* includeTrust (unused) */); if (srv != SECSuccess) { LOG(ERROR) << "PK11_ImportCert failed with error " << PORT_GetError(); not_imported->push_back(net::NSSCertDatabase::ImportCertFailure( @@ -224,9 +215,8 @@ // PK11_ImportCert instead. SECStatus srv = PK11_ImportCert(slot.get(), cert->os_cert_handle(), key, - net::x509_util::GetUniqueNicknameForSlot( - cert->GetDefaultNickname(net::USER_CERT), - &cert->os_cert_handle()->derSubject, slot.get()) + net::x509_util::GetDefaultUniqueNickname( + cert->os_cert_handle(), net::USER_CERT, slot.get()) .c_str(), PR_FALSE /* includeTrust (unused) */);
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index a3b8028..91dfe6d 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc
@@ -942,13 +942,6 @@ if (redirect_info.new_method != method_) { // TODO(davidben): This logic still needs to be replicated at the consumers. - if (method_ == "POST") { - // If being switched from POST, must remove Origin header. - // TODO(jww): This is Origin header removal is probably layering violation - // and - // should be refactored into //content. See https://crbug.com/471397. - extra_request_headers_.RemoveHeader(HttpRequestHeaders::kOrigin); - } // The inclusion of a multipart Content-Type header can cause problems with // some // servers:
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 5f9da873..accef39 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -8070,12 +8070,12 @@ // Check that the post-specific headers were stripped: EXPECT_FALSE(ContainsString(data, "Content-Length:")); EXPECT_FALSE(ContainsString(data, "Content-Type:")); - EXPECT_FALSE(ContainsString(data, "Origin:")); // These extra request headers should not have been stripped. EXPECT_TRUE(ContainsString(data, "Accept:")); EXPECT_TRUE(ContainsString(data, "Accept-Language:")); EXPECT_TRUE(ContainsString(data, "Accept-Charset:")); + EXPECT_TRUE(ContainsString(data, "Origin: http://localhost:1337")); } // The following tests check that we handle mutating the request for HTTP @@ -8096,9 +8096,8 @@ HTTPRedirectOriginHeaderTest(url, "GET", "GET", url.GetOrigin().spec()); HTTPRedirectOriginHeaderTest(https_redirect_url, "GET", "GET", "null"); - HTTPRedirectOriginHeaderTest(url, "POST", "GET", std::string()); - HTTPRedirectOriginHeaderTest(https_redirect_url, "POST", "GET", - std::string()); + HTTPRedirectOriginHeaderTest(url, "POST", "GET", url.GetOrigin().spec()); + HTTPRedirectOriginHeaderTest(https_redirect_url, "POST", "GET", "null"); } TEST_F(URLRequestTestHTTP, Redirect302Tests) { @@ -8114,9 +8113,8 @@ HTTPRedirectOriginHeaderTest(url, "GET", "GET", url.GetOrigin().spec()); HTTPRedirectOriginHeaderTest(https_redirect_url, "GET", "GET", "null"); - HTTPRedirectOriginHeaderTest(url, "POST", "GET", std::string()); - HTTPRedirectOriginHeaderTest(https_redirect_url, "POST", "GET", - std::string()); + HTTPRedirectOriginHeaderTest(url, "POST", "GET", url.GetOrigin().spec()); + HTTPRedirectOriginHeaderTest(https_redirect_url, "POST", "GET", "null"); } TEST_F(URLRequestTestHTTP, Redirect303Tests) { @@ -8132,9 +8130,8 @@ HTTPRedirectOriginHeaderTest(url, "GET", "GET", url.GetOrigin().spec()); HTTPRedirectOriginHeaderTest(https_redirect_url, "GET", "GET", "null"); - HTTPRedirectOriginHeaderTest(url, "POST", "GET", std::string()); - HTTPRedirectOriginHeaderTest(https_redirect_url, "POST", "GET", - std::string()); + HTTPRedirectOriginHeaderTest(url, "POST", "GET", url.GetOrigin().spec()); + HTTPRedirectOriginHeaderTest(https_redirect_url, "POST", "GET", "null"); } TEST_F(URLRequestTestHTTP, Redirect307Tests) {
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc index 2c33892..ac5a8c27 100644 --- a/pdf/pdfium/pdfium_engine.cc +++ b/pdf/pdfium/pdfium_engine.cc
@@ -1789,9 +1789,11 @@ double page_y; DeviceToPage(page_index, point.x(), point.y(), &page_x, &page_y); - FORM_OnLButtonDown(form_, pages_[page_index]->GetPage(), 0, page_x, page_y); + FPDF_PAGE page = pages_[page_index]->GetPage(); + FORM_OnLButtonDown(form_, page, 0, page_x, page_y); if (form_type > FPDF_FORMFIELD_UNKNOWN) { // returns -1 sometimes... - mouse_down_state_.Set(PDFiumPage::FormTypeToArea(form_type), target); + DCHECK_EQ(area, PDFiumPage::FormTypeToArea(form_type)); + mouse_down_state_.Set(area, target); // Destroy SelectionChangeInvalidator object before SetInFormTextArea() // changes plugin's focus to be in form text area. This way, regular text @@ -1801,27 +1803,16 @@ // (not the Renderer). selection_invalidator.reset(); - bool is_valid_control = (form_type == FPDF_FORMFIELD_TEXTFIELD || - form_type == FPDF_FORMFIELD_COMBOBOX); - -// TODO(bug_62400): figure out selection and copying -// for XFA fields -#if defined(PDF_ENABLE_XFA) - is_valid_control |= (form_type == FPDF_FORMFIELD_XFA); -#endif - SetInFormTextArea(is_valid_control); - if (is_valid_control) { - FPDF_ANNOTATION annot = FPDFAnnot_GetFormFieldAtPoint( - form_, pages_[last_page_mouse_down_]->GetPage(), page_x, page_y); - if (annot) { - int flags = FPDFAnnot_GetFormFieldFlags( - pages_[last_page_mouse_down_]->GetPage(), annot); - - editable_form_text_area_ = - CheckIfEditableFormTextArea(flags, form_type); - - FPDFPage_CloseAnnot(annot); - } + bool is_form_text_area = area == PDFiumPage::FORM_TEXT_AREA; + SetInFormTextArea(is_form_text_area); + if (is_form_text_area) { + FPDF_ANNOTATION annot = + FPDFAnnot_GetFormFieldAtPoint(form_, page, page_x, page_y); + DCHECK(annot); + int flags = FPDFAnnot_GetFormFieldFlags(page, annot); + editable_form_text_area_ = + CheckIfEditableFormTextArea(flags, form_type); + FPDFPage_CloseAnnot(annot); } return true; // Return now before we get into the selection code. }
diff --git a/pdf/pdfium/pdfium_page.cc b/pdf/pdfium/pdfium_page.cc index 01a5fb6..ef264dd 100644 --- a/pdf/pdfium/pdfium_page.cc +++ b/pdf/pdfium/pdfium_page.cc
@@ -296,6 +296,10 @@ switch (form_type) { case FPDF_FORMFIELD_COMBOBOX: case FPDF_FORMFIELD_TEXTFIELD: +#if defined(PDF_ENABLE_XFA) + // TODO(bug_353450): figure out selection and copying for XFA fields. + case FPDF_FORMFIELD_XFA: +#endif return FORM_TEXT_AREA; default: return NONSELECTABLE_AREA;
diff --git a/remoting/host/installer/linux/debian/chrome-remote-desktop.init b/remoting/host/installer/linux/debian/chrome-remote-desktop.init index da41f8d0..10363c10 100755 --- a/remoting/host/installer/linux/debian/chrome-remote-desktop.init +++ b/remoting/host/installer/linux/debian/chrome-remote-desktop.init
@@ -59,12 +59,10 @@ set +e if [ "$action" = "--start" ]; then - # TODO(rkjnsn): Support starting user-initiated sessions with our PAM - # wrapper. if [ "$(whoami)" = "root" ]; then "$USER_SESSION_PATH" start "$user" else - sudo -u "$user" --login --background "$HOST_PATH" --start + "$USER_SESSION_PATH" start fi else sudo -u "$user" "$HOST_PATH" "$action"
diff --git a/remoting/host/installer/linux/debian/control b/remoting/host/installer/linux/debian/control index 65bf9004..de5a3c63 100644 --- a/remoting/host/installer/linux/debian/control +++ b/remoting/host/installer/linux/debian/control
@@ -12,7 +12,7 @@ Package: chrome-remote-desktop Architecture: any -Depends: xvfb-randr | xvfb, policykit-1, xbase-clients, python (>= 2.6), python-psutil, ${shlibs:Depends}, ${misc:Depends}, ${python:Depends} +Depends: adduser, xvfb-randr | xvfb, policykit-1, xbase-clients, python (>= 2.6), python-psutil, ${shlibs:Depends}, ${misc:Depends}, ${python:Depends} Recommends: xvfb-randr Suggests: google-chrome-stable | google-chrome-beta | google-chrome-unstable Description: Chrome Remote Desktop Beta
diff --git a/remoting/host/installer/linux/debian/postinst b/remoting/host/installer/linux/debian/postinst index b7adfc4..b0f9f146 100755 --- a/remoting/host/installer/linux/debian/postinst +++ b/remoting/host/installer/linux/debian/postinst
@@ -18,9 +18,23 @@ NOTIFIER_DIR="/var/lib/update-notifier/user.d" VAR_DIR="/var/lib/chrome-remote-desktop" HASHES_FILE="$VAR_DIR/hashes" +USER_SESSION_PATH="/opt/google/chrome-remote-desktop/user-session" +CRD_GROUP="chrome-remote-desktop" case "$1" in "configure") + # Create CRD group if it doesn't already exist + if ! getent group "$CRD_GROUP" > /dev/null 2>&1; then + addgroup --system "$CRD_GROUP" + fi + # dpkg supports "stat overrides", which allow the administrator to specify + # the ownership and permissions that should be used when a given filesystem + # object is installed. If such an override is set, we shouldn't change the + # owner and permissions here. + if ! dpkg-statoverride --list "$USER_SESSION_PATH" > /dev/null 2>&1; then + chown root:"$CRD_GROUP" "$USER_SESSION_PATH" + chmod u=srwx,g=rx,o=r "$USER_SESSION_PATH" + fi # Kill host processes. The wrapper script will restart them. # TODO(lambroslambrou): Remove the '-9' when the underlying problem with # hosts not responding to SIGTERM has been fixed - http://crbug.com/420090
diff --git a/remoting/ios/client_keyboard.h b/remoting/ios/client_keyboard.h index 4908137..541e6fb 100644 --- a/remoting/ios/client_keyboard.h +++ b/remoting/ios/client_keyboard.h
@@ -14,7 +14,9 @@ @end // A class for capturing keyboard inputs and forwarding them to the delegate. -// It should remain first responder in order to capture all key inputs. +// It should remain first responder in order to capture all key inputs. Note +// that it will hide the soft keyboard and refuse to resign first responder if +// you try to resign first responder when the soft keyboard is showing. @interface ClientKeyboard : UIView<UIKeyInput, UITextInputTraits> @property(nonatomic) UIKeyboardAppearance keyboardAppearance;
diff --git a/remoting/ios/client_keyboard.mm b/remoting/ios/client_keyboard.mm index 54c483c..3a7132f01 100644 --- a/remoting/ios/client_keyboard.mm +++ b/remoting/ios/client_keyboard.mm
@@ -65,6 +65,10 @@ return YES; } +- (BOOL)resignFirstResponder { + return [self resignFirstResponderForced:NO]; +} + - (UIView*)inputAccessoryView { return nil; } @@ -89,7 +93,8 @@ if (self.isFirstResponder) { // Cause the app to reload inputView. - [self resignFirstResponder]; + + [self resignFirstResponderForced:YES]; [self becomeFirstResponder]; } } @@ -98,4 +103,21 @@ return _inputView == nil; } +#pragma mark - Private + +- (BOOL)resignFirstResponderForced:(BOOL)forced { + if (!forced && self.showsSoftKeyboard) { + // This translates the action of resigning first responder when the keyboard + // is showing into hiding the soft keyboard while keeping the view first + // responder. This is to allow the hide keyboard button on the soft keyboard + // to work properly with ClientKeyboard's soft keyboard logic, which calls + // resignFirstResponder. + // This may cause weird behavior if the superview has multiple responders + // (text views). + self.showsSoftKeyboard = NO; + return NO; + } + return [super resignFirstResponder]; +} + @end
diff --git a/sdch/BUILD.gn b/sdch/BUILD.gn index 76bbbd4..a86e33ca 100644 --- a/sdch/BUILD.gn +++ b/sdch/BUILD.gn
@@ -65,7 +65,6 @@ include_dirs = [ "ios" ] } else if (is_mac) { include_dirs = [ "mac" ] - defines = [ "OPEN_VCDIFF_USE_AUTO_PTR" ] } else if (is_win) { include_dirs = [ "win" ] }
diff --git a/services/device/battery/battery_status_manager_linux.cc b/services/device/battery/battery_status_manager_linux.cc index 6f4ca7b9..701f93c 100644 --- a/services/device/battery/battery_status_manager_linux.cc +++ b/services/device/battery/battery_status_manager_linux.cc
@@ -307,6 +307,10 @@ return status; } +void OnSignalConnectedDoNothing(const std::string& interface_name, + const std::string& signal_name, + bool success) {} + } // namespace // Class that represents a dedicated thread which communicates with DBus to @@ -314,7 +318,7 @@ class BatteryStatusManagerLinux::BatteryStatusNotificationThread : public base::Thread { public: - BatteryStatusNotificationThread( + explicit BatteryStatusNotificationThread( const BatteryStatusService::BatteryUpdateCallback& callback) : base::Thread(kBatteryNotifierThreadName), callback_(callback) {} @@ -345,14 +349,12 @@ kUPowerServiceName, kUPowerSignalDeviceAdded, base::Bind(&BatteryStatusNotificationThread::DeviceAdded, base::Unretained(this)), - base::Bind(&BatteryStatusNotificationThread::OnSignalConnected, - base::Unretained(this))); + base::Bind(&OnSignalConnectedDoNothing)); upower_->proxy()->ConnectToSignal( kUPowerServiceName, kUPowerSignalDeviceRemoved, base::Bind(&BatteryStatusNotificationThread::DeviceRemoved, base::Unretained(this)), - base::Bind(&BatteryStatusNotificationThread::OnSignalConnected, - base::Unretained(this))); + base::Bind(&OnSignalConnectedDoNothing)); FindBatteryDevice(); } @@ -365,7 +367,9 @@ void SetDBusForTesting(dbus::Bus* bus) { system_bus_ = bus; } private: - bool OnWatcherThread() { return task_runner()->BelongsToCurrentThread(); } + bool OnWatcherThread() const { + return task_runner()->BelongsToCurrentThread(); + } void InitDBus() { DCHECK(OnWatcherThread()); @@ -373,16 +377,20 @@ dbus::Bus::Options options; options.bus_type = dbus::Bus::SYSTEM; options.connection_type = dbus::Bus::PRIVATE; - system_bus_ = make_scoped_refptr(new dbus::Bus(options)); + system_bus_ = base::MakeRefCounted<dbus::Bus>(options); } bool IsDaemonVersionBelow_0_99() { + DCHECK(OnWatcherThread()); + base::Version daemon_version = upower_->properties()->daemon_version(); return daemon_version.IsValid() && daemon_version.CompareTo(base::Version("0.99")) < 0; } void FindBatteryDevice() { + DCHECK(OnWatcherThread()); + // If ShutdownDBusConnection() has been called, the DBus connection will be // destroyed eventually. In the meanwhile, pending tasks can still end up // calling this class. Ignore these calls. @@ -456,31 +464,26 @@ kUPowerDeviceInterfaceName, kUPowerDeviceSignalChanged, base::Bind(&BatteryStatusNotificationThread::BatteryChanged, base::Unretained(this)), - base::Bind(&BatteryStatusNotificationThread::OnSignalConnected, - base::Unretained(this))); + base::Bind(&OnSignalConnectedDoNothing)); } } void ShutdownDBusConnection() { DCHECK(OnWatcherThread()); - if (!system_bus_.get()) + if (!system_bus_) return; - battery_.reset(); // before the system_bus_ is shut down. + battery_.reset(); // before the |system_bus_| is shut down. upower_.reset(); // Shutdown DBus connection later because there may be pending tasks on // this thread. message_loop()->task_runner()->PostTask( FROM_HERE, base::Bind(&dbus::Bus::ShutdownAndBlock, system_bus_)); - system_bus_ = NULL; + system_bus_ = nullptr; } - void OnSignalConnected(const std::string& interface_name, - const std::string& signal_name, - bool success) {} - std::unique_ptr<BatteryObject> CreateBattery( const dbus::ObjectPath& device_path) { return base::MakeUnique<BatteryObject>( @@ -489,13 +492,17 @@ base::Unretained(this))); } - void DeviceAdded(dbus::Signal* signal /* unused */) { + void DeviceAdded(dbus::Signal* /* signal */) { + DCHECK(OnWatcherThread()); + // Re-iterate all devices to see if we need to monitor the added battery // instead of the currently monitored battery. FindBatteryDevice(); } void DeviceRemoved(dbus::Signal* signal) { + DCHECK(OnWatcherThread()); + if (!battery_) return; @@ -523,15 +530,18 @@ } if (!removed_device_path.IsValid() || - battery_->proxy()->object_path() == removed_device_path) + battery_->proxy()->object_path() == removed_device_path) { FindBatteryDevice(); + } } - void BatteryPropertyChanged(const std::string& property_name) { + void BatteryPropertyChanged(const std::string& /* property_name */) { + DCHECK(OnWatcherThread()); NotifyBatteryStatus(); } - void BatteryChanged(dbus::Signal* signal /* unsused */) { + void BatteryChanged(dbus::Signal* /* signal */) { + DCHECK(OnWatcherThread()); DCHECK(battery_); battery_->properties()->Invalidate(); NotifyBatteryStatus(); @@ -540,7 +550,7 @@ void NotifyBatteryStatus() { DCHECK(OnWatcherThread()); - if (!system_bus_.get() || !battery_ || notifying_battery_status_) + if (!system_bus_ || !battery_ || notifying_battery_status_) return; // If the system uses a UPower daemon older than version 0.99 @@ -556,7 +566,7 @@ notifying_battery_status_ = false; } - BatteryStatusService::BatteryUpdateCallback callback_; + const BatteryStatusService::BatteryUpdateCallback callback_; scoped_refptr<dbus::Bus> system_bus_; std::unique_ptr<UPowerObject> upower_; std::unique_ptr<BatteryObject> battery_;
diff --git a/services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.cc b/services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.cc index c46236a..c6f2866 100644 --- a/services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.cc +++ b/services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.cc
@@ -118,9 +118,12 @@ // angles. DCHECK(fusion_sensor_); - // Only generate a new sensor value when the accelerometer reading changes. - if (which_sensor_changed != mojom::SensorType::ACCELEROMETER) + // Not generating a new sensor value when the |fusion_sensor_|'s reporting + // mode is ON_CHANGE and the accelerometer reading doesn't change. + if (fusion_sensor_->GetReportingMode() == mojom::ReportingMode::ON_CHANGE && + which_sensor_changed != mojom::SensorType::ACCELEROMETER) { return false; + } SensorReading gravity_reading; SensorReading geomagnetic_reading; @@ -129,12 +132,12 @@ return false; } - double gravity_x = gravity_reading.values[0].value(); - double gravity_y = gravity_reading.values[1].value(); - double gravity_z = gravity_reading.values[2].value(); - double geomagnetic_x = geomagnetic_reading.values[0].value(); - double geomagnetic_y = geomagnetic_reading.values[1].value(); - double geomagnetic_z = geomagnetic_reading.values[2].value(); + double gravity_x = gravity_reading.accel.x; + double gravity_y = gravity_reading.accel.y; + double gravity_z = gravity_reading.accel.z; + double geomagnetic_x = geomagnetic_reading.magn.x; + double geomagnetic_y = geomagnetic_reading.magn.y; + double geomagnetic_z = geomagnetic_reading.magn.z; double alpha, beta, gamma; if (!ComputeAbsoluteOrientationEulerAnglesFromGravityAndGeomagnetic( @@ -143,10 +146,10 @@ return false; } - fused_reading->values[0].value() = beta; - fused_reading->values[1].value() = gamma; - fused_reading->values[2].value() = alpha; - fused_reading->values[3].value() = 0.0; + fused_reading->orientation_euler.x = beta; + fused_reading->orientation_euler.y = gamma; + fused_reading->orientation_euler.z = alpha; + return true; }
diff --git a/services/device/generic_sensor/generic_sensor_service_unittest.cc b/services/device/generic_sensor/generic_sensor_service_unittest.cc index 2c058ae..79147698 100644 --- a/services/device/generic_sensor/generic_sensor_service_unittest.cc +++ b/services/device/generic_sensor/generic_sensor_service_unittest.cc
@@ -52,7 +52,7 @@ // Only mocking the shared memory update for AMBIENT_LIGHT type is enough. if (GetType() == SensorType::AMBIENT_LIGHT) { // Set the shared buffer value as frequency for testing purpose. - reading.values[0] = configuration.frequency(); + reading.als.value = configuration.frequency(); UpdateSensorReading(reading, true); } return true; @@ -118,7 +118,7 @@ void SensorReadingChanged() override { UpdateReadingData(); if (check_value_) - std::move(check_value_).Run(GetReadingValue()); + std::move(check_value_).Run(reading_data_.als.value); if (quit_closure_) std::move(quit_closure_).Run(); } @@ -170,8 +170,6 @@ } private: - double GetReadingValue() { return reading_data_.values[0]; } - void UpdateReadingData() { memset(&reading_data_, 0, sizeof(SensorReading)); int read_attempts = 0;
diff --git a/services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.cc b/services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.cc index b8cced7a..8526240 100644 --- a/services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.cc +++ b/services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.cc
@@ -48,17 +48,17 @@ // First reading. if (initial_timestamp_ == 0.0) { - initial_timestamp_ = reading.timestamp; + initial_timestamp_ = reading.timestamp(); return false; } double delivery_rate = - (reading.timestamp - initial_timestamp_) / reading_updates_count_; + (reading.timestamp() - initial_timestamp_) / reading_updates_count_; double alpha = time_constant_ / (time_constant_ + delivery_rate); - double acceleration_x = reading.values[0].value(); - double acceleration_y = reading.values[1].value(); - double acceleration_z = reading.values[2].value(); + double acceleration_x = reading.accel.x; + double acceleration_y = reading.accel.y; + double acceleration_z = reading.accel.z; // Isolate gravity. gravity_x_ = alpha * gravity_x_ + (1 - alpha) * acceleration_x; @@ -66,9 +66,9 @@ gravity_z_ = alpha * gravity_z_ + (1 - alpha) * acceleration_z; // Get linear acceleration. - fused_reading->values[0].value() = acceleration_x - gravity_x_; - fused_reading->values[1].value() = acceleration_y - gravity_y_; - fused_reading->values[2].value() = acceleration_z - gravity_z_; + fused_reading->accel.x = acceleration_x - gravity_x_; + fused_reading->accel.y = acceleration_y - gravity_y_; + fused_reading->accel.z = acceleration_z - gravity_z_; return true; }
diff --git a/services/device/generic_sensor/linux/sensor_data_linux.cc b/services/device/generic_sensor/linux/sensor_data_linux.cc index 8134f7e..b29a2e6 100644 --- a/services/device/generic_sensor/linux/sensor_data_linux.cc +++ b/services/device/generic_sensor/linux/sensor_data_linux.cc
@@ -31,7 +31,7 @@ data->sensor_scale_name = "in_intensity_scale"; data->apply_scaling_func = base::Bind( [](double scaling_value, double offset, SensorReading& reading) { - reading.values[0] = scaling_value * (reading.values[0] + offset); + reading.als.value = scaling_value * (reading.als.value + offset); }); data->default_configuration = PlatformSensorConfiguration( SensorTraits<SensorType::AMBIENT_LIGHT>::kDefaultFrequency); @@ -80,9 +80,9 @@ data->apply_scaling_func = base::Bind( [](double scaling_value, double offset, SensorReading& reading) { double scaling = kMeanGravity / scaling_value; - reading.values[0] = scaling * (reading.values[0] + offset); - reading.values[1] = scaling * (reading.values[1] + offset); - reading.values[2] = scaling * (reading.values[2] + offset); + reading.accel.x = scaling * (reading.accel.x + offset); + reading.accel.y = scaling * (reading.accel.y + offset); + reading.accel.z = scaling * (reading.accel.z + offset); }); #else data->sensor_scale_name = "in_accel_scale"; @@ -91,9 +91,9 @@ data->apply_scaling_func = base::Bind( [](double scaling_value, double offset, SensorReading& reading) { // Adapt Linux reading values to generic sensor api specs. - reading.values[0] = -scaling_value * (reading.values[0] + offset); - reading.values[1] = -scaling_value * (reading.values[1] + offset); - reading.values[2] = -scaling_value * (reading.values[2] + offset); + reading.accel.x = -scaling_value * (reading.accel.x + offset); + reading.accel.y = -scaling_value * (reading.accel.y + offset); + reading.accel.z = -scaling_value * (reading.accel.z + offset); }); #endif @@ -117,9 +117,9 @@ [](double scaling_value, double offset, SensorReading& reading) { double scaling = kMeanGravity * kRadiansInDegrees / scaling_value; // Adapt CrOS reading values to generic sensor api specs. - reading.values[0] = -scaling * (reading.values[0] + offset); - reading.values[1] = -scaling * (reading.values[1] + offset); - reading.values[2] = -scaling * (reading.values[2] + offset); + reading.gyro.x = -scaling * (reading.gyro.x + offset); + reading.gyro.y = -scaling * (reading.gyro.y + offset); + reading.gyro.z = -scaling * (reading.gyro.z + offset); }); #else data->sensor_scale_name = "in_anglvel_scale"; @@ -127,9 +127,9 @@ data->sensor_frequency_file_name = "in_anglvel_sampling_frequency"; data->apply_scaling_func = base::Bind( [](double scaling_value, double offset, SensorReading& reading) { - reading.values[0] = scaling_value * (reading.values[0] + offset); - reading.values[1] = scaling_value * (reading.values[1] + offset); - reading.values[2] = scaling_value * (reading.values[2] + offset); + reading.gyro.x = scaling_value * (reading.gyro.x + offset); + reading.gyro.y = scaling_value * (reading.gyro.y + offset); + reading.gyro.z = scaling_value * (reading.gyro.z + offset); }); #endif @@ -152,9 +152,9 @@ data->apply_scaling_func = base::Bind( [](double scaling_value, double offset, SensorReading& reading) { double scaling = scaling_value * kMicroteslaInGauss; - reading.values[0] = scaling * (reading.values[0] + offset); - reading.values[1] = scaling * (reading.values[1] + offset); - reading.values[2] = scaling * (reading.values[2] + offset); + reading.magn.x = scaling * (reading.magn.x + offset); + reading.magn.y = scaling * (reading.magn.y + offset); + reading.magn.z = scaling * (reading.magn.z + offset); }); MaybeCheckKernelVersionAndAssignFileNames(file_names_x, file_names_y,
diff --git a/services/device/generic_sensor/linux/sensor_data_linux.h b/services/device/generic_sensor/linux/sensor_data_linux.h index 3e485b95..f3bd1a6 100644 --- a/services/device/generic_sensor/linux/sensor_data_linux.h +++ b/services/device/generic_sensor/linux/sensor_data_linux.h
@@ -10,7 +10,7 @@ namespace device { class PlatformSensorConfiguration; -struct SensorReading; +union SensorReading; // This structure represents a context that is used to identify a udev device // and create a type specific SensorInfoLinux. For example, when a
diff --git a/services/device/generic_sensor/linux/sensor_device_manager.cc b/services/device/generic_sensor/linux/sensor_device_manager.cc index fbc56b00..1e7a8eb 100644 --- a/services/device/generic_sensor/linux/sensor_device_manager.cc +++ b/services/device/generic_sensor/linux/sensor_device_manager.cc
@@ -103,7 +103,7 @@ } if (sensor_file_names.empty() || - sensor_file_names.size() > SensorReading::kValuesCount) + sensor_file_names.size() > SensorReadingRaw::kValuesCount) continue; const std::string scaling_value =
diff --git a/services/device/generic_sensor/orientation_euler_angles_fusion_algorithm_using_quaternion.cc b/services/device/generic_sensor/orientation_euler_angles_fusion_algorithm_using_quaternion.cc index 675a1a7..20c4ac3d 100644 --- a/services/device/generic_sensor/orientation_euler_angles_fusion_algorithm_using_quaternion.cc +++ b/services/device/generic_sensor/orientation_euler_angles_fusion_algorithm_using_quaternion.cc
@@ -81,16 +81,16 @@ if (!fusion_sensor_->GetLatestReading(0, &reading)) return false; - double x = reading.values[0].value(); - double y = reading.values[1].value(); - double z = reading.values[2].value(); - double w = reading.values[3].value(); + double x = reading.orientation_quat.x; + double y = reading.orientation_quat.y; + double z = reading.orientation_quat.z; + double w = reading.orientation_quat.w; double alpha, beta, gamma; ComputeEulerAnglesFromQuaternion(x, y, z, w, &alpha, &beta, &gamma); - fused_reading->values[0].value() = beta; - fused_reading->values[1].value() = gamma; - fused_reading->values[2].value() = alpha; - fused_reading->values[3].value() = 0.0; + + fused_reading->orientation_euler.x = beta; + fused_reading->orientation_euler.y = gamma; + fused_reading->orientation_euler.z = alpha; return true; }
diff --git a/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.cc b/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.cc index a1bb94f..139f848 100644 --- a/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.cc +++ b/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.cc
@@ -52,15 +52,15 @@ if (!fusion_sensor_->GetLatestReading(0, &reading)) return false; - double beta = reading.values[0].value(); - double gamma = reading.values[1].value(); - double alpha = reading.values[2].value(); + double beta = reading.orientation_euler.x; + double gamma = reading.orientation_euler.y; + double alpha = reading.orientation_euler.z; double x, y, z, w; ComputeQuaternionFromEulerAngles(alpha, beta, gamma, &x, &y, &z, &w); - fused_reading->values[0].value() = x; - fused_reading->values[1].value() = y; - fused_reading->values[2].value() = z; - fused_reading->values[3].value() = w; + fused_reading->orientation_quat.x = x; + fused_reading->orientation_quat.y = y; + fused_reading->orientation_quat.z = z; + fused_reading->orientation_quat.w = w; return true; }
diff --git a/services/device/generic_sensor/platform_sensor_accelerometer_mac.cc b/services/device/generic_sensor/platform_sensor_accelerometer_mac.cc index b2542db..bc0700e7 100644 --- a/services/device/generic_sensor/platform_sensor_accelerometer_mac.cc +++ b/services/device/generic_sensor/platform_sensor_accelerometer_mac.cc
@@ -23,12 +23,11 @@ bool IsSignificantlyDifferent(const device::SensorReading& reading1, const device::SensorReading& reading2) { - return (std::fabs(reading1.values[0] - reading2.values[0]) >= + return (std::fabs(reading1.accel.x - reading2.accel.x) >= kGravityThreshold) || - (std::fabs(reading1.values[1] - reading2.values[1]) >= + (std::fabs(reading1.accel.y - reading2.accel.y) >= kGravityThreshold) || - (std::fabs(reading1.values[2] - reading2.values[2]) >= - kGravityThreshold); + (std::fabs(reading1.accel.z - reading2.accel.z) >= kGravityThreshold); } } // namespace @@ -91,10 +90,11 @@ return; SensorReading reading; - reading.timestamp = (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); - reading.values[0] = axis_value[0] * kMeanGravity; - reading.values[1] = axis_value[1] * kMeanGravity; - reading.values[2] = axis_value[2] * kMeanGravity; + reading.accel.timestamp = + (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); + reading.accel.x = axis_value[0] * kMeanGravity; + reading.accel.y = axis_value[1] * kMeanGravity; + reading.accel.z = axis_value[2] * kMeanGravity; if (IsSignificantlyDifferent(reading_, reading)) { reading_ = reading;
diff --git a/services/device/generic_sensor/platform_sensor_ambient_light_mac.cc b/services/device/generic_sensor/platform_sensor_ambient_light_mac.cc index 2caac139..bb9208f 100644 --- a/services/device/generic_sensor/platform_sensor_ambient_light_mac.cc +++ b/services/device/generic_sensor/platform_sensor_ambient_light_mac.cc
@@ -168,8 +168,9 @@ current_lux_ = lux; SensorReading reading; - reading.timestamp = (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); - reading.values[0] = current_lux_; + reading.als.timestamp = + (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); + reading.als.value = current_lux_; UpdateSensorReading(reading, true); return true; }
diff --git a/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc b/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc index 1b663d5..1668e8e 100644 --- a/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc +++ b/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc
@@ -503,7 +503,7 @@ SensorReadingSharedBuffer* buffer = static_cast<SensorReadingSharedBuffer*>(mapping.get()); - EXPECT_THAT(buffer->reading.values[0], sensor_value[0]); + EXPECT_THAT(buffer->reading.als.value, sensor_value[0]); } // Tests that Accelerometer readings are correctly converted. @@ -545,16 +545,16 @@ static_cast<SensorReadingSharedBuffer*>(mapping.get()); #if defined(OS_CHROMEOS) double scaling = kMeanGravity / kAccelerometerScalingValue; - EXPECT_THAT(buffer->reading.values[0], scaling * sensor_values[0]); - EXPECT_THAT(buffer->reading.values[1], scaling * sensor_values[1]); - EXPECT_THAT(buffer->reading.values[2], scaling * sensor_values[2]); + EXPECT_THAT(buffer->reading.accel.x, scaling * sensor_values[0]); + EXPECT_THAT(buffer->reading.accel.y, scaling * sensor_values[1]); + EXPECT_THAT(buffer->reading.accel.z, scaling * sensor_values[2]); #else double scaling = kAccelerometerScalingValue; - EXPECT_THAT(buffer->reading.values[0], + EXPECT_THAT(buffer->reading.accel.x, -scaling * (sensor_values[0] + kAccelerometerOffsetValue)); - EXPECT_THAT(buffer->reading.values[1], + EXPECT_THAT(buffer->reading.accel.y, -scaling * (sensor_values[1] + kAccelerometerOffsetValue)); - EXPECT_THAT(buffer->reading.values[2], + EXPECT_THAT(buffer->reading.accel.z, -scaling * (sensor_values[2] + kAccelerometerOffsetValue)); #endif } @@ -596,16 +596,16 @@ static_cast<SensorReadingSharedBuffer*>(mapping.get()); #if defined(OS_CHROMEOS) double scaling = kMeanGravity * kRadiansInDegrees / kGyroscopeScalingValue; - EXPECT_THAT(buffer->reading.values[0], -scaling * sensor_values[0]); - EXPECT_THAT(buffer->reading.values[1], -scaling * sensor_values[1]); - EXPECT_THAT(buffer->reading.values[2], -scaling * sensor_values[2]); + EXPECT_THAT(buffer->reading.gyro.x, -scaling * sensor_values[0]); + EXPECT_THAT(buffer->reading.gyro.y, -scaling * sensor_values[1]); + EXPECT_THAT(buffer->reading.gyro.z, -scaling * sensor_values[2]); #else double scaling = kGyroscopeScalingValue; - EXPECT_THAT(buffer->reading.values[0], + EXPECT_THAT(buffer->reading.gyro.x, scaling * (sensor_values[0] + kGyroscopeOffsetValue)); - EXPECT_THAT(buffer->reading.values[1], + EXPECT_THAT(buffer->reading.gyro.y, scaling * (sensor_values[1] + kGyroscopeOffsetValue)); - EXPECT_THAT(buffer->reading.values[2], + EXPECT_THAT(buffer->reading.gyro.z, scaling * (sensor_values[2] + kGyroscopeOffsetValue)); #endif } @@ -647,11 +647,11 @@ SensorReadingSharedBuffer* buffer = static_cast<SensorReadingSharedBuffer*>(mapping.get()); double scaling = kMagnetometerScalingValue * kMicroteslaInGauss; - EXPECT_THAT(buffer->reading.values[0], + EXPECT_THAT(buffer->reading.magn.x, scaling * (sensor_values[0] + kMagnetometerOffsetValue)); - EXPECT_THAT(buffer->reading.values[1], + EXPECT_THAT(buffer->reading.magn.y, scaling * (sensor_values[1] + kMagnetometerOffsetValue)); - EXPECT_THAT(buffer->reading.values[2], + EXPECT_THAT(buffer->reading.magn.z, scaling * (sensor_values[2] + kMagnetometerOffsetValue)); }
diff --git a/services/device/generic_sensor/platform_sensor_and_provider_unittest_win.cc b/services/device/generic_sensor/platform_sensor_and_provider_unittest_win.cc index c69068d..02fc685 100644 --- a/services/device/generic_sensor/platform_sensor_and_provider_unittest_win.cc +++ b/services/device/generic_sensor/platform_sensor_and_provider_unittest_win.cc
@@ -584,9 +584,9 @@ base::RunLoop().RunUntilIdle(); SensorReadingSharedBuffer* buffer = static_cast<SensorReadingSharedBuffer*>(mapping.get()); - EXPECT_THAT(buffer->reading.values[0], -x_accel * kMeanGravity); - EXPECT_THAT(buffer->reading.values[1], -y_accel * kMeanGravity); - EXPECT_THAT(buffer->reading.values[2], -z_accel * kMeanGravity); + EXPECT_THAT(buffer->reading.accel.x, -x_accel * kMeanGravity); + EXPECT_THAT(buffer->reading.accel.y, -y_accel * kMeanGravity); + EXPECT_THAT(buffer->reading.accel.z, -z_accel * kMeanGravity); EXPECT_TRUE(sensor->StopListening(client.get(), configuration)); } @@ -624,9 +624,9 @@ base::RunLoop().RunUntilIdle(); SensorReadingSharedBuffer* buffer = static_cast<SensorReadingSharedBuffer*>(mapping.get()); - EXPECT_THAT(buffer->reading.values[0], -x_ang_accel * kRadiansInDegrees); - EXPECT_THAT(buffer->reading.values[1], -y_ang_accel * kRadiansInDegrees); - EXPECT_THAT(buffer->reading.values[2], -z_ang_accel * kRadiansInDegrees); + EXPECT_THAT(buffer->reading.gyro.x, -x_ang_accel * kRadiansInDegrees); + EXPECT_THAT(buffer->reading.gyro.y, -y_ang_accel * kRadiansInDegrees); + EXPECT_THAT(buffer->reading.gyro.z, -z_ang_accel * kRadiansInDegrees); EXPECT_TRUE(sensor->StopListening(client.get(), configuration)); } @@ -664,12 +664,9 @@ base::RunLoop().RunUntilIdle(); SensorReadingSharedBuffer* buffer = static_cast<SensorReadingSharedBuffer*>(mapping.get()); - EXPECT_THAT(buffer->reading.values[0], - -x_magn_field * kMicroteslaInMilligauss); - EXPECT_THAT(buffer->reading.values[1], - -y_magn_field * kMicroteslaInMilligauss); - EXPECT_THAT(buffer->reading.values[2], - -z_magn_field * kMicroteslaInMilligauss); + EXPECT_THAT(buffer->reading.magn.x, -x_magn_field * kMicroteslaInMilligauss); + EXPECT_THAT(buffer->reading.magn.y, -y_magn_field * kMicroteslaInMilligauss); + EXPECT_THAT(buffer->reading.magn.z, -z_magn_field * kMicroteslaInMilligauss); EXPECT_TRUE(sensor->StopListening(client.get(), configuration)); } @@ -710,9 +707,9 @@ SensorReadingSharedBuffer* buffer = static_cast<SensorReadingSharedBuffer*>(mapping.get()); - EXPECT_THAT(buffer->reading.values[0], x); - EXPECT_THAT(buffer->reading.values[1], y); - EXPECT_THAT(buffer->reading.values[2], z); + EXPECT_THAT(buffer->reading.orientation_euler.x, x); + EXPECT_THAT(buffer->reading.orientation_euler.y, y); + EXPECT_THAT(buffer->reading.orientation_euler.z, z); EXPECT_TRUE(sensor->StopListening(client.get(), configuration)); } @@ -758,10 +755,10 @@ SensorReadingSharedBuffer* buffer = static_cast<SensorReadingSharedBuffer*>(mapping.get()); - EXPECT_THAT(buffer->reading.values[0], -x); - EXPECT_THAT(buffer->reading.values[1], -y); - EXPECT_THAT(buffer->reading.values[2], -z); - EXPECT_THAT(buffer->reading.values[3], w); + EXPECT_THAT(buffer->reading.orientation_quat.x, -x); + EXPECT_THAT(buffer->reading.orientation_quat.y, -y); + EXPECT_THAT(buffer->reading.orientation_quat.z, -z); + EXPECT_THAT(buffer->reading.orientation_quat.w, w); EXPECT_TRUE(sensor->StopListening(client.get(), configuration)); }
diff --git a/services/device/generic_sensor/platform_sensor_android.cc b/services/device/generic_sensor/platform_sensor_android.cc index 45a54b97..5c611763 100644 --- a/services/device/generic_sensor/platform_sensor_android.cc +++ b/services/device/generic_sensor/platform_sensor_android.cc
@@ -87,11 +87,11 @@ jdouble value3, jdouble value4) { SensorReading reading; - reading.timestamp = timestamp; - reading.values[0] = value1; - reading.values[1] = value2; - reading.values[2] = value3; - reading.values[3] = value4; + reading.raw.timestamp = timestamp; + reading.raw.values[0] = value1; + reading.raw.values[1] = value2; + reading.raw.values[2] = value3; + reading.raw.values[3] = value4; bool needNotify = (GetReportingMode() == mojom::ReportingMode::ON_CHANGE); UpdateSensorReading(reading, needNotify);
diff --git a/services/device/generic_sensor/platform_sensor_fusion.cc b/services/device/generic_sensor/platform_sensor_fusion.cc index ec8ed50..b4d49ab 100644 --- a/services/device/generic_sensor/platform_sensor_fusion.cc +++ b/services/device/generic_sensor/platform_sensor_fusion.cc
@@ -35,11 +35,7 @@ } mojom::ReportingMode PlatformSensorFusion::GetReportingMode() { - for (const auto& sensor : source_sensors_) { - if (sensor->GetReportingMode() == mojom::ReportingMode::ON_CHANGE) - return mojom::ReportingMode::ON_CHANGE; - } - return mojom::ReportingMode::CONTINUOUS; + return reporting_mode_; } PlatformSensorConfiguration PlatformSensorFusion::GetDefaultConfiguration() { @@ -94,7 +90,8 @@ void PlatformSensorFusion::OnSensorReadingChanged(mojom::SensorType type) { SensorReading reading; - reading.timestamp = (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); + reading.raw.timestamp = + (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); if (!fusion_algorithm_->GetFusedData(type, &reading)) return; @@ -150,8 +147,13 @@ if (num_sensors_created_ != source_sensors_.size()) return; - for (const auto& sensor : source_sensors_) + reporting_mode_ = mojom::ReportingMode::CONTINUOUS; + + for (const auto& sensor : source_sensors_) { sensor->AddClient(this); + if (sensor->GetReportingMode() == mojom::ReportingMode::ON_CHANGE) + reporting_mode_ = mojom::ReportingMode::ON_CHANGE; + } fusion_algorithm_->set_fusion_sensor(this);
diff --git a/services/device/generic_sensor/platform_sensor_fusion.h b/services/device/generic_sensor/platform_sensor_fusion.h index 41eb3f1..fe9ea8d5 100644 --- a/services/device/generic_sensor/platform_sensor_fusion.h +++ b/services/device/generic_sensor/platform_sensor_fusion.h
@@ -73,6 +73,7 @@ // Repeating timer for data polling if all source sensors are CONTINUOUS // reporting mode. base::RepeatingTimer timer_; + mojom::ReportingMode reporting_mode_; DISALLOW_COPY_AND_ASSIGN(PlatformSensorFusion); };
diff --git a/services/device/generic_sensor/platform_sensor_fusion_algorithm.cc b/services/device/generic_sensor/platform_sensor_fusion_algorithm.cc index 7d9f9f7..0d2a398 100644 --- a/services/device/generic_sensor/platform_sensor_fusion_algorithm.cc +++ b/services/device/generic_sensor/platform_sensor_fusion_algorithm.cc
@@ -15,10 +15,12 @@ bool PlatformSensorFusionAlgorithm::IsReadingSignificantlyDifferent( const SensorReading& reading1, const SensorReading& reading2) { - return (std::fabs(reading1.values[0] - reading2.values[0]) >= threshold_) || - (std::fabs(reading1.values[1] - reading2.values[1]) >= threshold_) || - (std::fabs(reading1.values[2] - reading2.values[2]) >= threshold_) || - (std::fabs(reading1.values[3] - reading2.values[3]) >= threshold_); + for (size_t i = 0; i < SensorReadingRaw::kValuesCount; ++i) { + if (std::fabs(reading1.raw.values[i] - reading2.raw.values[i]) >= + threshold_) + return true; + } + return false; } void PlatformSensorFusionAlgorithm::Reset() {}
diff --git a/services/device/generic_sensor/platform_sensor_linux.cc b/services/device/generic_sensor/platform_sensor_linux.cc index 9c6ca71..27907348 100644 --- a/services/device/generic_sensor/platform_sensor_linux.cc +++ b/services/device/generic_sensor/platform_sensor_linux.cc
@@ -14,8 +14,11 @@ // Checks if at least one value has been changed. bool HaveValuesChanged(const SensorReading& lhs, const SensorReading& rhs) { - return lhs.values[0] != rhs.values[0] || lhs.values[1] != rhs.values[1] || - lhs.values[2] != rhs.values[2]; + for (size_t i = 0; i < SensorReadingRaw::kValuesCount; ++i) { + if (lhs.raw.values[i] != rhs.raw.values[i]) + return true; + } + return false; } } // namespace @@ -55,7 +58,8 @@ notifyNeeded = true; } old_values_ = reading; - reading.timestamp = (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); + reading.raw.timestamp = + (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); UpdateSensorReading(reading, notifyNeeded); }
diff --git a/services/device/generic_sensor/platform_sensor_reader_linux.cc b/services/device/generic_sensor/platform_sensor_reader_linux.cc index 521d780a..99326a3e 100644 --- a/services/device/generic_sensor/platform_sensor_reader_linux.cc +++ b/services/device/generic_sensor/platform_sensor_reader_linux.cc
@@ -98,7 +98,7 @@ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); SensorReading readings; - DCHECK_LE(sensor_file_paths_.size(), arraysize(readings.values)); + DCHECK_LE(sensor_file_paths_.size(), arraysize(readings.raw.values)); int i = 0; for (const auto& path : sensor_file_paths_) { std::string new_read_value; @@ -115,7 +115,7 @@ StopFetchingData(); return; } - readings.values[i++] = new_value; + readings.raw.values[i++] = new_value; } if (!apply_scaling_func_.is_null()) apply_scaling_func_.Run(scaling_value_, offset_value_, readings);
diff --git a/services/device/generic_sensor/platform_sensor_reader_win.cc b/services/device/generic_sensor/platform_sensor_reader_win.cc index 10268c9..efb0678 100644 --- a/services/device/generic_sensor/platform_sensor_reader_win.cc +++ b/services/device/generic_sensor/platform_sensor_reader_win.cc
@@ -65,7 +65,7 @@ report, &lux)) { return E_FAIL; } - reading->values[0] = lux; + reading->als.value = lux; return S_OK; }; return params; @@ -92,9 +92,9 @@ // Windows uses coordinate system where Z axis points down from device // screen, therefore, using right hand notation, we have to reverse // sign for each axis. Values are converted from G/s^2 to m/s^2. - reading->values[0] = -x * kMeanGravity; - reading->values[1] = -y * kMeanGravity; - reading->values[2] = -z * kMeanGravity; + reading->accel.x = -x * kMeanGravity; + reading->accel.y = -y * kMeanGravity; + reading->accel.z = -z * kMeanGravity; return S_OK; }; return params; @@ -124,9 +124,9 @@ // Windows uses coordinate system where Z axis points down from device // screen, therefore, using right hand notation, we have to reverse // sign for each axis. Values are converted from deg to rad. - reading->values[0] = -x * kRadiansInDegrees; - reading->values[1] = -y * kRadiansInDegrees; - reading->values[2] = -z * kRadiansInDegrees; + reading->gyro.x = -x * kRadiansInDegrees; + reading->gyro.y = -y * kRadiansInDegrees; + reading->gyro.z = -z * kRadiansInDegrees; return S_OK; }; return params; @@ -157,9 +157,9 @@ // screen, therefore, using right hand notation, we have to reverse // sign for each axis. Values are converted from Milligaus to // Microtesla. - reading->values[0] = -x * kMicroteslaInMilligauss; - reading->values[1] = -y * kMicroteslaInMilligauss; - reading->values[2] = -z * kMicroteslaInMilligauss; + reading->magn.x = -x * kMicroteslaInMilligauss; + reading->magn.y = -y * kMicroteslaInMilligauss; + reading->magn.z = -z * kMicroteslaInMilligauss; return S_OK; }; return params; @@ -184,9 +184,9 @@ return E_FAIL; } - reading->values[0] = x; - reading->values[1] = y; - reading->values[2] = z; + reading->orientation_euler.x = x; + reading->orientation_euler.y = y; + reading->orientation_euler.z = z; return S_OK; }; return params; @@ -212,10 +212,10 @@ // Windows uses coordinate system where Z axis points down from device // screen, therefore, using right hand notation, we have to reverse // sign for each quaternion component. - reading->values[0] = -quat[0]; // x*sin(Theta/2) - reading->values[1] = -quat[1]; // y*sin(Theta/2) - reading->values[2] = -quat[2]; // z*sin(Theta/2) - reading->values[3] = quat[3]; // cos(Theta/2) + reading->orientation_quat.x = -quat[0]; // x*sin(Theta/2) + reading->orientation_quat.y = -quat[1]; // y*sin(Theta/2) + reading->orientation_quat.z = -quat[2]; // z*sin(Theta/2) + reading->orientation_quat.w = quat[3]; // cos(Theta/2) return S_OK; }; return params; @@ -333,10 +333,11 @@ base::TimeDelta delta = time_now - timestamp; SensorReading reading; - reading.timestamp = ((ticks_now - delta) - base::TimeTicks()).InSecondsF(); + reading.raw.timestamp = + ((ticks_now - delta) - base::TimeTicks()).InSecondsF(); // Discard update events that have non-monotonically increasing timestamp. - if (last_sensor_reading_.timestamp > reading.timestamp) + if (last_sensor_reading_.raw.timestamp > reading.timestamp()) return E_FAIL; hr = platform_sensor_reader_->SensorReadingChanged(report, &reading);
diff --git a/services/device/generic_sensor/platform_sensor_reader_win.h b/services/device/generic_sensor/platform_sensor_reader_win.h index 632a0c37..2823d999 100644 --- a/services/device/generic_sensor/platform_sensor_reader_win.h +++ b/services/device/generic_sensor/platform_sensor_reader_win.h
@@ -14,7 +14,7 @@ class PlatformSensorConfiguration; struct ReaderInitParams; -struct SensorReading; +union SensorReading; // Generic class that uses ISensor interface to fetch sensor data. Used // by PlatformSensorWin and delivers notifications via Client interface.
diff --git a/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer.cc b/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer.cc index 8bd7df8..c0a29e7b 100644 --- a/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer.cc +++ b/services/device/generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer.cc
@@ -48,18 +48,17 @@ if (!fusion_sensor_->GetLatestReading(0, &reading)) return false; - double acceleration_x = reading.values[0].value(); - double acceleration_y = reading.values[1].value(); - double acceleration_z = reading.values[2].value(); + double acceleration_x = reading.accel.x; + double acceleration_y = reading.accel.y; + double acceleration_z = reading.accel.z; double alpha = 0.0; double beta = std::atan2(-acceleration_y, acceleration_z); double gamma = std::asin(acceleration_x / kMeanGravity); - fused_reading->values[0].value() = beta; - fused_reading->values[1].value() = gamma; - fused_reading->values[2].value() = alpha; - fused_reading->values[3].value() = 0.0; + fused_reading->orientation_euler.x = beta; + fused_reading->orientation_euler.y = gamma; + fused_reading->orientation_euler.z = alpha; return true; }
diff --git a/services/device/public/cpp/generic_sensor/sensor_reading.cc b/services/device/public/cpp/generic_sensor/sensor_reading.cc index 85b2c36..36b560cf 100644 --- a/services/device/public/cpp/generic_sensor/sensor_reading.cc +++ b/services/device/public/cpp/generic_sensor/sensor_reading.cc
@@ -6,13 +6,31 @@ namespace device { -SensorReading::SensorReading() = default; -SensorReading::SensorReading(const SensorReading& other) = default; -SensorReading::~SensorReading() = default; +SensorReadingRaw::SensorReadingRaw() = default; +SensorReadingRaw::~SensorReadingRaw() = default; + +SensorReadingBase::SensorReadingBase() = default; +SensorReadingBase::~SensorReadingBase() = default; + +SensorReadingSingle::SensorReadingSingle() = default; +SensorReadingSingle::~SensorReadingSingle() = default; + +SensorReadingXYZ::SensorReadingXYZ() = default; +SensorReadingXYZ::~SensorReadingXYZ() = default; + +SensorReadingQuat::SensorReadingQuat() = default; +SensorReadingQuat::~SensorReadingQuat() = default; SensorReadingSharedBuffer::SensorReadingSharedBuffer() = default; SensorReadingSharedBuffer::~SensorReadingSharedBuffer() = default; +SensorReading::SensorReading() { + new (&raw) SensorReadingRaw(); +} +SensorReading::~SensorReading() { + raw.~SensorReadingRaw(); +} + // static uint64_t SensorReadingSharedBuffer::GetOffset(mojom::SensorType type) { return (static_cast<uint64_t>(mojom::SensorType::LAST) -
diff --git a/services/device/public/cpp/generic_sensor/sensor_reading.h b/services/device/public/cpp/generic_sensor/sensor_reading.h index e571a738..ed146db 100644 --- a/services/device/public/cpp/generic_sensor/sensor_reading.h +++ b/services/device/public/cpp/generic_sensor/sensor_reading.h
@@ -38,96 +38,150 @@ Storage storage_; }; -// This structure represents sensor reading data: timestamp and 4 values. -struct SensorReading { - SensorReading(); - ~SensorReading(); - SensorReading(const SensorReading& other); +struct SensorReadingBase { + SensorReadingBase(); + ~SensorReadingBase(); SensorReadingField<double> timestamp; - constexpr static int kValuesCount = 4; - // AMBIENT_LIGHT: - // values[0]: ambient light level in SI lux units. - // - // PROXIMITY: - // values[0]: proximity sensor distance measured in centimeters. - // - // ACCELEROMETER: - // values[0]: acceleration minus Gx on the x-axis in SI meters per second - // squared (m/s^2) units. - // values[1]: acceleration minus Gy on the y-axis in SI meters per second - // squared (m/s^2) units. - // values[2]: acceleration minus Gz on the z-axis in SI meters per second - // squared (m/s^2) units. - // - // LINEAR_ACCELERATION: - // values[0]: acceleration on the x-axis in SI meters per second squared - // (m/s^2) units. - // values[1]: acceleration on the y-axis in SI meters per second squared - // (m/s^2) units. - // values[2]: acceleration on the z-axis in SI meters per second squared - // (m/s^2) units. - // - // GYROSCOPE: - // values[0]: angular speed around the x-axis in radians/second. - // values[1]: angular speed around the y-axis in radians/second. - // values[2]: angular speed around the z-axis in radians/second. - // - // MAGNETOMETER: - // values[0]: ambient magnetic field in the x-axis in micro-Tesla (uT). - // values[1]: ambient magnetic field in the y-axis in micro-Tesla (uT). - // values[2]: ambient magnetic field in the z-axis in micro-Tesla (uT). - // - // PRESSURE: - // values[0]: atmospheric pressure in hPa (millibar). - // - // ABSOLUTE_ORIENTATION_EULER_ANGLES: - // values[0]: x-axis angle in degrees representing the orientation of the - // device in 3D space. It corresponds to the beta value in the W3C - // DeviceOrientation Event Specification. This value is in [180, 180). - // values[1]: y-axis angle in degrees representing the orientation of the - // device in 3D space. It corresponds to the gamma value in the W3C - // DeviceOrientation Event Specification. This value is in [-90, 90). - // values[2]: z-axis angle in degrees representing the orientation of the - // device in 3D space. It corresponds to the alpha value in the W3C - // DeviceOrientation Event Specification. This value is in [0, 360). - // - // ABSOLUTE_ORIENTATION_QUATERNION: - // values[0]: x value of a quaternion representing the orientation of the - // device in 3D space. - // values[1]: y value of a quaternion representing the orientation of the - // device in 3D space. - // values[2]: z value of a quaternion representing the orientation of the - // device in 3D space. - // values[3]: w value of a quaternion representing the orientation of the - // device in 3D space. - // - // RELATIVE_ORIENTATION_EULER_ANGLES: - // (Identical to ABSOLUTE_ORIENTATION_EULER_ANGLES except that it doesn't use - // the geomagnetic field.) - // values[0]: x-axis angle in degrees representing the orientation of the - // device in 3D space. It corresponds to the beta value in the W3C - // DeviceOrientation Event Specification. This value is in [180, 180). - // values[1]: y-axis angle in degrees representing the orientation of the - // device in 3D space. It corresponds to the gamma value in the W3C - // DeviceOrientation Event Specification. This value is in [-90, 90). - // values[2]: z-axis angle in degrees representing the orientation of the - // device in 3D space. It corresponds to the alpha value in the W3C - // DeviceOrientation Event Specification. This value is in [0, 360). - // - // RELATIVE_ORIENTATION_QUATERNION: - // (Identical to ABSOLUTE_ORIENTATION_QUATERNION except that it doesn't use - // the geomagnetic field.) - // values[0]: x value of a quaternion representing the orientation of the - // device in 3D space. - // values[1]: y value of a quaternion representing the orientation of the - // device in 3D space. - // values[2]: z value of a quaternion representing the orientation of the - // device in 3D space. - // values[3]: w value of a quaternion representing the orientation of the - // device in 3D space. +}; + +// Represents raw sensor reading data: timestamp and 4 values. +struct SensorReadingRaw : public SensorReadingBase { + SensorReadingRaw(); + ~SensorReadingRaw(); + + constexpr static size_t kValuesCount = 4; SensorReadingField<double> values[kValuesCount]; }; +// Represents a single data value. +struct SensorReadingSingle : public SensorReadingBase { + SensorReadingSingle(); + ~SensorReadingSingle(); + SensorReadingField<double> value; +}; + +// Represents a vector in 3d coordinate system. +struct SensorReadingXYZ : public SensorReadingBase { + SensorReadingXYZ(); + ~SensorReadingXYZ(); + SensorReadingField<double> x; + SensorReadingField<double> y; + SensorReadingField<double> z; +}; + +// Represents quaternion. +struct SensorReadingQuat : public SensorReadingXYZ { + SensorReadingQuat(); + ~SensorReadingQuat(); + SensorReadingField<double> w; +}; + +// A common type to represent sensor reading. +// For every implemented sensor type, the reading is stored as described below: +// +// AMBIENT_LIGHT: +// als.value: ambient light level in SI lux units. +// +// PROXIMITY: +// proximity.value: proximity sensor distance measured in centimeters. +// +// ACCELEROMETER: +// accel.x: acceleration minus Gx on the x-axis in SI meters per second +// squared (m/s^2) units. +// accel.y: acceleration minus Gy on the y-axis in SI meters per second +// squared (m/s^2) units. +// accel.z: acceleration minus Gz on the z-axis in SI meters per second +// squared (m/s^2) units. +// +// LINEAR_ACCELERATION: +// accel.x: acceleration on the x-axis in SI meters per second squared +// (m/s^2) units. +// accel.y: acceleration on the y-axis in SI meters per second squared +// (m/s^2) units. +// accel.z: acceleration on the z-axis in SI meters per second squared +// (m/s^2) units. +// +// GYROSCOPE: +// gyro.x: angular speed around the x-axis in radians/second. +// gyro.y: angular speed around the y-axis in radians/second. +// gyro.z: angular speed around the z-axis in radians/second. +// +// MAGNETOMETER: +// magn.x: ambient magnetic field in the x-axis in micro-Tesla (uT). +// magn.y: ambient magnetic field in the y-axis in micro-Tesla (uT). +// magn.z: ambient magnetic field in the z-axis in micro-Tesla (uT). +// +// PRESSURE: +// pressure.value: atmospheric pressure in hPa (millibar). +// +// ABSOLUTE_ORIENTATION_EULER_ANGLES: +// orientation_euler.x: x-axis angle in degrees representing the orientation of +// the device in 3D space. It corresponds to the beta value in the W3C +// DeviceOrientation Event Specification. This value is in [180, 180). +// orientation_euler.y: y-axis angle in degrees representing the orientation of +// the device in 3D space. It corresponds to the gamma value in the W3C +// DeviceOrientation Event Specification. This value is in [-90, 90). +// orientation_euler.z: z-axis angle in degrees representing the orientation of +// the device in 3D space. It corresponds to the alpha value in the W3C +// DeviceOrientation Event Specification. This value is in [0, 360). +// +// ABSOLUTE_ORIENTATION_QUATERNION: +// orientation_quat.x: x value of a quaternion representing the orientation of +// the device in 3D space. +// orientation_quat.y: y value of a quaternion representing the orientation of +// the device in 3D space. +// orientation_quat.z: z value of a quaternion representing the orientation of +// the device in 3D space. +// orientation_quat.w: w value of a quaternion representing the orientation of +// the device in 3D space. +// +// RELATIVE_ORIENTATION_EULER_ANGLES: +// (Identical to ABSOLUTE_ORIENTATION_EULER_ANGLES except that it doesn't use +// the geomagnetic field.) +// orientation_euler.x: x-axis angle in degrees representing the orientation of +// the device in 3D space. It corresponds to the beta value in the W3C +// DeviceOrientation Event Specification. This value is in [180, 180). +// orientation_euler.y: y-axis angle in degrees representing the orientation of +// the device in 3D space. It corresponds to the gamma value in the W3C +// DeviceOrientation Event Specification. This value is in [-90, 90). +// orientation_euler.z: z-axis angle in degrees representing the orientation of +// the device in 3D space. It corresponds to the alpha value in the W3C +// DeviceOrientation Event Specification. This value is in [0, 360). +// +// RELATIVE_ORIENTATION_QUATERNION: +// (Identical to ABSOLUTE_ORIENTATION_QUATERNION except that it doesn't use +// the geomagnetic field.) +// orientation_quat.x: x value of a quaternion representing the orientation of +// the device in 3D space. +// orientation_quat.y: y value of a quaternionrepresenting the orientation of +// the device in 3D space. +// orientation_quat.z: z value of a quaternion representing the orientation of +// the device in 3D space. +// orientation_quat.w: w value of a quaternion representing the orientation of +// the device in 3D space. + +union SensorReading { + SensorReadingRaw raw; + SensorReadingSingle als; // AMBIENT_LIGHT + SensorReadingSingle proximity; // PROXIMITY + SensorReadingSingle pressure; // PRESSURE + SensorReadingXYZ accel; // ACCELEROMETER, LINEAR_ACCELERATION + SensorReadingXYZ gyro; // GYROSCOPE + SensorReadingXYZ magn; // MAGNETOMETER + SensorReadingQuat orientation_quat; // ABSOLUTE_ORIENTATION_QUATERNION, + // RELATIVE_ORIENTATION_QUATERNION + SensorReadingXYZ orientation_euler; // ABSOLUTE_ORIENTATION_EULER_ANGLES, + // RELATIVE_ORIENTATION_EULER_ANGLES + + double timestamp() const { return raw.timestamp; } + + SensorReading(); + ~SensorReading(); +}; + +static_assert(sizeof(SensorReading) == sizeof(SensorReadingRaw), + "Check SensorReading size."); + // This structure represents sensor reading buffer: sensor reading and seqlock // for synchronization. struct SensorReadingSharedBuffer {
diff --git a/services/resource_coordinator/coordination_unit/coordination_unit_graph_observer.h b/services/resource_coordinator/coordination_unit/coordination_unit_graph_observer.h index 28fe1cb..00494788 100644 --- a/services/resource_coordinator/coordination_unit/coordination_unit_graph_observer.h +++ b/services/resource_coordinator/coordination_unit/coordination_unit_graph_observer.h
@@ -77,16 +77,24 @@ int64_t value) {} // Called whenever a property of the FrameCoordinationUnit is changed. - virtual void OnFramePropertyChanged( - const FrameCoordinationUnitImpl* coordination_unit, - const mojom::PropertyType property_type, - int64_t value) {} + virtual void OnFramePropertyChanged(const FrameCoordinationUnitImpl* frame_cu, + const mojom::PropertyType property_type, + int64_t value) {} + // Called whenever a property of the WebContentsCoordinationUnit is changed. virtual void OnWebContentsPropertyChanged( - const WebContentsCoordinationUnitImpl* coordination_unit, + const WebContentsCoordinationUnitImpl* web_contents_cu, const mojom::PropertyType property_type, int64_t value) {} + // Called whenever an event is received in |coordination_unit| if the + // |coordination_unit| doesn't implement its own EventReceived handler. + virtual void OnEventReceived(const CoordinationUnitImpl* coordination_unit, + const mojom::Event event) {} + virtual void OnWebContentsEventReceived( + const WebContentsCoordinationUnitImpl* web_contents_cu, + const mojom::Event event) {} + void set_coordination_unit_manager( CoordinationUnitManager* coordination_unit_manager) { coordination_unit_manager_ = coordination_unit_manager;
diff --git a/services/resource_coordinator/coordination_unit/coordination_unit_impl.cc b/services/resource_coordinator/coordination_unit/coordination_unit_impl.cc index 9e8ab57..eb78e53 100644 --- a/services/resource_coordinator/coordination_unit/coordination_unit_impl.cc +++ b/services/resource_coordinator/coordination_unit/coordination_unit_impl.cc
@@ -165,22 +165,23 @@ policy_callback_->SetCoordinationPolicy(std::move(policy)); } -void CoordinationUnitImpl::SendEvent(mojom::EventPtr event) { +void CoordinationUnitImpl::SendEvent(mojom::Event event) { + OnEventReceived(event); // TODO(crbug.com/691886) Consider removing the following code. - switch (event->type) { - case mojom::EventType::kOnWebContentsShown: + switch (event) { + case mojom::Event::kOnWebContentsShown: state_flags_[kTabVisible] = true; break; - case mojom::EventType::kOnWebContentsHidden: + case mojom::Event::kOnWebContentsHidden: state_flags_[kTabVisible] = false; break; - case mojom::EventType::kOnProcessAudioStarted: + case mojom::Event::kOnProcessAudioStarted: state_flags_[kAudioPlaying] = true; break; - case mojom::EventType::kOnProcessAudioStopped: + case mojom::Event::kOnProcessAudioStopped: state_flags_[kAudioPlaying] = false; break; - case mojom::EventType::kTestEvent: + case mojom::Event::kTestEvent: state_flags_[kTestState] = true; break; default: @@ -407,6 +408,11 @@ observers_.RemoveObserver(observer); } +void CoordinationUnitImpl::OnEventReceived(const mojom::Event event) { + for (auto& observer : observers_) + observer.OnEventReceived(this, event); +} + void CoordinationUnitImpl::OnPropertyChanged( const mojom::PropertyType property_type, int64_t value) {
diff --git a/services/resource_coordinator/coordination_unit/coordination_unit_impl.h b/services/resource_coordinator/coordination_unit/coordination_unit_impl.h index 089d4ef..d06e82b 100644 --- a/services/resource_coordinator/coordination_unit/coordination_unit_impl.h +++ b/services/resource_coordinator/coordination_unit/coordination_unit_impl.h
@@ -53,11 +53,11 @@ void Bind(mojom::CoordinationUnitRequest request); // Overridden from mojom::CoordinationUnit: - void SendEvent(mojom::EventPtr event) override; void GetID(const GetIDCallback& callback) override; void AddBinding(mojom::CoordinationUnitRequest request) override; void AddChild(const CoordinationUnitID& child_id) override; void RemoveChild(const CoordinationUnitID& child_id) override; + void SendEvent(mojom::Event event) override; void SetProperty(mojom::PropertyType property_type, int64_t value) override; // TODO(crbug.com/691886) Consider removing this. void SetCoordinationPolicyCallback( @@ -92,6 +92,7 @@ protected: friend class FrameCoordinationUnitImpl; + virtual void OnEventReceived(const mojom::Event event); virtual void OnPropertyChanged(const mojom::PropertyType property_type, int64_t value); // Propagate property change to relevant |CoordinationUnitImpl| instances.
diff --git a/services/resource_coordinator/coordination_unit/coordination_unit_impl_unittest.cc b/services/resource_coordinator/coordination_unit/coordination_unit_impl_unittest.cc index f874868..891bc76 100644 --- a/services/resource_coordinator/coordination_unit/coordination_unit_impl_unittest.cc +++ b/services/resource_coordinator/coordination_unit/coordination_unit_impl_unittest.cc
@@ -70,9 +70,7 @@ void ForcePolicyUpdates() { base::RunLoop callback; SetPolicyClosure(callback.QuitClosure()); - mojom::EventPtr event = mojom::Event::New(); - event->type = mojom::EventType::kTestEvent; - coordination_unit_->SendEvent(std::move(event)); + coordination_unit_->SendEvent(mojom::Event::kTestEvent); callback.Run(); } @@ -131,9 +129,7 @@ child_unit.SetPolicyClosure(child_callback.QuitClosure()); // This event should force the policy to recalculated for all children. - mojom::EventPtr event = mojom::Event::New(); - event->type = mojom::EventType::kTestEvent; - parent_unit.interface()->SendEvent(std::move(event)); + parent_unit.interface()->SendEvent(mojom::Event::kTestEvent); parent_callback.Run(); child_callback.Run();
diff --git a/services/resource_coordinator/coordination_unit/metrics_collector.cc b/services/resource_coordinator/coordination_unit/metrics_collector.cc index 7120569..af53d392 100644 --- a/services/resource_coordinator/coordination_unit/metrics_collector.cc +++ b/services/resource_coordinator/coordination_unit/metrics_collector.cc
@@ -29,6 +29,8 @@ const char kTabFromBackgroundedToFirstAudioStartsUMA[] = "TabManager.Heuristics.FromBackgroundedToFirstAudioStarts"; +const char kTabFromBackgroundedToFirstTitleUpdatedUMA[] = + "TabManager.Heuristics.FromBackgroundedToFirstTitleUpdated"; // Gets the number of tabs that are co-resident in all of the render processes // associated with a |CoordinationUnitType::kWebContents| coordination unit. @@ -74,31 +76,29 @@ } void MetricsCollector::OnFramePropertyChanged( - const FrameCoordinationUnitImpl* frame_coordination_unit, + const FrameCoordinationUnitImpl* frame_cu, const mojom::PropertyType property_type, int64_t value) { - FrameData& frame_data = frame_data_map_[frame_coordination_unit->id()]; + FrameData& frame_data = frame_data_map_[frame_cu->id()]; if (property_type == mojom::PropertyType::kAudible) { bool audible = static_cast<bool>(value); if (!audible) { frame_data.last_audible_time = clock_->NowTicks(); return; } - auto* web_contents_coordination_unit = - frame_coordination_unit->GetWebContentsCoordinationUnit(); + auto* web_contents_cu = frame_cu->GetWebContentsCoordinationUnit(); // Only record metrics while it is backgrounded. - if (!web_contents_coordination_unit || - web_contents_coordination_unit->IsVisible()) + if (!web_contents_cu || web_contents_cu->IsVisible()) return; // Audio is considered to have started playing if the tab has never // previously played audio, or has been silent for at least one minute. auto now = clock_->NowTicks(); if (frame_data.last_audible_time + kMaxAudioSlientTime < now) { MetricsReportRecord& record = - metrics_report_record_map_[web_contents_coordination_unit->id()]; - const WebContentsData web_contents_data = - web_contents_data_map_[web_contents_coordination_unit->id()]; + metrics_report_record_map_[web_contents_cu->id()]; if (!record.first_audible_after_backgrounded_reported) { + const WebContentsData web_contents_data = + web_contents_data_map_[web_contents_cu->id()]; HEURISTICS_HISTOGRAM(kTabFromBackgroundedToFirstAudioStartsUMA, now - web_contents_data.last_invisible_time); record.first_audible_after_backgrounded_reported = true; @@ -108,24 +108,24 @@ } void MetricsCollector::OnWebContentsPropertyChanged( - const WebContentsCoordinationUnitImpl* web_contents_coordination_unit, + const WebContentsCoordinationUnitImpl* web_contents_cu, const mojom::PropertyType property_type, int64_t value) { - const auto web_contents_cu_id = web_contents_coordination_unit->id(); + const auto web_contents_cu_id = web_contents_cu->id(); if (property_type == mojom::PropertyType::kVisible) { if (value) { // The web contents becomes visible again, clear all record in order to // report metrics when web contents becomes invisible next time. - ResetMetricsReportRecord(web_contents_coordination_unit->id()); + ResetMetricsReportRecord(web_contents_cu_id); return; } web_contents_data_map_[web_contents_cu_id].last_invisible_time = clock_->NowTicks(); } else if (property_type == mojom::PropertyType::kCPUUsage) { if (IsCollectingCPUUsageForUkm(web_contents_cu_id)) { - RecordCPUUsageForUkm( - web_contents_cu_id, static_cast<double>(value) / 1000, - GetNumCoresidentTabs(web_contents_coordination_unit)); + RecordCPUUsageForUkm(web_contents_cu_id, + static_cast<double>(value) / 1000, + GetNumCoresidentTabs(web_contents_cu)); } } else if (property_type == mojom::PropertyType::kUKMSourceId) { ukm::SourceId ukm_source_id = value; @@ -134,6 +134,26 @@ } } +void MetricsCollector::OnWebContentsEventReceived( + const WebContentsCoordinationUnitImpl* web_contents_cu, + const mojom::Event event) { + if (event == mojom::Event::kTitleUpdated) { + // Only record metrics while it is backgrounded. + if (web_contents_cu->IsVisible()) + return; + auto now = clock_->NowTicks(); + MetricsReportRecord& record = + metrics_report_record_map_[web_contents_cu->id()]; + if (!record.first_title_updated_after_backgrounded_reported) { + const WebContentsData web_contents_data = + web_contents_data_map_[web_contents_cu->id()]; + HEURISTICS_HISTOGRAM(kTabFromBackgroundedToFirstTitleUpdatedUMA, + now - web_contents_data.last_invisible_time); + record.first_title_updated_after_backgrounded_reported = true; + } + } +} + bool MetricsCollector::IsCollectingCPUUsageForUkm( const CoordinationUnitID& web_contents_cu_id) { UkmCPUUsageCollectionState& state = @@ -186,10 +206,12 @@ } MetricsCollector::MetricsReportRecord::MetricsReportRecord() - : first_audible_after_backgrounded_reported(false) {} + : first_audible_after_backgrounded_reported(false), + first_title_updated_after_backgrounded_reported(false) {} void MetricsCollector::MetricsReportRecord::Reset() { first_audible_after_backgrounded_reported = false; + first_title_updated_after_backgrounded_reported = false; } } // namespace resource_coordinator
diff --git a/services/resource_coordinator/coordination_unit/metrics_collector.h b/services/resource_coordinator/coordination_unit/metrics_collector.h index 39cb7cc63..d30e554 100644 --- a/services/resource_coordinator/coordination_unit/metrics_collector.h +++ b/services/resource_coordinator/coordination_unit/metrics_collector.h
@@ -18,6 +18,7 @@ class WebContentsCoordinationUnitImpl; extern const char kTabFromBackgroundedToFirstAudioStartsUMA[]; +extern const char kTabFromBackgroundedToFirstTitleUpdatedUMA[]; // A MetricsCollector observes changes happened inside CoordinationUnit Graph, // and reports UMA/UKM. @@ -30,14 +31,16 @@ bool ShouldObserve(const CoordinationUnitImpl* coordination_unit) override; void OnBeforeCoordinationUnitDestroyed( const CoordinationUnitImpl* coordination_unit) override; - void OnFramePropertyChanged( - const FrameCoordinationUnitImpl* frame_coordination_unit, - const mojom::PropertyType property_type, - int64_t value) override; + void OnFramePropertyChanged(const FrameCoordinationUnitImpl* frame_cu, + const mojom::PropertyType property_type, + int64_t value) override; void OnWebContentsPropertyChanged( - const WebContentsCoordinationUnitImpl* web_contents_coordination_unit, + const WebContentsCoordinationUnitImpl* web_contents_cu, const mojom::PropertyType property_type, int64_t value) override; + void OnWebContentsEventReceived( + const WebContentsCoordinationUnitImpl* web_contents_cu, + const mojom::Event event) override; private: friend class MetricsCollectorTest; @@ -46,6 +49,7 @@ MetricsReportRecord(); void Reset(); bool first_audible_after_backgrounded_reported; + bool first_title_updated_after_backgrounded_reported; }; struct FrameData {
diff --git a/services/resource_coordinator/coordination_unit/metrics_collector_unittest.cc b/services/resource_coordinator/coordination_unit/metrics_collector_unittest.cc index a9a645d..f79918d 100644 --- a/services/resource_coordinator/coordination_unit/metrics_collector_unittest.cc +++ b/services/resource_coordinator/coordination_unit/metrics_collector_unittest.cc
@@ -33,41 +33,39 @@ std::string()); CoordinationUnitID frame_cu_id(CoordinationUnitType::kFrame, std::string()); - auto tab_coordination_unit = CreateCoordinationUnit(tab_cu_id); - auto frame_coordination_unit = CreateCoordinationUnit(frame_cu_id); - coordination_unit_manager().OnCoordinationUnitCreated( - tab_coordination_unit.get()); - coordination_unit_manager().OnCoordinationUnitCreated( - frame_coordination_unit.get()); + auto web_contents_cu = CreateCoordinationUnit(tab_cu_id); + auto frame_cu = CreateCoordinationUnit(frame_cu_id); + coordination_unit_manager().OnCoordinationUnitCreated(web_contents_cu.get()); + coordination_unit_manager().OnCoordinationUnitCreated(frame_cu.get()); - tab_coordination_unit->AddChild(frame_coordination_unit->id()); + web_contents_cu->AddChild(frame_cu->id()); - tab_coordination_unit->SetProperty(mojom::PropertyType::kVisible, true); - frame_coordination_unit->SetProperty(mojom::PropertyType::kAudible, true); + web_contents_cu->SetProperty(mojom::PropertyType::kVisible, true); + frame_cu->SetProperty(mojom::PropertyType::kAudible, true); // The tab is not backgrounded, thus no metrics recorded. histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAudioStartsUMA, 0); - frame_coordination_unit->SetProperty(mojom::PropertyType::kAudible, false); + frame_cu->SetProperty(mojom::PropertyType::kAudible, false); - tab_coordination_unit->SetProperty(mojom::PropertyType::kVisible, false); - frame_coordination_unit->SetProperty(mojom::PropertyType::kAudible, true); + web_contents_cu->SetProperty(mojom::PropertyType::kVisible, false); + frame_cu->SetProperty(mojom::PropertyType::kAudible, true); // The tab was recently audible, thus no metrics recorded. histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAudioStartsUMA, 0); - frame_coordination_unit->SetProperty(mojom::PropertyType::kAudible, false); + frame_cu->SetProperty(mojom::PropertyType::kAudible, false); AdvanceClock(base::TimeDelta::FromMinutes(1)); - tab_coordination_unit->SetProperty(mojom::PropertyType::kVisible, true); - frame_coordination_unit->SetProperty(mojom::PropertyType::kAudible, true); + web_contents_cu->SetProperty(mojom::PropertyType::kVisible, true); + frame_cu->SetProperty(mojom::PropertyType::kAudible, true); // The tab was not recently audible but it is not backgrounded, thus no // metrics recorded. histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAudioStartsUMA, 0); - frame_coordination_unit->SetProperty(mojom::PropertyType::kAudible, false); + frame_cu->SetProperty(mojom::PropertyType::kAudible, false); - tab_coordination_unit->SetProperty(mojom::PropertyType::kVisible, false); + web_contents_cu->SetProperty(mojom::PropertyType::kVisible, false); AdvanceClock(base::TimeDelta::FromSeconds(61)); - frame_coordination_unit->SetProperty(mojom::PropertyType::kAudible, true); + frame_cu->SetProperty(mojom::PropertyType::kAudible, true); // The tab was not recently audible and it is backgrounded, thus metrics // recorded. histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAudioStartsUMA, @@ -79,40 +77,71 @@ std::string()); CoordinationUnitID frame_cu_id(CoordinationUnitType::kFrame, std::string()); - auto tab_coordination_unit = CreateCoordinationUnit(tab_cu_id); - auto frame_coordination_unit = CreateCoordinationUnit(frame_cu_id); - coordination_unit_manager().OnCoordinationUnitCreated( - tab_coordination_unit.get()); - coordination_unit_manager().OnCoordinationUnitCreated( - frame_coordination_unit.get()); + auto web_contents_cu = CreateCoordinationUnit(tab_cu_id); + auto frame_cu = CreateCoordinationUnit(frame_cu_id); + coordination_unit_manager().OnCoordinationUnitCreated(web_contents_cu.get()); + coordination_unit_manager().OnCoordinationUnitCreated(frame_cu.get()); - tab_coordination_unit->AddChild(frame_coordination_unit->id()); + web_contents_cu->AddChild(frame_cu->id()); - tab_coordination_unit->SetProperty(mojom::PropertyType::kVisible, false); + web_contents_cu->SetProperty(mojom::PropertyType::kVisible, false); - frame_coordination_unit->SetProperty(mojom::PropertyType::kAudible, false); + frame_cu->SetProperty(mojom::PropertyType::kAudible, false); AdvanceClock(base::TimeDelta::FromSeconds(61)); - frame_coordination_unit->SetProperty(mojom::PropertyType::kAudible, true); + frame_cu->SetProperty(mojom::PropertyType::kAudible, true); // The tab was not recently audible and it is backgrounded, thus metrics // recorded. histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAudioStartsUMA, 1); - frame_coordination_unit->SetProperty(mojom::PropertyType::kAudible, false); + frame_cu->SetProperty(mojom::PropertyType::kAudible, false); AdvanceClock(base::TimeDelta::FromSeconds(61)); - frame_coordination_unit->SetProperty(mojom::PropertyType::kAudible, true); + frame_cu->SetProperty(mojom::PropertyType::kAudible, true); // Only record the metrics once. histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAudioStartsUMA, 1); - tab_coordination_unit->SetProperty(mojom::PropertyType::kVisible, true); - tab_coordination_unit->SetProperty(mojom::PropertyType::kVisible, false); - frame_coordination_unit->SetProperty(mojom::PropertyType::kAudible, false); + web_contents_cu->SetProperty(mojom::PropertyType::kVisible, true); + web_contents_cu->SetProperty(mojom::PropertyType::kVisible, false); + frame_cu->SetProperty(mojom::PropertyType::kAudible, false); AdvanceClock(base::TimeDelta::FromSeconds(61)); - frame_coordination_unit->SetProperty(mojom::PropertyType::kAudible, true); + frame_cu->SetProperty(mojom::PropertyType::kAudible, true); // The tab becomes visible and then invisible again, thus metrics recorded. histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAudioStartsUMA, 2); } +TEST_F(MetricsCollectorTest, FromBackgroundedToFirstTitleUpdatedUMA) { + CoordinationUnitID tab_cu_id(CoordinationUnitType::kWebContents, + std::string()); + CoordinationUnitID frame_cu_id(CoordinationUnitType::kFrame, std::string()); + + auto web_contents_cu = CreateCoordinationUnit(tab_cu_id); + coordination_unit_manager().OnCoordinationUnitCreated(web_contents_cu.get()); + + web_contents_cu->SetProperty(mojom::PropertyType::kVisible, true); + web_contents_cu->SendEvent(mojom::Event::kTitleUpdated); + // The tab is not backgrounded, thus no metrics recorded. + histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstTitleUpdatedUMA, + 0); + + web_contents_cu->SetProperty(mojom::PropertyType::kVisible, false); + web_contents_cu->SendEvent(mojom::Event::kTitleUpdated); + // The tab is backgrounded, thus metrics recorded. + histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstTitleUpdatedUMA, + 1); + web_contents_cu->SendEvent(mojom::Event::kTitleUpdated); + // Metrics should only be recorded once per background period, thus metrics + // not recorded. + histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstTitleUpdatedUMA, + 1); + + web_contents_cu->SetProperty(mojom::PropertyType::kVisible, true); + web_contents_cu->SetProperty(mojom::PropertyType::kVisible, false); + web_contents_cu->SendEvent(mojom::Event::kTitleUpdated); + // The tab is backgrounded from foregrounded, thus metrics recorded. + histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstTitleUpdatedUMA, + 2); +} + } // namespace resource_coordinator
diff --git a/services/resource_coordinator/coordination_unit/web_contents_coordination_unit_impl.cc b/services/resource_coordinator/coordination_unit/web_contents_coordination_unit_impl.cc index a5581099e..44f18317 100644 --- a/services/resource_coordinator/coordination_unit/web_contents_coordination_unit_impl.cc +++ b/services/resource_coordinator/coordination_unit/web_contents_coordination_unit_impl.cc
@@ -60,6 +60,12 @@ return is_visible; } +void WebContentsCoordinationUnitImpl::OnEventReceived( + const mojom::Event event) { + for (auto& observer : observers()) + observer.OnWebContentsEventReceived(this, event); +} + void WebContentsCoordinationUnitImpl::OnPropertyChanged( const mojom::PropertyType property_type, int64_t value) {
diff --git a/services/resource_coordinator/coordination_unit/web_contents_coordination_unit_impl.h b/services/resource_coordinator/coordination_unit/web_contents_coordination_unit_impl.h index 4bc0e8d..dc371c9 100644 --- a/services/resource_coordinator/coordination_unit/web_contents_coordination_unit_impl.h +++ b/services/resource_coordinator/coordination_unit/web_contents_coordination_unit_impl.h
@@ -28,6 +28,7 @@ private: // CoordinationUnitImpl implementation. + void OnEventReceived(const mojom::Event event) override; void OnPropertyChanged(const mojom::PropertyType property_type, int64_t value) override; double CalculateCPUUsage();
diff --git a/services/resource_coordinator/public/cpp/resource_coordinator_interface.cc b/services/resource_coordinator/public/cpp/resource_coordinator_interface.cc index 7d749229..65c7104 100644 --- a/services/resource_coordinator/public/cpp/resource_coordinator_interface.cc +++ b/services/resource_coordinator/public/cpp/resource_coordinator_interface.cc
@@ -61,15 +61,12 @@ service_.set_connection_error_handler(base::Bind(&OnConnectionError)); } -void ResourceCoordinatorInterface::SendEvent( - const mojom::EventType& event_type) { +void ResourceCoordinatorInterface::SendEvent(const mojom::Event event) { DCHECK(thread_checker_.CalledOnValidThread()); if (!service_) return; - mojom::EventPtr event = mojom::Event::New(); - event->type = event_type; - service_->SendEvent(std::move(event)); + service_->SendEvent(event); } void ResourceCoordinatorInterface::SetProperty(
diff --git a/services/resource_coordinator/public/cpp/resource_coordinator_interface.h b/services/resource_coordinator/public/cpp/resource_coordinator_interface.h index 8d6a0ebe..c9d55ee9 100644 --- a/services/resource_coordinator/public/cpp/resource_coordinator_interface.h +++ b/services/resource_coordinator/public/cpp/resource_coordinator_interface.h
@@ -20,8 +20,6 @@ namespace resource_coordinator { -using EventType = mojom::EventType; - class SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_EXPORT ResourceCoordinatorInterface { public: @@ -36,7 +34,7 @@ ~ResourceCoordinatorInterface(); - void SendEvent(const mojom::EventType& event_type); + void SendEvent(const mojom::Event event); void SetProperty(mojom::PropertyType property_type, int64_t value); void AddBinding(mojom::CoordinationUnitRequest request); void AddChild(const ResourceCoordinatorInterface& child);
diff --git a/services/resource_coordinator/public/interfaces/BUILD.gn b/services/resource_coordinator/public/interfaces/BUILD.gn index 77f4fded..825aa16 100644 --- a/services/resource_coordinator/public/interfaces/BUILD.gn +++ b/services/resource_coordinator/public/interfaces/BUILD.gn
@@ -11,11 +11,11 @@ "coordination_unit.mojom", "coordination_unit_introspector.mojom", "coordination_unit_provider.mojom", - "events.mojom", "memory_instrumentation/constants.mojom", "memory_instrumentation/memory_instrumentation.mojom", "service_callbacks.mojom", "service_constants.mojom", + "signals.mojom", "tab_signal.mojom", "tracing/tracing.mojom", "tracing/tracing_constants.mojom",
diff --git a/services/resource_coordinator/public/interfaces/coordination_unit.mojom b/services/resource_coordinator/public/interfaces/coordination_unit.mojom index dbe7b8d..36ebf7a 100644 --- a/services/resource_coordinator/public/interfaces/coordination_unit.mojom +++ b/services/resource_coordinator/public/interfaces/coordination_unit.mojom
@@ -4,7 +4,7 @@ module resource_coordinator.mojom; -import "events.mojom"; +import "signals.mojom"; import "mojo/common/values.mojom"; // Any new type here needs to be mirrored between coordination_unit_types.h and @@ -30,20 +30,7 @@ SetCoordinationPolicy(CoordinationPolicy policy); }; -// Defines the Storage property keys that can be get/set on the -// CoordinationUnitImpl internal key-value store. -enum PropertyType { - kTest, - kAudible, - kCPUUsage, - kNetworkIdle, - kVisible, - kUKMSourceId, -}; - interface CoordinationUnit { - SendEvent(Event event); - // Mainly used to force a round-trip to the service over the pipe for // a specific unit, so we don't have to deal with possibly-not-yet-created // children in AddChild() @@ -61,6 +48,9 @@ RemoveChild(CoordinationUnitID child_id); SetCoordinationPolicyCallback(CoordinationPolicyCallback callback); - // Sets a property on the CoordinationUnitImpl's internal key-value store. + // Sends event signal to CoordinationUnit, an event signal are non-persistent. + SendEvent(Event event); + + // Sets a property on the CoordinationUnit's internal key-value store. SetProperty(PropertyType property_type, int64 value); };
diff --git a/services/resource_coordinator/public/interfaces/events.mojom b/services/resource_coordinator/public/interfaces/events.mojom deleted file mode 100644 index 57c942e3..0000000 --- a/services/resource_coordinator/public/interfaces/events.mojom +++ /dev/null
@@ -1,22 +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. - -module resource_coordinator.mojom; - -enum EventType { - kTestEvent, - kOnNavigationCommit, - - // WebContents event types. - kOnWebContentsShown, - kOnWebContentsHidden, - - // Process event types. - kOnProcessAudioStarted, - kOnProcessAudioStopped, -}; - -struct Event { - EventType type; -};
diff --git a/services/resource_coordinator/public/interfaces/signals.mojom b/services/resource_coordinator/public/interfaces/signals.mojom new file mode 100644 index 0000000..e8b6231a --- /dev/null +++ b/services/resource_coordinator/public/interfaces/signals.mojom
@@ -0,0 +1,29 @@ +// 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. + +module resource_coordinator.mojom; + +enum Event { + kTestEvent, + kTitleUpdated, + + // TODO(crbug.com/691886) Clean up the below events. + kOnNavigationCommit, + kOnWebContentsShown, + kOnWebContentsHidden, + kOnProcessAudioStarted, + kOnProcessAudioStopped, +}; + +// Defines the Storage property keys that can be get/set on the +// CoordinationUnitImpl internal key-value store. +enum PropertyType { + kTest, + kAudible, + kCPUUsage, + kNetworkIdle, + kVisible, + kURL, + kUKMSourceId, +};
diff --git a/services/ui/demo/window_tree_data.cc b/services/ui/demo/window_tree_data.cc index 3d78c94..e298166 100644 --- a/services/ui/demo/window_tree_data.cc +++ b/services/ui/demo/window_tree_data.cc
@@ -68,7 +68,6 @@ void WindowTreeData::Init( std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) { - window_tree_host->InitHost(); window_tree_host->Show(); // Take ownership of the WTH. window_tree_host_ = std::move(window_tree_host);
diff --git a/services/viz/public/cpp/compositing/DEPS b/services/viz/public/cpp/compositing/DEPS index d1586ba..5274d06c4 100644 --- a/services/viz/public/cpp/compositing/DEPS +++ b/services/viz/public/cpp/compositing/DEPS
@@ -1,9 +1,10 @@ include_rules = [ + "+cc", + "+gpu/ipc", + "+gpu/ipc/common", + "+skia/public/interfaces", "+ui/gfx/ipc", "+ui/gfx/mojo", "+ui/gfx/geometry/mojo", - "+cc", - "+gpu/ipc", - "+skia/public/interfaces", "+ui/latency/mojo", ]
diff --git a/services/viz/public/cpp/compositing/returned_resource.typemap b/services/viz/public/cpp/compositing/returned_resource.typemap new file mode 100644 index 0000000..ec2faf2 --- /dev/null +++ b/services/viz/public/cpp/compositing/returned_resource.typemap
@@ -0,0 +1,15 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +mojom = "//services/viz/public/interfaces/compositing/returned_resource.mojom" +public_headers = [ "//components/viz/common/resources/returned_resource.h" ] +traits_headers = [ "//services/viz/public/cpp/compositing/returned_resource_struct_traits.h" ] +deps = [ + "//components/viz/common", + "//gpu/command_buffer/common", +] +type_mappings = [ + "viz.mojom.ReturnedResource=viz::ReturnedResource", + "viz.mojom.ReturnedResourceArray=viz::ReturnedResourceArray", +]
diff --git a/cc/ipc/returned_resource_struct_traits.h b/services/viz/public/cpp/compositing/returned_resource_struct_traits.h similarity index 65% rename from cc/ipc/returned_resource_struct_traits.h rename to services/viz/public/cpp/compositing/returned_resource_struct_traits.h index 12f92a0c..7f217fa 100644 --- a/cc/ipc/returned_resource_struct_traits.h +++ b/services/viz/public/cpp/compositing/returned_resource_struct_traits.h
@@ -2,16 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_IPC_RETURNED_RESOURCE_STRUCT_TRAITS_H_ -#define CC_IPC_RETURNED_RESOURCE_STRUCT_TRAITS_H_ +#ifndef SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_RETURNED_RESOURCE_STRUCT_TRAITS_H_ +#define SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_RETURNED_RESOURCE_STRUCT_TRAITS_H_ -#include "cc/ipc/returned_resource.mojom-shared.h" #include "components/viz/common/resources/returned_resource.h" +#include "gpu/ipc/common/sync_token_struct_traits.h" +#include "services/viz/public/interfaces/compositing/returned_resource.mojom-shared.h" namespace mojo { template <> -struct StructTraits<cc::mojom::ReturnedResourceDataView, +struct StructTraits<viz::mojom::ReturnedResourceDataView, viz::ReturnedResource> { static uint32_t id(const viz::ReturnedResource& resource) { return resource.id; @@ -30,7 +31,7 @@ return resource.lost; } - static bool Read(cc::mojom::ReturnedResourceDataView data, + static bool Read(viz::mojom::ReturnedResourceDataView data, viz::ReturnedResource* out) { if (!data.ReadSyncToken(&out->sync_token)) return false; @@ -43,4 +44,4 @@ } // namespace mojo -#endif // CC_IPC_RETURNED_RESOURCE_STRUCT_TRAITS_H_ +#endif // SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_RETURNED_RESOURCE_STRUCT_TRAITS_H_
diff --git a/services/viz/public/cpp/compositing/struct_traits_unittest.cc b/services/viz/public/cpp/compositing/struct_traits_unittest.cc index a989f48..9fc1046 100644 --- a/services/viz/public/cpp/compositing/struct_traits_unittest.cc +++ b/services/viz/public/cpp/compositing/struct_traits_unittest.cc
@@ -15,7 +15,6 @@ #include "cc/ipc/local_surface_id_struct_traits.h" #include "cc/ipc/quads_struct_traits.h" #include "cc/ipc/render_pass_struct_traits.h" -#include "cc/ipc/returned_resource_struct_traits.h" #include "cc/ipc/selection_struct_traits.h" #include "cc/ipc/shared_quad_state_struct_traits.h" #include "cc/ipc/surface_id_struct_traits.h" @@ -29,6 +28,7 @@ #include "components/viz/common/frame_sinks/begin_frame_args.h" #include "components/viz/common/quads/resource_format.h" #include "components/viz/common/resources/resource_settings.h" +#include "components/viz/common/resources/returned_resource.h" #include "components/viz/common/resources/transferable_resource.h" #include "components/viz/test/begin_frame_args_test.h" #include "gpu/ipc/common/mailbox_holder_struct_traits.h" @@ -39,7 +39,9 @@ #include "mojo/public/cpp/bindings/binding_set.h" #include "services/viz/public/cpp/compositing/compositor_frame_struct_traits.h" #include "services/viz/public/cpp/compositing/resource_settings_struct_traits.h" +#include "services/viz/public/cpp/compositing/returned_resource_struct_traits.h" #include "services/viz/public/interfaces/compositing/compositor_frame.mojom.h" +#include "services/viz/public/interfaces/compositing/returned_resource.mojom.h" #include "skia/public/interfaces/bitmap_skbitmap_struct_traits.h" #include "skia/public/interfaces/blur_image_filter_tile_mode_struct_traits.h" #include "skia/public/interfaces/image_filter_struct_traits.h" @@ -57,6 +59,22 @@ using StructTraitsTest = testing::Test; +// Test StructTrait serialization and deserialization for copyable type. |input| +// will be serialized and then deserialized into |output|. +template <class MojomType, class Type> +void SerializeAndDeserialize(const Type& input, Type* output) { + MojomType::Deserialize(MojomType::Serialize(&input), output); +} + +// Test StructTrait serialization and deserialization for move only type. +// |input| will be serialized and then deserialized into |output|. +template <class MojomType, class Type> +void SerializeAndDeserialize(Type&& input, Type* output) { + MojomType::Deserialize(MojomType::Serialize(&input), output); +} + +} // namespace + TEST_F(StructTraitsTest, ResourceSettings) { constexpr size_t kArbitrarySize = 32; constexpr bool kArbitraryBool = true; @@ -67,8 +85,8 @@ DefaultBufferToTextureTargetMapForTesting(); ResourceSettings output; - mojom::ResourceSettings::Deserialize( - mojom::ResourceSettings::Serialize(&input), &output); + SerializeAndDeserialize<mojom::ResourceSettings>(input, &output); + EXPECT_EQ(input.texture_id_allocation_chunk_size, output.texture_id_allocation_chunk_size); EXPECT_EQ(input.use_gpu_memory_buffer_resources, @@ -148,8 +166,7 @@ input.metadata.begin_frame_ack = begin_frame_ack; cc::CompositorFrame output; - mojom::CompositorFrame::Deserialize(mojom::CompositorFrame::Serialize(&input), - &output); + SerializeAndDeserialize<mojom::CompositorFrame>(input, &output); EXPECT_EQ(device_scale_factor, output.metadata.device_scale_factor); EXPECT_EQ(root_scroll_offset, output.metadata.root_scroll_offset); @@ -200,6 +217,31 @@ out_solid_color_draw_quad->force_anti_aliasing_off); } -} // namespace +TEST_F(StructTraitsTest, ReturnedResource) { + const cc::RenderPassId id = 1337u; + const gpu::CommandBufferNamespace command_buffer_namespace = gpu::IN_PROCESS; + const int32_t extra_data_field = 0xbeefbeef; + const gpu::CommandBufferId command_buffer_id( + gpu::CommandBufferId::FromUnsafeValue(0xdeadbeef)); + const uint64_t release_count = 0xdeadbeefdead; + const gpu::SyncToken sync_token(command_buffer_namespace, extra_data_field, + command_buffer_id, release_count); + const int count = 1234; + const bool lost = true; + + ReturnedResource input; + input.id = id; + input.sync_token = sync_token; + input.count = count; + input.lost = lost; + + ReturnedResource output; + SerializeAndDeserialize<mojom::ReturnedResource>(input, &output); + + EXPECT_EQ(id, output.id); + EXPECT_EQ(sync_token, output.sync_token); + EXPECT_EQ(count, output.count); + EXPECT_EQ(lost, output.lost); +} } // namespace viz
diff --git a/services/viz/public/cpp/compositing/typemaps.gni b/services/viz/public/cpp/compositing/typemaps.gni index 7af5e5c..c0974d95 100644 --- a/services/viz/public/cpp/compositing/typemaps.gni +++ b/services/viz/public/cpp/compositing/typemaps.gni
@@ -5,4 +5,5 @@ typemaps = [ "//services/viz/public/cpp/compositing/compositor_frame.typemap", "//services/viz/public/cpp/compositing/resource_settings.typemap", + "//services/viz/public/cpp/compositing/returned_resource.typemap", ]
diff --git a/services/viz/public/interfaces/compositing/BUILD.gn b/services/viz/public/interfaces/compositing/BUILD.gn index c0bc16cb..22d92f8c 100644 --- a/services/viz/public/interfaces/compositing/BUILD.gn +++ b/services/viz/public/interfaces/compositing/BUILD.gn
@@ -9,10 +9,12 @@ "compositor_frame.mojom", "compositor_frame_sink.mojom", "resource_settings.mojom", + "returned_resource.mojom", ] public_deps = [ "//cc/ipc:interfaces", + "//gpu/ipc/common:interfaces", "//services/viz/public/interfaces/hit_test", "//ui/gfx/geometry/mojo", "//ui/gfx/mojo",
diff --git a/services/viz/public/interfaces/compositing/compositor_frame_sink.mojom b/services/viz/public/interfaces/compositing/compositor_frame_sink.mojom index 3f93e56..22973aa 100644 --- a/services/viz/public/interfaces/compositing/compositor_frame_sink.mojom +++ b/services/viz/public/interfaces/compositing/compositor_frame_sink.mojom
@@ -9,10 +9,10 @@ import "cc/ipc/frame_sink_id.mojom"; import "cc/ipc/local_surface_id.mojom"; import "cc/ipc/surface_id.mojom"; -import "cc/ipc/returned_resource.mojom"; import "cc/ipc/surface_sequence.mojom"; import "services/viz/public/interfaces/hit_test/hit_test_region_list.mojom"; import "services/viz/public/interfaces/compositing/compositor_frame.mojom"; +import "services/viz/public/interfaces/compositing/returned_resource.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; // A CompositorFrameSink is an interface for receiving CompositorFrame @@ -50,7 +50,7 @@ // TODO(fsamuel): This method ought not be necessary with unified BeginFrame. // However, there's a fair amount of cleanup and refactoring necessary to get // rid of it. - DidReceiveCompositorFrameAck(array<cc.mojom.ReturnedResource> resources); + DidReceiveCompositorFrameAck(array<ReturnedResource> resources); // Notification for the client to generate a CompositorFrame. OnBeginFrame(cc.mojom.BeginFrameArgs args); @@ -59,5 +59,5 @@ OnBeginFramePausedChanged(bool paused); // Returns resources sent to SubmitCompositorFrame to be reused or freed. - ReclaimResources(array<cc.mojom.ReturnedResource> resources); + ReclaimResources(array<ReturnedResource> resources); };
diff --git a/cc/ipc/returned_resource.mojom b/services/viz/public/interfaces/compositing/returned_resource.mojom similarity index 79% rename from cc/ipc/returned_resource.mojom rename to services/viz/public/interfaces/compositing/returned_resource.mojom index 396d2e6f..9a5ffb6 100644 --- a/cc/ipc/returned_resource.mojom +++ b/services/viz/public/interfaces/compositing/returned_resource.mojom
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module cc.mojom; +module viz.mojom; import "gpu/ipc/common/sync_token.mojom"; -// See src/cc/resources/returned_resource.h. +// See components/viz/common/resources/returned_resource.h. struct ReturnedResource { uint32 id; gpu.mojom.SyncToken sync_token;
diff --git a/storage/browser/fileapi/file_system_context.cc b/storage/browser/fileapi/file_system_context.cc index f8cce89e..f0377b9 100644 --- a/storage/browser/fileapi/file_system_context.cc +++ b/storage/browser/fileapi/file_system_context.cc
@@ -105,7 +105,6 @@ case kFileSystemTypeRestrictedNativeLocal: case kFileSystemTypeArcContent: case kFileSystemTypeArcDocumentsProvider: - case kFileSystemTypeRecent: return FILE_PERMISSION_READ_ONLY | FILE_PERMISSION_USE_FILE_PERMISSION;
diff --git a/storage/common/fileapi/file_system_types.h b/storage/common/fileapi/file_system_types.h index b93ea11..6ea0721 100644 --- a/storage/common/fileapi/file_system_types.h +++ b/storage/common/fileapi/file_system_types.h
@@ -129,9 +129,6 @@ // A filesystem to provide access to documents providers in ARC. kFileSystemTypeArcDocumentsProvider, - // A filesystem showing recently modified files across multiple sources. - kFileSystemTypeRecent, - // -------------------------------------------------------------------- // Marks the end of internal type enum. (This is not the actual fs type) // New internal filesystem types must be added above this line.
diff --git a/storage/common/fileapi/file_system_util.cc b/storage/common/fileapi/file_system_util.cc index f399768b..4156e5a 100644 --- a/storage/common/fileapi/file_system_util.cc +++ b/storage/common/fileapi/file_system_util.cc
@@ -325,8 +325,6 @@ return "ArcContent"; case kFileSystemTypeArcDocumentsProvider: return "ArcDocumentsProvider"; - case kFileSystemTypeRecent: - return "Recent"; case kFileSystemInternalTypeEnumStart: case kFileSystemInternalTypeEnumEnd: NOTREACHED();
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index ca68c80..061482d 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -10772,7 +10772,8 @@ ], "swarming": { "can_use_on_swarming_builders": true, - "hard_timeout": 1800 + "hard_timeout": 1800, + "shards": 5 }, "test": "mash_browser_tests" },
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json index ba5a6346..405aa79 100644 --- a/testing/buildbot/chromium.perf.fyi.json +++ b/testing/buildbot/chromium.perf.fyi.json
@@ -43,7 +43,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -73,7 +73,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -104,7 +104,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -134,7 +134,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -165,7 +165,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -195,7 +195,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -226,7 +226,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -256,7 +256,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -287,7 +287,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -317,7 +317,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -348,7 +348,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -378,7 +378,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -409,7 +409,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -439,7 +439,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -470,7 +470,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -500,7 +500,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -531,7 +531,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -561,7 +561,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -592,7 +592,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -622,7 +622,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -653,7 +653,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -683,7 +683,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -714,7 +714,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -744,7 +744,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -775,7 +775,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -805,7 +805,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -836,7 +836,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -857,7 +857,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -887,7 +887,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -918,7 +918,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -948,7 +948,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -979,7 +979,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1009,7 +1009,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1040,7 +1040,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1070,7 +1070,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1101,7 +1101,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1131,7 +1131,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1162,7 +1162,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1192,7 +1192,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1223,7 +1223,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1244,7 +1244,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1274,7 +1274,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1305,7 +1305,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1335,7 +1335,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1366,7 +1366,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1396,7 +1396,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1427,7 +1427,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1448,7 +1448,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1478,7 +1478,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1509,7 +1509,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1539,7 +1539,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1570,7 +1570,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1600,7 +1600,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1631,7 +1631,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1661,7 +1661,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1692,7 +1692,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1722,7 +1722,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1753,7 +1753,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1783,7 +1783,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1814,7 +1814,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1844,7 +1844,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1875,7 +1875,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1905,7 +1905,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1936,7 +1936,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1966,7 +1966,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1997,7 +1997,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2027,7 +2027,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2058,7 +2058,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2088,7 +2088,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2119,7 +2119,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2149,7 +2149,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2180,7 +2180,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2201,7 +2201,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2231,7 +2231,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2261,7 +2261,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2292,7 +2292,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2322,7 +2322,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2353,7 +2353,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2383,7 +2383,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2414,7 +2414,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2444,7 +2444,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2475,7 +2475,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2505,7 +2505,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2536,7 +2536,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2566,7 +2566,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2597,7 +2597,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2627,7 +2627,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2658,7 +2658,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2688,7 +2688,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2719,7 +2719,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2749,7 +2749,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2780,7 +2780,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2810,7 +2810,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2841,7 +2841,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2871,7 +2871,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2902,7 +2902,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2932,7 +2932,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2963,7 +2963,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2993,7 +2993,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3024,7 +3024,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3054,7 +3054,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3085,7 +3085,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3115,7 +3115,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3146,7 +3146,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3176,7 +3176,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3207,7 +3207,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3237,7 +3237,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3268,7 +3268,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3298,7 +3298,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3329,7 +3329,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3359,7 +3359,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3390,7 +3390,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3420,7 +3420,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3451,7 +3451,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3481,7 +3481,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3512,7 +3512,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3542,7 +3542,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3573,7 +3573,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3603,7 +3603,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3634,7 +3634,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3664,7 +3664,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3695,7 +3695,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3725,7 +3725,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3756,7 +3756,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3786,7 +3786,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3817,7 +3817,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3847,7 +3847,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3878,7 +3878,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3908,7 +3908,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3939,7 +3939,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3969,7 +3969,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4000,7 +4000,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4030,7 +4030,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4061,7 +4061,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4091,7 +4091,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4122,7 +4122,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4152,7 +4152,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4183,7 +4183,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4213,7 +4213,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4244,7 +4244,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4274,7 +4274,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4305,7 +4305,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4335,7 +4335,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4366,7 +4366,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4396,7 +4396,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4427,7 +4427,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4457,7 +4457,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4488,7 +4488,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4518,7 +4518,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4549,7 +4549,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4579,7 +4579,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4610,7 +4610,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4640,7 +4640,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4671,7 +4671,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4701,7 +4701,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4732,7 +4732,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4762,7 +4762,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4793,7 +4793,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4823,7 +4823,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4854,7 +4854,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4875,7 +4875,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4905,7 +4905,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4936,7 +4936,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4966,7 +4966,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4997,7 +4997,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5027,7 +5027,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5058,7 +5058,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5088,7 +5088,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5119,7 +5119,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5149,7 +5149,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5180,7 +5180,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5214,7 +5214,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5245,7 +5245,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5275,7 +5275,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5306,7 +5306,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5336,7 +5336,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5367,7 +5367,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5397,7 +5397,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5428,7 +5428,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5458,7 +5458,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5489,7 +5489,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5519,7 +5519,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5550,7 +5550,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5580,7 +5580,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5611,7 +5611,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5641,7 +5641,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5672,7 +5672,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5702,7 +5702,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5733,7 +5733,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5763,7 +5763,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5794,7 +5794,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5824,7 +5824,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5855,7 +5855,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5885,7 +5885,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5916,7 +5916,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5946,7 +5946,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5977,7 +5977,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6007,7 +6007,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6038,7 +6038,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6068,7 +6068,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6099,7 +6099,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6129,7 +6129,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6160,7 +6160,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6190,7 +6190,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6221,7 +6221,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6251,7 +6251,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6282,7 +6282,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6312,7 +6312,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6343,7 +6343,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6373,7 +6373,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6404,7 +6404,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6434,7 +6434,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6465,7 +6465,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6495,7 +6495,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6526,7 +6526,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6556,7 +6556,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6587,7 +6587,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6617,7 +6617,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6648,7 +6648,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6678,7 +6678,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6709,7 +6709,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6739,7 +6739,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6770,7 +6770,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6800,7 +6800,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6831,7 +6831,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6861,7 +6861,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6892,7 +6892,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6922,7 +6922,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6953,7 +6953,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6983,7 +6983,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7014,7 +7014,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7044,7 +7044,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7075,7 +7075,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7105,7 +7105,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7136,7 +7136,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7166,7 +7166,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7197,7 +7197,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7227,7 +7227,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7258,7 +7258,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7288,7 +7288,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7318,7 +7318,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7349,7 +7349,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7379,7 +7379,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7410,7 +7410,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7440,7 +7440,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7471,7 +7471,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7501,7 +7501,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7532,7 +7532,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7562,7 +7562,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7593,7 +7593,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7623,7 +7623,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7654,7 +7654,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7684,7 +7684,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7715,7 +7715,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7745,7 +7745,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7776,7 +7776,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7806,7 +7806,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7837,7 +7837,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7867,7 +7867,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7898,7 +7898,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7928,7 +7928,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7959,7 +7959,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7989,7 +7989,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8020,7 +8020,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8050,7 +8050,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8081,7 +8081,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8111,7 +8111,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8142,7 +8142,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8172,7 +8172,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8203,7 +8203,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8233,7 +8233,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8264,7 +8264,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8294,7 +8294,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8325,7 +8325,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8355,7 +8355,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8386,7 +8386,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8416,7 +8416,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8447,7 +8447,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8477,7 +8477,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8508,7 +8508,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8538,7 +8538,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8569,7 +8569,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8599,7 +8599,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8630,7 +8630,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8660,7 +8660,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8691,7 +8691,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8721,7 +8721,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8752,7 +8752,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8782,7 +8782,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8813,7 +8813,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8843,7 +8843,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8874,7 +8874,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8904,7 +8904,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8935,7 +8935,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8965,7 +8965,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8996,7 +8996,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9026,7 +9026,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9057,7 +9057,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9087,7 +9087,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9118,7 +9118,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9148,7 +9148,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9179,7 +9179,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9209,7 +9209,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9240,7 +9240,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9270,7 +9270,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9301,7 +9301,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9331,7 +9331,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9362,7 +9362,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9392,7 +9392,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9423,7 +9423,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9453,7 +9453,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9484,7 +9484,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9514,7 +9514,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9545,7 +9545,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9575,7 +9575,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9606,7 +9606,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9636,7 +9636,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9667,7 +9667,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9697,7 +9697,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9728,7 +9728,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9758,7 +9758,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9789,7 +9789,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9819,7 +9819,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9850,7 +9850,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9880,7 +9880,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9911,7 +9911,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9941,7 +9941,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9972,7 +9972,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -10002,7 +10002,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10033,7 +10033,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -10063,7 +10063,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10094,7 +10094,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -10124,7 +10124,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10155,7 +10155,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -10185,7 +10185,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10216,7 +10216,7 @@ "pool": "Chrome-perf-fyi" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600,
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json index 61020f5..2767fe5 100644 --- a/testing/buildbot/chromium.perf.json +++ b/testing/buildbot/chromium.perf.json
@@ -31,7 +31,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62,7 +62,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -92,7 +92,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -123,7 +123,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -153,7 +153,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -184,7 +184,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -214,7 +214,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -245,7 +245,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -275,7 +275,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -306,7 +306,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -336,7 +336,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -367,7 +367,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -397,7 +397,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -428,7 +428,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -458,7 +458,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -489,7 +489,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -519,7 +519,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -550,7 +550,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -580,7 +580,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -611,7 +611,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -641,7 +641,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -672,7 +672,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -702,7 +702,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -733,7 +733,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -754,7 +754,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -784,7 +784,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -815,7 +815,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -845,7 +845,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -876,7 +876,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -906,7 +906,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -937,7 +937,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -967,7 +967,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -998,7 +998,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1028,7 +1028,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1059,7 +1059,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1089,7 +1089,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1120,7 +1120,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1141,7 +1141,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1171,7 +1171,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1202,7 +1202,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1232,7 +1232,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1263,7 +1263,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1293,7 +1293,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1324,7 +1324,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1354,7 +1354,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 16200, "ignore_task_failure": false, "io_timeout": 3600, @@ -1385,7 +1385,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 16200, "ignore_task_failure": true, "io_timeout": 3600, @@ -1415,7 +1415,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1446,7 +1446,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1476,7 +1476,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1507,7 +1507,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1537,7 +1537,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1568,7 +1568,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1598,7 +1598,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1629,7 +1629,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1659,7 +1659,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1690,7 +1690,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1720,7 +1720,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1751,7 +1751,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1781,7 +1781,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1812,7 +1812,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1842,7 +1842,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1873,7 +1873,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1903,7 +1903,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1933,7 +1933,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -1964,7 +1964,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -1994,7 +1994,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2025,7 +2025,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2055,7 +2055,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2086,7 +2086,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2116,7 +2116,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2147,7 +2147,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2177,7 +2177,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2208,7 +2208,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2238,7 +2238,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2269,7 +2269,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2299,7 +2299,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2330,7 +2330,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2360,7 +2360,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2391,7 +2391,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2421,7 +2421,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2452,7 +2452,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2482,7 +2482,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2513,7 +2513,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2543,7 +2543,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2574,7 +2574,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2604,7 +2604,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2635,7 +2635,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2665,7 +2665,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2696,7 +2696,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2726,7 +2726,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2757,7 +2757,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2787,7 +2787,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2818,7 +2818,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2848,7 +2848,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2879,7 +2879,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2909,7 +2909,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -2940,7 +2940,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -2970,7 +2970,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3001,7 +3001,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3031,7 +3031,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3062,7 +3062,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3092,7 +3092,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3123,7 +3123,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3153,7 +3153,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3184,7 +3184,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3214,7 +3214,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3245,6 +3245,67 @@ "pool": "Chrome-perf" } ], + "expiration": 72000, + "hard_timeout": 10800, + "ignore_task_failure": true, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_canvas_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-chromium" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_canvas_cases", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build48-b1--device4", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_canvas_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=reference", + "--output-trace-tag=_ref" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_canvas_cases.reference", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build48-b1--device4", + "os": "Android", + "pool": "Chrome-perf" + } + ], "expiration": 36000, "hard_timeout": 10800, "ignore_task_failure": true, @@ -3275,7 +3336,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3306,7 +3367,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3336,7 +3397,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3367,7 +3428,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3397,7 +3458,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3428,7 +3489,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3458,7 +3519,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3489,7 +3550,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3519,7 +3580,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3550,7 +3611,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3580,7 +3641,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3611,6 +3672,67 @@ "pool": "Chrome-perf" } ], + "expiration": 72000, + "hard_timeout": 10800, + "ignore_task_failure": true, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_webgl_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-chromium" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_webgl_cases", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build14-b1--device5", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_webgl_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=reference", + "--output-trace-tag=_ref" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_webgl_cases.reference", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build14-b1--device5", + "os": "Android", + "pool": "Chrome-perf" + } + ], "expiration": 36000, "hard_timeout": 10800, "ignore_task_failure": true, @@ -3641,7 +3763,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3672,7 +3794,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3702,7 +3824,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3733,129 +3855,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": true, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.cold.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-chromium" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.cold.blank_page", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build48-b1--device4", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.cold.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=reference", - "--output-trace-tag=_ref" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.cold.blank_page.reference", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build48-b1--device4", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": true, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.warm.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-chromium" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.warm.blank_page", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build13-b1--device7", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.warm.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=reference", - "--output-trace-tag=_ref" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.warm.blank_page.reference", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build13-b1--device7", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3885,7 +3885,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3916,7 +3916,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -3946,7 +3946,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -3977,7 +3977,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4007,7 +4007,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4038,7 +4038,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4068,7 +4068,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4099,7 +4099,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4129,7 +4129,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4160,7 +4160,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4190,7 +4190,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4221,7 +4221,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4251,7 +4251,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4282,7 +4282,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4312,7 +4312,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4343,7 +4343,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4373,7 +4373,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4404,7 +4404,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4434,7 +4434,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4465,7 +4465,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4495,7 +4495,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4526,7 +4526,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4556,7 +4556,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4587,7 +4587,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4617,7 +4617,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4648,7 +4648,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4678,7 +4678,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4709,7 +4709,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4739,7 +4739,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4770,7 +4770,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4800,7 +4800,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4831,7 +4831,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4852,7 +4852,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4882,7 +4882,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4913,7 +4913,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -4943,7 +4943,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -4974,7 +4974,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5004,7 +5004,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5035,7 +5035,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5065,7 +5065,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5096,7 +5096,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5130,7 +5130,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5161,7 +5161,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5191,7 +5191,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5222,7 +5222,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5252,7 +5252,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5283,7 +5283,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5313,7 +5313,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5344,7 +5344,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5374,7 +5374,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5405,7 +5405,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5435,7 +5435,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5466,7 +5466,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5496,7 +5496,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5527,7 +5527,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5557,7 +5557,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5588,7 +5588,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5618,7 +5618,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5649,7 +5649,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5679,7 +5679,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5710,7 +5710,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5740,7 +5740,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5771,7 +5771,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5801,7 +5801,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5832,7 +5832,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5862,7 +5862,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5893,7 +5893,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5923,7 +5923,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -5954,7 +5954,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -5984,7 +5984,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6015,7 +6015,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6045,7 +6045,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6076,7 +6076,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6106,7 +6106,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6137,7 +6137,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6158,7 +6158,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6188,7 +6188,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6219,7 +6219,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6249,7 +6249,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6280,7 +6280,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6310,7 +6310,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6341,7 +6341,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6371,7 +6371,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 16200, "ignore_task_failure": false, "io_timeout": 3600, @@ -6402,7 +6402,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 16200, "ignore_task_failure": true, "io_timeout": 3600, @@ -6432,7 +6432,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6463,7 +6463,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6493,7 +6493,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6524,7 +6524,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6554,7 +6554,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6585,7 +6585,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6615,7 +6615,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6646,7 +6646,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6676,7 +6676,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6707,7 +6707,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6737,7 +6737,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6768,7 +6768,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6798,7 +6798,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6829,7 +6829,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6859,7 +6859,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6890,7 +6890,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -6920,7 +6920,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6950,7 +6950,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -6981,7 +6981,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7011,7 +7011,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7042,7 +7042,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7072,7 +7072,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7103,7 +7103,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7133,7 +7133,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7164,7 +7164,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7194,7 +7194,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7225,7 +7225,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7255,7 +7255,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7286,7 +7286,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7316,7 +7316,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7347,7 +7347,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7377,7 +7377,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7408,7 +7408,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7438,7 +7438,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7469,7 +7469,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7499,7 +7499,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7530,7 +7530,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7560,7 +7560,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7591,7 +7591,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7621,7 +7621,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7652,7 +7652,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7682,7 +7682,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7713,7 +7713,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7743,7 +7743,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7774,7 +7774,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7804,7 +7804,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7835,7 +7835,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7865,7 +7865,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7896,7 +7896,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7926,7 +7926,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -7957,7 +7957,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -7987,7 +7987,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8018,7 +8018,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8048,7 +8048,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8079,7 +8079,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8109,7 +8109,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8140,7 +8140,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8170,7 +8170,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8201,7 +8201,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8231,7 +8231,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8262,6 +8262,67 @@ "pool": "Chrome-perf" } ], + "expiration": 72000, + "hard_timeout": 10800, + "ignore_task_failure": true, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_canvas_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-chromium" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_canvas_cases", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build75-b1--device4", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_canvas_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=reference", + "--output-trace-tag=_ref" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_canvas_cases.reference", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build75-b1--device4", + "os": "Android", + "pool": "Chrome-perf" + } + ], "expiration": 36000, "hard_timeout": 10800, "ignore_task_failure": true, @@ -8292,7 +8353,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8323,7 +8384,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8353,7 +8414,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8384,7 +8445,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8414,7 +8475,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8445,7 +8506,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8475,7 +8536,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8506,7 +8567,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8536,7 +8597,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8567,7 +8628,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8597,7 +8658,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8628,6 +8689,67 @@ "pool": "Chrome-perf" } ], + "expiration": 72000, + "hard_timeout": 10800, + "ignore_task_failure": true, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_webgl_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-chromium" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_webgl_cases", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build74-b1--device5", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_webgl_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=reference", + "--output-trace-tag=_ref" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_webgl_cases.reference", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build74-b1--device5", + "os": "Android", + "pool": "Chrome-perf" + } + ], "expiration": 36000, "hard_timeout": 10800, "ignore_task_failure": true, @@ -8658,7 +8780,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8689,7 +8811,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8719,7 +8841,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8750,129 +8872,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": true, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.cold.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-chromium" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.cold.blank_page", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build75-b1--device4", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.cold.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=reference", - "--output-trace-tag=_ref" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.cold.blank_page.reference", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build75-b1--device4", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": true, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.warm.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-chromium" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.warm.blank_page", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build73-b1--device7", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.warm.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=reference", - "--output-trace-tag=_ref" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.warm.blank_page.reference", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build73-b1--device7", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8902,7 +8902,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8933,7 +8933,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -8963,7 +8963,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -8994,7 +8994,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9024,7 +9024,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9055,7 +9055,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9085,7 +9085,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9116,7 +9116,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9146,7 +9146,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9177,7 +9177,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9207,7 +9207,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9238,7 +9238,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9268,7 +9268,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9299,7 +9299,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9329,7 +9329,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9360,7 +9360,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9390,7 +9390,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9421,7 +9421,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9451,7 +9451,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9482,7 +9482,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9512,7 +9512,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9543,7 +9543,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9573,7 +9573,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9604,7 +9604,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9634,7 +9634,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9665,7 +9665,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9695,7 +9695,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9726,7 +9726,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9756,7 +9756,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9787,7 +9787,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9817,7 +9817,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9848,7 +9848,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9869,7 +9869,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9899,7 +9899,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9930,7 +9930,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -9960,7 +9960,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -9991,7 +9991,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -10021,7 +10021,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10052,7 +10052,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -10082,7 +10082,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10113,7 +10113,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -10148,7 +10148,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10179,7 +10179,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10210,7 +10210,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10241,7 +10241,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10272,7 +10272,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10303,7 +10303,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10334,7 +10334,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10365,7 +10365,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10396,7 +10396,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10427,7 +10427,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10458,7 +10458,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10489,7 +10489,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10520,7 +10520,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10551,7 +10551,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10582,7 +10582,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10613,7 +10613,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10644,7 +10644,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10675,7 +10675,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10706,7 +10706,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10737,7 +10737,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10768,7 +10768,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 16200, "ignore_task_failure": false, "io_timeout": 3600, @@ -10799,7 +10799,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10830,7 +10830,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10861,7 +10861,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10892,7 +10892,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10923,7 +10923,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10954,7 +10954,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -10985,7 +10985,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11016,7 +11016,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11047,7 +11047,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11078,7 +11078,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11109,7 +11109,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11140,7 +11140,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11171,7 +11171,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11202,7 +11202,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11233,7 +11233,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11264,7 +11264,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11295,7 +11295,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11326,7 +11326,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11357,7 +11357,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11388,7 +11388,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11419,7 +11419,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11450,7 +11450,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11481,7 +11481,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11512,7 +11512,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11543,7 +11543,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11574,7 +11574,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11605,7 +11605,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11636,7 +11636,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11667,7 +11667,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11698,7 +11698,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11729,6 +11729,37 @@ "pool": "Chrome-perf" } ], + "expiration": 72000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_canvas_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-webview", + "--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk" + ], + "isolate_name": "telemetry_perf_webview_tests", + "name": "smoothness.tough_canvas_cases", + "override_compile_targets": [ + "telemetry_perf_webview_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build165-b1--device4", + "os": "Android", + "pool": "Chrome-perf" + } + ], "expiration": 36000, "hard_timeout": 10800, "ignore_task_failure": false, @@ -11760,7 +11791,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11791,7 +11822,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11822,7 +11853,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11853,7 +11884,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11884,7 +11915,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11915,6 +11946,37 @@ "pool": "Chrome-perf" } ], + "expiration": 72000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_webgl_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-webview", + "--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk" + ], + "isolate_name": "telemetry_perf_webview_tests", + "name": "smoothness.tough_webgl_cases", + "override_compile_targets": [ + "telemetry_perf_webview_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build165-b1--device7", + "os": "Android", + "pool": "Chrome-perf" + } + ], "expiration": 36000, "hard_timeout": 10800, "ignore_task_failure": false, @@ -11946,7 +12008,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -11977,69 +12039,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.cold.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-webview", - "--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk" - ], - "isolate_name": "telemetry_perf_webview_tests", - "name": "start_with_ext.cold.blank_page", - "override_compile_targets": [ - "telemetry_perf_webview_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build166-b1--device4", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.warm.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-webview", - "--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk" - ], - "isolate_name": "telemetry_perf_webview_tests", - "name": "start_with_ext.warm.blank_page", - "override_compile_targets": [ - "telemetry_perf_webview_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build164-b1--device7", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12070,7 +12070,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12101,7 +12101,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12132,7 +12132,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12163,7 +12163,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12194,7 +12194,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12225,7 +12225,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12256,7 +12256,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12287,7 +12287,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12318,7 +12318,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12349,7 +12349,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12380,7 +12380,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12411,7 +12411,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12442,7 +12442,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12473,7 +12473,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12504,7 +12504,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12535,7 +12535,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12566,7 +12566,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12597,7 +12597,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12628,7 +12628,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12659,7 +12659,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12693,7 +12693,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12724,7 +12724,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -12754,7 +12754,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12785,7 +12785,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -12815,7 +12815,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12846,7 +12846,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -12876,7 +12876,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12907,7 +12907,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -12937,7 +12937,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -12968,7 +12968,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -12998,7 +12998,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -13029,7 +13029,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -13059,7 +13059,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -13090,7 +13090,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -13120,7 +13120,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -13151,7 +13151,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -13181,7 +13181,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -13212,7 +13212,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -13242,7 +13242,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -13273,7 +13273,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -13303,7 +13303,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -13334,7 +13334,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -13364,7 +13364,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -13395,7 +13395,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -13416,7 +13416,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -13446,7 +13446,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -13477,7 +13477,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -13507,7 +13507,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -13538,7 +13538,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -13568,7 +13568,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -13599,7 +13599,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -13629,7 +13629,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -13660,7 +13660,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -13690,7 +13690,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -13721,7 +13721,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -13751,7 +13751,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -13782,7 +13782,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -13803,7 +13803,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -13833,7 +13833,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -13864,7 +13864,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -13894,7 +13894,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -13925,7 +13925,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -13955,7 +13955,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -13986,7 +13986,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -14016,7 +14016,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 16200, "ignore_task_failure": false, "io_timeout": 3600, @@ -14047,7 +14047,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 16200, "ignore_task_failure": true, "io_timeout": 3600, @@ -14077,7 +14077,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -14108,7 +14108,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -14138,7 +14138,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -14169,7 +14169,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -14199,7 +14199,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -14230,7 +14230,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -14260,7 +14260,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -14291,7 +14291,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -14321,7 +14321,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -14352,7 +14352,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -14382,7 +14382,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -14413,7 +14413,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -14443,7 +14443,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -14474,7 +14474,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -14504,7 +14504,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -14535,7 +14535,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -14565,7 +14565,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -14595,7 +14595,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -14626,7 +14626,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -14656,7 +14656,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -14687,7 +14687,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -14717,7 +14717,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -14748,7 +14748,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -14778,7 +14778,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -14809,7 +14809,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -14839,7 +14839,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -14870,7 +14870,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -14900,7 +14900,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -14931,7 +14931,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -14961,7 +14961,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -14992,7 +14992,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -15022,7 +15022,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -15053,7 +15053,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -15083,7 +15083,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -15114,7 +15114,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -15144,7 +15144,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -15175,7 +15175,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -15205,7 +15205,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -15236,7 +15236,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -15266,7 +15266,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -15297,7 +15297,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -15327,7 +15327,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -15358,7 +15358,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -15388,7 +15388,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -15419,7 +15419,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -15449,7 +15449,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -15480,7 +15480,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -15510,7 +15510,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -15541,7 +15541,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -15571,7 +15571,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -15602,7 +15602,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -15632,7 +15632,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -15663,7 +15663,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -15693,7 +15693,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -15724,7 +15724,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -15754,7 +15754,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -15785,7 +15785,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -15815,7 +15815,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -15846,7 +15846,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -15876,7 +15876,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -15907,6 +15907,67 @@ "pool": "Chrome-perf" } ], + "expiration": 72000, + "hard_timeout": 10800, + "ignore_task_failure": true, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_canvas_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-chromium" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_canvas_cases", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build45-b1--device4", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_canvas_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=reference", + "--output-trace-tag=_ref" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_canvas_cases.reference", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build45-b1--device4", + "os": "Android", + "pool": "Chrome-perf" + } + ], "expiration": 36000, "hard_timeout": 10800, "ignore_task_failure": true, @@ -15937,7 +15998,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -15968,7 +16029,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -15998,7 +16059,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -16029,7 +16090,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -16059,7 +16120,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -16090,7 +16151,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -16120,7 +16181,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -16151,7 +16212,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -16181,7 +16242,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -16212,7 +16273,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -16242,7 +16303,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -16273,6 +16334,67 @@ "pool": "Chrome-perf" } ], + "expiration": 72000, + "hard_timeout": 10800, + "ignore_task_failure": true, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_webgl_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-chromium" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_webgl_cases", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build16-b1--device5", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_webgl_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=reference", + "--output-trace-tag=_ref" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_webgl_cases.reference", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build16-b1--device5", + "os": "Android", + "pool": "Chrome-perf" + } + ], "expiration": 36000, "hard_timeout": 10800, "ignore_task_failure": true, @@ -16303,7 +16425,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -16334,7 +16456,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -16364,7 +16486,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -16395,129 +16517,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": true, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.cold.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-chromium" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.cold.blank_page", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build45-b1--device4", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.cold.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=reference", - "--output-trace-tag=_ref" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.cold.blank_page.reference", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build45-b1--device4", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": true, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.warm.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-chromium" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.warm.blank_page", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build15-b1--device7", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.warm.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=reference", - "--output-trace-tag=_ref" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.warm.blank_page.reference", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build15-b1--device7", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -16547,7 +16547,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -16578,7 +16578,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -16608,7 +16608,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -16639,7 +16639,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -16669,7 +16669,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -16700,7 +16700,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -16730,7 +16730,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -16761,7 +16761,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -16791,7 +16791,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -16822,7 +16822,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -16852,7 +16852,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -16883,7 +16883,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -16913,7 +16913,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -16944,7 +16944,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -16974,7 +16974,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17005,7 +17005,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -17035,7 +17035,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17066,7 +17066,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -17096,7 +17096,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17127,7 +17127,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -17157,7 +17157,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17188,7 +17188,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -17218,7 +17218,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17249,7 +17249,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -17279,7 +17279,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17310,7 +17310,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -17340,7 +17340,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17371,7 +17371,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -17401,7 +17401,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17432,7 +17432,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -17462,7 +17462,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17493,7 +17493,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -17514,7 +17514,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17544,7 +17544,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17575,7 +17575,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -17605,7 +17605,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17636,7 +17636,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -17666,7 +17666,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17697,7 +17697,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -17727,7 +17727,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17758,7 +17758,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -17793,7 +17793,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17824,7 +17824,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17855,7 +17855,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17886,7 +17886,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17917,7 +17917,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17948,7 +17948,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -17979,7 +17979,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18010,7 +18010,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18041,7 +18041,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18072,7 +18072,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18103,7 +18103,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18134,7 +18134,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18165,7 +18165,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18196,7 +18196,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18227,7 +18227,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18258,7 +18258,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18289,7 +18289,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18320,7 +18320,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18351,7 +18351,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18382,7 +18382,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18413,7 +18413,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18444,7 +18444,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 16200, "ignore_task_failure": false, "io_timeout": 3600, @@ -18475,7 +18475,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18506,7 +18506,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18537,7 +18537,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18568,7 +18568,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18599,7 +18599,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18630,7 +18630,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18661,7 +18661,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18692,7 +18692,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18723,7 +18723,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18754,7 +18754,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18785,7 +18785,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18816,7 +18816,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18847,7 +18847,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18878,7 +18878,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18909,7 +18909,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18940,7 +18940,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -18971,7 +18971,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19002,7 +19002,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19033,7 +19033,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19064,7 +19064,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19095,7 +19095,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19126,7 +19126,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19157,7 +19157,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19188,7 +19188,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19219,7 +19219,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19250,7 +19250,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19281,7 +19281,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19312,7 +19312,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19343,7 +19343,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19374,7 +19374,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19405,6 +19405,37 @@ "pool": "Chrome-perf" } ], + "expiration": 72000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_canvas_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-webview", + "--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk" + ], + "isolate_name": "telemetry_perf_webview_tests", + "name": "smoothness.tough_canvas_cases", + "override_compile_targets": [ + "telemetry_perf_webview_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build113-b1--device4", + "os": "Android", + "pool": "Chrome-perf" + } + ], "expiration": 36000, "hard_timeout": 10800, "ignore_task_failure": false, @@ -19436,7 +19467,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19467,7 +19498,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19498,7 +19529,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19529,7 +19560,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19560,7 +19591,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19591,6 +19622,37 @@ "pool": "Chrome-perf" } ], + "expiration": 72000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_webgl_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-webview", + "--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk" + ], + "isolate_name": "telemetry_perf_webview_tests", + "name": "smoothness.tough_webgl_cases", + "override_compile_targets": [ + "telemetry_perf_webview_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build113-b1--device7", + "os": "Android", + "pool": "Chrome-perf" + } + ], "expiration": 36000, "hard_timeout": 10800, "ignore_task_failure": false, @@ -19622,7 +19684,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19653,69 +19715,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.cold.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-webview", - "--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk" - ], - "isolate_name": "telemetry_perf_webview_tests", - "name": "start_with_ext.cold.blank_page", - "override_compile_targets": [ - "telemetry_perf_webview_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build114-b1--device4", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.warm.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-webview", - "--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk" - ], - "isolate_name": "telemetry_perf_webview_tests", - "name": "start_with_ext.warm.blank_page", - "override_compile_targets": [ - "telemetry_perf_webview_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build112-b1--device7", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19746,7 +19746,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19777,7 +19777,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19808,7 +19808,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19839,7 +19839,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19870,7 +19870,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19901,7 +19901,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19932,7 +19932,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19963,7 +19963,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -19994,7 +19994,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20025,7 +20025,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20056,7 +20056,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20087,7 +20087,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20118,7 +20118,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20149,7 +20149,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20180,7 +20180,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20211,7 +20211,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20242,7 +20242,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20273,7 +20273,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20304,7 +20304,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20335,7 +20335,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20369,7 +20369,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20400,7 +20400,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -20430,7 +20430,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20461,7 +20461,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -20491,7 +20491,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20522,7 +20522,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -20552,7 +20552,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20583,7 +20583,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -20613,7 +20613,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20644,7 +20644,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -20674,7 +20674,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20705,7 +20705,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -20735,7 +20735,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20766,7 +20766,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -20796,7 +20796,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20827,7 +20827,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -20857,7 +20857,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20888,7 +20888,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -20918,7 +20918,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -20949,7 +20949,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -20979,7 +20979,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -21010,7 +21010,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -21040,7 +21040,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -21071,7 +21071,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -21092,7 +21092,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -21122,7 +21122,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -21153,7 +21153,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -21183,7 +21183,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -21214,7 +21214,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -21244,7 +21244,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -21275,7 +21275,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -21305,7 +21305,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -21336,7 +21336,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -21366,7 +21366,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -21397,7 +21397,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -21427,7 +21427,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -21458,7 +21458,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -21479,7 +21479,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -21509,7 +21509,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -21540,7 +21540,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -21570,7 +21570,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -21601,7 +21601,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -21631,7 +21631,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -21662,7 +21662,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -21692,7 +21692,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 16200, "ignore_task_failure": false, "io_timeout": 3600, @@ -21723,7 +21723,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 16200, "ignore_task_failure": true, "io_timeout": 3600, @@ -21753,7 +21753,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -21784,7 +21784,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -21814,7 +21814,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -21845,7 +21845,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -21875,7 +21875,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -21906,7 +21906,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -21936,7 +21936,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -21967,7 +21967,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -21997,7 +21997,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -22028,7 +22028,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -22058,7 +22058,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -22089,7 +22089,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -22119,7 +22119,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -22150,7 +22150,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -22180,7 +22180,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -22211,7 +22211,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -22241,7 +22241,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -22271,7 +22271,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -22302,7 +22302,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -22332,7 +22332,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -22363,7 +22363,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -22393,7 +22393,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -22424,7 +22424,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -22454,7 +22454,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -22485,7 +22485,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -22515,7 +22515,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -22546,7 +22546,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -22576,7 +22576,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -22607,7 +22607,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -22637,7 +22637,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -22668,7 +22668,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -22698,7 +22698,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -22729,7 +22729,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -22759,7 +22759,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -22790,7 +22790,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -22820,7 +22820,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -22851,7 +22851,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -22881,7 +22881,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -22912,7 +22912,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -22942,7 +22942,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -22973,7 +22973,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -23003,7 +23003,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -23034,7 +23034,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -23064,7 +23064,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -23095,7 +23095,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -23125,7 +23125,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -23156,7 +23156,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -23186,7 +23186,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -23217,7 +23217,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -23247,7 +23247,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -23278,7 +23278,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -23308,7 +23308,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -23339,7 +23339,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -23369,7 +23369,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -23400,7 +23400,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -23430,7 +23430,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -23461,7 +23461,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -23491,7 +23491,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -23522,7 +23522,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -23552,7 +23552,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -23583,6 +23583,67 @@ "pool": "Chrome-perf" } ], + "expiration": 72000, + "hard_timeout": 10800, + "ignore_task_failure": true, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_canvas_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-chromium" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_canvas_cases", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build49-b1--device4", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_canvas_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=reference", + "--output-trace-tag=_ref" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_canvas_cases.reference", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build49-b1--device4", + "os": "Android", + "pool": "Chrome-perf" + } + ], "expiration": 36000, "hard_timeout": 10800, "ignore_task_failure": true, @@ -23613,7 +23674,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -23644,7 +23705,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -23674,7 +23735,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -23705,7 +23766,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -23735,7 +23796,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -23766,7 +23827,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -23796,7 +23857,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -23827,7 +23888,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -23857,7 +23918,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -23888,7 +23949,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -23918,7 +23979,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -23949,6 +24010,67 @@ "pool": "Chrome-perf" } ], + "expiration": 72000, + "hard_timeout": 10800, + "ignore_task_failure": true, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_webgl_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-chromium" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_webgl_cases", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build10-b1--device5", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_webgl_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=reference", + "--output-trace-tag=_ref" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_webgl_cases.reference", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build10-b1--device5", + "os": "Android", + "pool": "Chrome-perf" + } + ], "expiration": 36000, "hard_timeout": 10800, "ignore_task_failure": true, @@ -23979,7 +24101,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -24010,7 +24132,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -24040,7 +24162,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -24071,129 +24193,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": true, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.cold.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-chromium" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.cold.blank_page", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build49-b1--device4", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.cold.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=reference", - "--output-trace-tag=_ref" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.cold.blank_page.reference", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build49-b1--device4", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": true, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.warm.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-chromium" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.warm.blank_page", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build9-b1--device7", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.warm.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=reference", - "--output-trace-tag=_ref" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.warm.blank_page.reference", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build9-b1--device7", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -24223,7 +24223,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -24254,7 +24254,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -24284,7 +24284,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -24315,7 +24315,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -24345,7 +24345,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -24376,7 +24376,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -24406,7 +24406,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -24437,7 +24437,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -24467,7 +24467,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -24498,7 +24498,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -24528,7 +24528,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -24559,7 +24559,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -24589,7 +24589,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -24620,7 +24620,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -24650,7 +24650,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -24681,7 +24681,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -24711,7 +24711,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -24742,7 +24742,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -24772,7 +24772,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -24803,7 +24803,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -24833,7 +24833,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -24864,7 +24864,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -24894,7 +24894,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -24925,7 +24925,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -24955,7 +24955,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -24986,7 +24986,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -25016,7 +25016,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -25047,7 +25047,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -25077,7 +25077,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -25108,7 +25108,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -25138,7 +25138,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -25169,7 +25169,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -25190,7 +25190,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -25220,7 +25220,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -25251,7 +25251,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -25281,7 +25281,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -25312,7 +25312,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -25342,7 +25342,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -25373,7 +25373,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -25403,7 +25403,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -25434,7 +25434,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -25468,7 +25468,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -25499,7 +25499,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -25529,7 +25529,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -25560,7 +25560,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -25590,7 +25590,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -25621,7 +25621,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -25651,7 +25651,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -25682,7 +25682,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -25712,7 +25712,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -25743,7 +25743,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -25773,7 +25773,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -25804,7 +25804,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -25834,7 +25834,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -25865,7 +25865,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -25895,7 +25895,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -25926,7 +25926,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -25956,7 +25956,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -25987,7 +25987,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -26017,7 +26017,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -26048,7 +26048,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -26078,7 +26078,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -26109,7 +26109,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -26139,7 +26139,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -26170,7 +26170,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -26200,7 +26200,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -26231,7 +26231,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -26261,7 +26261,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -26292,7 +26292,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -26322,7 +26322,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -26353,7 +26353,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -26374,7 +26374,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -26404,7 +26404,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -26435,7 +26435,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -26465,7 +26465,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -26496,7 +26496,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -26526,7 +26526,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -26557,7 +26557,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -26587,7 +26587,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 16200, "ignore_task_failure": false, "io_timeout": 3600, @@ -26618,7 +26618,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 16200, "ignore_task_failure": true, "io_timeout": 3600, @@ -26648,7 +26648,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -26679,7 +26679,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -26709,7 +26709,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -26740,7 +26740,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -26770,7 +26770,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -26801,7 +26801,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -26831,7 +26831,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -26862,7 +26862,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -26892,7 +26892,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -26923,7 +26923,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -26953,7 +26953,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -26984,7 +26984,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -27014,7 +27014,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -27045,7 +27045,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -27075,7 +27075,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -27106,7 +27106,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -27136,7 +27136,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -27166,7 +27166,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -27197,7 +27197,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -27227,7 +27227,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -27258,7 +27258,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -27288,7 +27288,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -27319,7 +27319,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -27349,7 +27349,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -27380,7 +27380,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -27410,7 +27410,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -27441,7 +27441,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -27471,7 +27471,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -27502,7 +27502,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -27532,7 +27532,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -27563,7 +27563,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -27593,7 +27593,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -27624,7 +27624,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -27654,7 +27654,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -27685,7 +27685,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -27715,7 +27715,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -27746,7 +27746,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -27776,7 +27776,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -27807,7 +27807,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -27837,7 +27837,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -27868,7 +27868,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -27898,7 +27898,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -27929,7 +27929,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -27959,7 +27959,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -27990,7 +27990,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -28020,7 +28020,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -28051,7 +28051,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -28081,7 +28081,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -28112,7 +28112,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -28142,7 +28142,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -28173,7 +28173,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -28203,7 +28203,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -28234,7 +28234,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -28264,7 +28264,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -28295,7 +28295,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -28325,7 +28325,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -28356,7 +28356,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -28386,7 +28386,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -28417,7 +28417,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -28447,7 +28447,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -28478,6 +28478,67 @@ "pool": "Chrome-perf" } ], + "expiration": 72000, + "hard_timeout": 10800, + "ignore_task_failure": true, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_canvas_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-chromium" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_canvas_cases", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build47-b1--device3", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_canvas_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=reference", + "--output-trace-tag=_ref" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_canvas_cases.reference", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build47-b1--device3", + "os": "Android", + "pool": "Chrome-perf" + } + ], "expiration": 36000, "hard_timeout": 10800, "ignore_task_failure": true, @@ -28508,7 +28569,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -28539,7 +28600,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -28569,7 +28630,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -28600,7 +28661,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -28630,7 +28691,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -28661,7 +28722,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -28691,7 +28752,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -28722,7 +28783,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -28752,7 +28813,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -28783,7 +28844,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -28813,7 +28874,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -28844,6 +28905,67 @@ "pool": "Chrome-perf" } ], + "expiration": 72000, + "hard_timeout": 10800, + "ignore_task_failure": true, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_webgl_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-chromium" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_webgl_cases", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build18-b1--device6", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600, + "upload_test_results": false + } + }, + { + "args": [ + "smoothness.tough_webgl_cases", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=reference", + "--output-trace-tag=_ref" + ], + "isolate_name": "telemetry_perf_tests", + "name": "smoothness.tough_webgl_cases.reference", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build18-b1--device6", + "os": "Android", + "pool": "Chrome-perf" + } + ], "expiration": 36000, "hard_timeout": 10800, "ignore_task_failure": true, @@ -28874,7 +28996,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -28905,7 +29027,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -28935,7 +29057,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -28966,129 +29088,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": true, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.cold.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-chromium" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.cold.blank_page", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build47-b1--device4", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.cold.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=reference", - "--output-trace-tag=_ref" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.cold.blank_page.reference", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build47-b1--device4", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": true, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.warm.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-chromium" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.warm.blank_page", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build17-b1--device7", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600, - "upload_test_results": false - } - }, - { - "args": [ - "start_with_ext.warm.blank_page", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=reference", - "--output-trace-tag=_ref" - ], - "isolate_name": "telemetry_perf_tests", - "name": "start_with_ext.warm.blank_page.reference", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build17-b1--device7", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -29118,7 +29118,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -29149,7 +29149,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -29179,7 +29179,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -29210,7 +29210,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -29240,7 +29240,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -29271,7 +29271,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -29301,7 +29301,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -29332,7 +29332,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -29362,7 +29362,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -29393,7 +29393,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -29423,7 +29423,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -29454,7 +29454,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -29484,7 +29484,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -29515,7 +29515,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -29545,7 +29545,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -29576,7 +29576,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -29606,7 +29606,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -29637,7 +29637,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -29667,7 +29667,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -29698,7 +29698,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -29728,7 +29728,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -29759,7 +29759,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -29789,7 +29789,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -29820,7 +29820,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -29850,7 +29850,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -29881,7 +29881,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -29911,7 +29911,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -29942,7 +29942,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -29972,7 +29972,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -30003,7 +30003,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -30033,7 +30033,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -30064,7 +30064,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -30085,7 +30085,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -30115,7 +30115,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -30146,7 +30146,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -30176,7 +30176,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -30207,7 +30207,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -30237,7 +30237,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -30268,7 +30268,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -30298,7 +30298,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -30329,7 +30329,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -30368,7 +30368,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -30399,7 +30399,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -30429,7 +30429,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -30460,7 +30460,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -30490,7 +30490,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -30521,7 +30521,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -30551,7 +30551,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -30582,7 +30582,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -30612,7 +30612,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -30643,7 +30643,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -30673,7 +30673,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -30704,7 +30704,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -30734,7 +30734,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -30765,7 +30765,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -30795,7 +30795,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -30826,7 +30826,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -30856,7 +30856,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -30887,7 +30887,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -30917,7 +30917,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -30948,7 +30948,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -30978,7 +30978,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -31009,7 +31009,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -31039,7 +31039,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -31070,7 +31070,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -31100,7 +31100,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -31131,7 +31131,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -31161,7 +31161,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -31192,7 +31192,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -31222,7 +31222,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -31253,7 +31253,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -31283,7 +31283,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -31314,7 +31314,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -31344,7 +31344,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -31375,7 +31375,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -31405,7 +31405,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -31436,7 +31436,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -31466,7 +31466,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -31497,7 +31497,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -31527,7 +31527,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -31558,7 +31558,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -31588,7 +31588,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -31619,7 +31619,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -31649,7 +31649,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -31680,7 +31680,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -31701,7 +31701,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -31731,7 +31731,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -31762,7 +31762,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -31792,7 +31792,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -31823,7 +31823,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -31853,7 +31853,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -31884,7 +31884,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -31914,7 +31914,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -31945,7 +31945,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -31966,7 +31966,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -31996,7 +31996,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -32027,7 +32027,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -32057,7 +32057,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -32088,7 +32088,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -32118,7 +32118,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -32149,7 +32149,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -32170,7 +32170,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -32200,7 +32200,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -32231,7 +32231,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -32261,7 +32261,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -32292,7 +32292,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -32322,7 +32322,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -32353,7 +32353,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -32383,7 +32383,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -32414,7 +32414,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -32444,7 +32444,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -32475,7 +32475,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -32505,7 +32505,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -32535,7 +32535,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -32566,7 +32566,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -32596,7 +32596,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -32627,7 +32627,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -32657,7 +32657,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -32688,7 +32688,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -32718,7 +32718,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -32749,7 +32749,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -32779,7 +32779,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -32810,7 +32810,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -32840,7 +32840,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -32871,7 +32871,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -32901,7 +32901,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -32932,7 +32932,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -32962,7 +32962,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -32993,7 +32993,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -33023,7 +33023,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -33054,7 +33054,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -33084,7 +33084,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -33115,7 +33115,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -33145,7 +33145,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -33176,7 +33176,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -33206,7 +33206,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -33237,7 +33237,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -33267,7 +33267,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -33298,7 +33298,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -33328,7 +33328,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -33359,7 +33359,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -33389,7 +33389,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -33420,7 +33420,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -33450,7 +33450,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -33481,7 +33481,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -33511,7 +33511,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -33542,7 +33542,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -33572,7 +33572,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -33603,7 +33603,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -33633,7 +33633,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -33664,7 +33664,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -33694,7 +33694,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -33725,7 +33725,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -33755,7 +33755,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -33786,7 +33786,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -33816,7 +33816,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -33847,7 +33847,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -33877,7 +33877,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -33908,7 +33908,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -33938,7 +33938,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -33969,7 +33969,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -33999,7 +33999,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -34030,7 +34030,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -34060,7 +34060,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -34091,7 +34091,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -34121,7 +34121,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -34152,7 +34152,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -34182,7 +34182,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -34213,7 +34213,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -34243,7 +34243,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -34274,7 +34274,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -34304,7 +34304,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -34335,7 +34335,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -34365,7 +34365,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -34396,7 +34396,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -34426,7 +34426,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -34457,7 +34457,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -34487,7 +34487,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -34518,7 +34518,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -34548,7 +34548,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -34579,7 +34579,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -34609,7 +34609,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -34640,7 +34640,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -34670,7 +34670,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -34701,7 +34701,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -34731,7 +34731,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -34762,7 +34762,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -34792,7 +34792,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -34823,7 +34823,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -34853,7 +34853,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -34884,7 +34884,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -34914,7 +34914,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -34945,7 +34945,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -34975,7 +34975,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -35006,7 +35006,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -35036,7 +35036,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -35067,7 +35067,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -35097,7 +35097,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -35128,7 +35128,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -35149,7 +35149,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -35179,7 +35179,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -35210,7 +35210,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -35240,7 +35240,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -35271,7 +35271,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -35301,7 +35301,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -35332,7 +35332,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -35362,7 +35362,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -35393,7 +35393,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -35423,7 +35423,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -35454,7 +35454,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -35488,7 +35488,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -35519,7 +35519,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -35549,7 +35549,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -35580,7 +35580,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -35610,7 +35610,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -35641,7 +35641,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -35671,7 +35671,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -35702,7 +35702,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -35732,7 +35732,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -35763,7 +35763,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -35793,7 +35793,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -35824,7 +35824,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -35854,7 +35854,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -35885,7 +35885,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -35915,7 +35915,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -35946,7 +35946,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -35976,7 +35976,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -36007,7 +36007,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -36037,7 +36037,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -36068,7 +36068,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -36098,7 +36098,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -36129,7 +36129,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -36159,7 +36159,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -36190,7 +36190,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -36220,7 +36220,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -36251,7 +36251,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -36281,7 +36281,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -36312,7 +36312,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -36342,7 +36342,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -36373,7 +36373,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -36403,7 +36403,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -36434,7 +36434,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -36464,7 +36464,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -36495,7 +36495,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -36525,7 +36525,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -36556,7 +36556,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -36586,7 +36586,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -36617,7 +36617,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -36647,7 +36647,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -36678,7 +36678,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -36708,7 +36708,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -36739,7 +36739,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -36769,7 +36769,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -36800,7 +36800,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -36830,7 +36830,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -36861,7 +36861,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -36891,7 +36891,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -36922,7 +36922,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -36952,7 +36952,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -36983,7 +36983,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -37013,7 +37013,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -37044,7 +37044,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -37065,7 +37065,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -37095,7 +37095,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -37126,7 +37126,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -37156,7 +37156,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -37187,7 +37187,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -37217,7 +37217,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -37248,7 +37248,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -37278,7 +37278,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -37309,7 +37309,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -37339,7 +37339,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -37370,7 +37370,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -37400,7 +37400,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -37431,7 +37431,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -37461,7 +37461,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -37492,7 +37492,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -37522,7 +37522,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -37553,7 +37553,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -37583,7 +37583,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -37613,7 +37613,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -37644,7 +37644,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -37674,7 +37674,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -37705,7 +37705,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -37735,7 +37735,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -37766,7 +37766,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -37796,7 +37796,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -37827,7 +37827,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -37857,7 +37857,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -37888,7 +37888,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -37918,7 +37918,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -37949,7 +37949,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -37979,7 +37979,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -38010,7 +38010,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -38040,7 +38040,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -38071,7 +38071,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -38101,7 +38101,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -38132,7 +38132,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -38162,7 +38162,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -38193,7 +38193,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -38223,7 +38223,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -38254,7 +38254,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -38284,7 +38284,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -38315,7 +38315,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -38345,7 +38345,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -38376,7 +38376,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -38406,7 +38406,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -38437,7 +38437,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -38467,7 +38467,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -38498,7 +38498,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -38528,7 +38528,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -38559,7 +38559,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -38589,7 +38589,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -38620,7 +38620,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -38650,7 +38650,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -38681,7 +38681,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -38711,7 +38711,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -38742,7 +38742,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -38772,7 +38772,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -38803,7 +38803,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -38833,7 +38833,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -38864,7 +38864,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -38894,7 +38894,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -38925,7 +38925,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -38955,7 +38955,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -38986,7 +38986,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -39016,7 +39016,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -39047,7 +39047,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -39077,7 +39077,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -39108,7 +39108,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -39138,7 +39138,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -39169,7 +39169,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -39199,7 +39199,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -39230,7 +39230,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -39260,7 +39260,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -39291,7 +39291,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -39321,7 +39321,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -39352,7 +39352,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -39382,7 +39382,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -39413,7 +39413,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -39443,7 +39443,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -39474,7 +39474,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -39504,7 +39504,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -39535,7 +39535,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -39565,7 +39565,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -39596,7 +39596,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -39626,7 +39626,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -39657,7 +39657,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -39687,7 +39687,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -39718,7 +39718,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -39748,7 +39748,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -39779,7 +39779,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -39809,7 +39809,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -39840,7 +39840,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -39870,7 +39870,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -39901,7 +39901,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -39931,7 +39931,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -39962,7 +39962,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -39992,7 +39992,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -40023,7 +40023,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -40053,7 +40053,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -40084,7 +40084,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -40114,7 +40114,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -40145,7 +40145,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -40175,7 +40175,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -40206,7 +40206,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -40236,7 +40236,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -40267,7 +40267,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -40297,7 +40297,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -40328,7 +40328,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -40358,7 +40358,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -40389,7 +40389,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -40419,7 +40419,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -40450,7 +40450,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -40480,7 +40480,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -40511,7 +40511,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -40545,7 +40545,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -40576,7 +40576,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -40606,7 +40606,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -40637,7 +40637,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -40667,7 +40667,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -40698,7 +40698,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -40728,7 +40728,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -40759,7 +40759,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -40789,7 +40789,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -40820,7 +40820,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -40850,7 +40850,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -40881,7 +40881,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -40911,7 +40911,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -40942,7 +40942,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -40972,7 +40972,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -41003,7 +41003,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -41033,7 +41033,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -41064,7 +41064,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -41094,7 +41094,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -41125,7 +41125,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -41155,7 +41155,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -41186,7 +41186,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -41216,7 +41216,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -41247,7 +41247,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -41277,7 +41277,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -41308,7 +41308,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -41338,7 +41338,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -41369,7 +41369,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -41399,7 +41399,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -41430,7 +41430,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -41460,7 +41460,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -41491,7 +41491,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -41521,7 +41521,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -41552,7 +41552,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -41582,7 +41582,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -41613,7 +41613,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -41643,7 +41643,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -41674,7 +41674,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -41704,7 +41704,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -41735,7 +41735,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -41765,7 +41765,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -41796,7 +41796,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -41826,7 +41826,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -41857,7 +41857,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -41887,7 +41887,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -41918,7 +41918,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -41948,7 +41948,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -41979,7 +41979,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -42009,7 +42009,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -42040,7 +42040,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -42070,7 +42070,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -42101,7 +42101,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -42131,7 +42131,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -42162,7 +42162,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -42192,7 +42192,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -42223,7 +42223,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -42253,7 +42253,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -42284,7 +42284,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -42305,7 +42305,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -42335,7 +42335,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -42366,7 +42366,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -42396,7 +42396,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -42427,7 +42427,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -42457,7 +42457,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -42488,7 +42488,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -42518,7 +42518,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -42549,7 +42549,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -42579,7 +42579,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -42610,7 +42610,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -42640,7 +42640,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -42670,7 +42670,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -42701,7 +42701,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -42731,7 +42731,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -42762,7 +42762,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -42792,7 +42792,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -42823,7 +42823,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -42853,7 +42853,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -42884,7 +42884,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -42914,7 +42914,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -42945,7 +42945,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -42975,7 +42975,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -43006,7 +43006,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -43036,7 +43036,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -43067,7 +43067,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -43097,7 +43097,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -43128,7 +43128,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -43158,7 +43158,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -43189,7 +43189,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -43219,7 +43219,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -43250,7 +43250,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -43280,7 +43280,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -43311,7 +43311,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -43341,7 +43341,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -43372,7 +43372,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -43402,7 +43402,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -43433,7 +43433,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -43463,7 +43463,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -43494,7 +43494,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -43524,7 +43524,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -43555,7 +43555,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -43585,7 +43585,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -43616,7 +43616,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -43646,7 +43646,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -43677,7 +43677,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -43707,7 +43707,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -43738,7 +43738,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -43768,7 +43768,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -43799,7 +43799,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -43829,7 +43829,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -43860,7 +43860,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -43890,7 +43890,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -43921,7 +43921,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -43951,7 +43951,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -43982,7 +43982,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -44012,7 +44012,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -44043,7 +44043,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -44073,7 +44073,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -44104,7 +44104,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -44134,7 +44134,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -44165,7 +44165,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -44195,7 +44195,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -44226,7 +44226,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -44256,7 +44256,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -44287,7 +44287,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -44317,7 +44317,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -44348,7 +44348,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -44378,7 +44378,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -44409,7 +44409,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -44439,7 +44439,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -44470,7 +44470,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -44500,7 +44500,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -44531,7 +44531,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -44561,7 +44561,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -44592,7 +44592,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -44622,7 +44622,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -44653,7 +44653,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -44683,7 +44683,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -44714,7 +44714,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -44744,7 +44744,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -44775,7 +44775,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -44805,7 +44805,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -44836,7 +44836,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -44866,7 +44866,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -44897,7 +44897,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -44927,7 +44927,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -44958,7 +44958,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -44988,7 +44988,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -45019,7 +45019,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -45049,7 +45049,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -45080,7 +45080,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -45110,7 +45110,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -45141,7 +45141,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -45171,7 +45171,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -45202,7 +45202,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -45232,7 +45232,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -45263,7 +45263,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -45293,7 +45293,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -45324,7 +45324,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -45354,7 +45354,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -45385,7 +45385,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -45415,7 +45415,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -45446,7 +45446,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -45476,7 +45476,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -45507,7 +45507,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -45537,7 +45537,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -45568,7 +45568,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -45602,7 +45602,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -45633,7 +45633,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -45663,7 +45663,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -45694,7 +45694,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -45724,7 +45724,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -45755,7 +45755,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -45785,7 +45785,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -45816,7 +45816,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -45846,7 +45846,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -45877,7 +45877,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -45907,7 +45907,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -45938,7 +45938,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -45968,7 +45968,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -45999,7 +45999,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -46029,7 +46029,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -46060,7 +46060,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -46090,7 +46090,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -46121,7 +46121,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -46151,7 +46151,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -46182,7 +46182,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -46212,7 +46212,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -46243,7 +46243,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -46273,7 +46273,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -46304,7 +46304,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -46334,7 +46334,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -46365,7 +46365,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -46395,7 +46395,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -46426,7 +46426,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -46456,7 +46456,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -46487,7 +46487,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -46517,7 +46517,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -46548,7 +46548,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -46578,7 +46578,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -46609,7 +46609,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -46639,7 +46639,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -46670,7 +46670,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -46700,7 +46700,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -46731,7 +46731,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -46761,7 +46761,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -46792,7 +46792,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -46822,7 +46822,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -46853,7 +46853,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -46883,7 +46883,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -46914,7 +46914,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -46944,7 +46944,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -46975,7 +46975,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -47005,7 +47005,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -47036,7 +47036,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -47066,7 +47066,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -47097,7 +47097,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -47127,7 +47127,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -47158,7 +47158,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -47188,7 +47188,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -47219,7 +47219,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -47249,7 +47249,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -47280,7 +47280,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -47310,7 +47310,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -47341,7 +47341,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -47371,7 +47371,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -47402,7 +47402,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -47432,7 +47432,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -47463,7 +47463,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -47493,7 +47493,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -47524,7 +47524,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -47554,7 +47554,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -47585,7 +47585,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -47615,7 +47615,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -47646,7 +47646,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -47667,7 +47667,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -47697,7 +47697,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -47727,7 +47727,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -47758,7 +47758,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -47788,7 +47788,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -47819,7 +47819,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -47849,7 +47849,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -47880,7 +47880,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -47910,7 +47910,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -47941,7 +47941,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -47971,7 +47971,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -48002,7 +48002,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -48032,7 +48032,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -48063,7 +48063,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -48093,7 +48093,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -48124,7 +48124,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -48154,7 +48154,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -48185,7 +48185,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -48215,7 +48215,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -48246,7 +48246,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -48276,7 +48276,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -48307,7 +48307,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -48337,7 +48337,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -48368,7 +48368,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -48398,7 +48398,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -48429,7 +48429,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -48459,7 +48459,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -48490,7 +48490,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -48520,7 +48520,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -48551,7 +48551,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -48581,7 +48581,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -48612,7 +48612,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -48642,7 +48642,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -48673,7 +48673,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -48703,7 +48703,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -48734,7 +48734,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -48764,7 +48764,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -48795,7 +48795,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -48825,7 +48825,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -48856,7 +48856,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -48886,7 +48886,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -48917,7 +48917,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -48947,7 +48947,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -48978,7 +48978,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -49008,7 +49008,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -49039,7 +49039,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -49069,7 +49069,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -49100,7 +49100,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -49130,7 +49130,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -49161,7 +49161,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -49191,7 +49191,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -49222,7 +49222,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -49252,7 +49252,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -49283,7 +49283,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -49313,7 +49313,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -49344,7 +49344,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -49374,7 +49374,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -49405,7 +49405,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -49435,7 +49435,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -49466,7 +49466,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -49496,7 +49496,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -49527,7 +49527,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -49557,7 +49557,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -49588,7 +49588,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -49618,7 +49618,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -49649,7 +49649,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -49679,7 +49679,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -49710,7 +49710,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -49740,7 +49740,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -49771,7 +49771,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -49801,7 +49801,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -49832,7 +49832,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -49862,7 +49862,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -49893,7 +49893,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -49923,7 +49923,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -49954,7 +49954,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -49984,7 +49984,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -50015,7 +50015,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -50045,7 +50045,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -50076,7 +50076,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -50106,7 +50106,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -50137,7 +50137,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -50167,7 +50167,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -50198,7 +50198,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -50228,7 +50228,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -50259,7 +50259,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -50289,7 +50289,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -50320,7 +50320,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -50350,7 +50350,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -50381,7 +50381,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -50411,7 +50411,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -50442,7 +50442,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -50472,7 +50472,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -50503,7 +50503,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -50533,7 +50533,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -50564,7 +50564,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -50594,7 +50594,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -50625,7 +50625,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -50659,7 +50659,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -50690,7 +50690,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -50720,7 +50720,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -50751,7 +50751,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -50781,7 +50781,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -50812,7 +50812,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -50842,7 +50842,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -50873,7 +50873,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -50903,7 +50903,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -50934,7 +50934,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -50964,7 +50964,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -50995,7 +50995,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -51025,7 +51025,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -51056,7 +51056,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -51086,7 +51086,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -51117,7 +51117,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -51147,7 +51147,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -51178,7 +51178,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -51208,7 +51208,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -51239,7 +51239,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -51269,7 +51269,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -51300,7 +51300,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -51330,7 +51330,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -51361,7 +51361,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -51391,7 +51391,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -51422,7 +51422,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -51452,7 +51452,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -51483,7 +51483,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -51513,7 +51513,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -51544,7 +51544,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -51574,7 +51574,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -51605,7 +51605,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -51635,7 +51635,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -51666,7 +51666,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -51696,7 +51696,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -51727,7 +51727,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -51757,7 +51757,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -51788,7 +51788,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -51818,7 +51818,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -51849,7 +51849,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -51879,7 +51879,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -51910,7 +51910,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -51940,7 +51940,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -51971,7 +51971,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -52001,7 +52001,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -52032,7 +52032,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -52062,7 +52062,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -52093,7 +52093,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -52123,7 +52123,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -52154,7 +52154,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -52184,7 +52184,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -52215,7 +52215,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -52245,7 +52245,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -52276,7 +52276,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -52306,7 +52306,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -52337,7 +52337,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -52367,7 +52367,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -52398,7 +52398,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -52428,7 +52428,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -52459,7 +52459,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -52489,7 +52489,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -52520,7 +52520,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -52550,7 +52550,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -52581,7 +52581,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -52611,7 +52611,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -52642,7 +52642,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -52672,7 +52672,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -52703,7 +52703,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -52733,7 +52733,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -52763,7 +52763,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -52794,7 +52794,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -52824,7 +52824,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -52855,7 +52855,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -52885,7 +52885,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -52916,7 +52916,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -52946,7 +52946,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -52977,7 +52977,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -53007,7 +53007,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -53038,7 +53038,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -53068,7 +53068,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -53099,7 +53099,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -53129,7 +53129,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -53160,7 +53160,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -53190,7 +53190,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -53221,7 +53221,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -53251,7 +53251,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -53282,7 +53282,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -53312,7 +53312,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -53343,7 +53343,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -53373,7 +53373,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -53404,7 +53404,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -53434,7 +53434,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -53465,7 +53465,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -53495,7 +53495,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -53526,7 +53526,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -53556,7 +53556,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -53587,7 +53587,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -53617,7 +53617,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -53648,7 +53648,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -53678,7 +53678,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -53709,7 +53709,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -53739,7 +53739,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -53770,7 +53770,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -53800,7 +53800,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -53831,7 +53831,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -53861,7 +53861,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -53892,7 +53892,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -53922,7 +53922,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -53953,7 +53953,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -53983,7 +53983,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -54014,7 +54014,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -54044,7 +54044,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -54075,7 +54075,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -54105,7 +54105,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -54136,7 +54136,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -54166,7 +54166,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -54197,7 +54197,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -54227,7 +54227,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -54258,7 +54258,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -54288,7 +54288,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -54319,7 +54319,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -54349,7 +54349,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -54380,7 +54380,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -54410,7 +54410,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -54441,7 +54441,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -54471,7 +54471,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -54502,7 +54502,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -54532,7 +54532,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -54563,7 +54563,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -54593,7 +54593,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -54624,7 +54624,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -54654,7 +54654,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -54685,7 +54685,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -54715,7 +54715,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -54746,7 +54746,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -54776,7 +54776,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -54807,7 +54807,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -54837,7 +54837,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -54868,7 +54868,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -54898,7 +54898,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -54929,7 +54929,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -54959,7 +54959,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -54990,7 +54990,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -55020,7 +55020,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -55051,7 +55051,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -55081,7 +55081,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -55112,7 +55112,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -55142,7 +55142,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -55173,7 +55173,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -55203,7 +55203,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -55234,7 +55234,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -55264,7 +55264,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -55295,7 +55295,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -55325,7 +55325,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -55356,7 +55356,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -55386,7 +55386,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -55417,7 +55417,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -55447,7 +55447,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -55478,7 +55478,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -55508,7 +55508,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -55539,7 +55539,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -55569,7 +55569,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -55600,7 +55600,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -55630,7 +55630,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -55661,7 +55661,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -55695,7 +55695,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -55726,7 +55726,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -55756,7 +55756,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -55787,7 +55787,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -55817,7 +55817,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -55848,7 +55848,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -55878,7 +55878,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -55909,7 +55909,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -55939,7 +55939,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -55970,7 +55970,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -56000,7 +56000,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -56031,7 +56031,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -56061,7 +56061,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -56092,7 +56092,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -56122,7 +56122,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -56153,7 +56153,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -56183,7 +56183,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -56214,7 +56214,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -56244,7 +56244,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -56275,7 +56275,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -56305,7 +56305,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -56336,7 +56336,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -56366,7 +56366,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -56397,7 +56397,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -56427,7 +56427,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -56458,7 +56458,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -56488,7 +56488,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -56519,7 +56519,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -56549,7 +56549,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -56580,7 +56580,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -56610,7 +56610,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -56641,7 +56641,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -56671,7 +56671,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -56702,7 +56702,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -56732,7 +56732,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -56763,7 +56763,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -56793,7 +56793,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -56824,7 +56824,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -56854,7 +56854,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -56885,7 +56885,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -56915,7 +56915,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -56946,7 +56946,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -56976,7 +56976,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -57007,7 +57007,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -57037,7 +57037,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -57068,7 +57068,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -57098,7 +57098,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -57129,7 +57129,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -57159,7 +57159,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -57190,7 +57190,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -57220,7 +57220,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -57251,7 +57251,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -57281,7 +57281,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -57312,7 +57312,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -57342,7 +57342,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -57373,7 +57373,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -57403,7 +57403,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -57434,7 +57434,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -57464,7 +57464,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -57495,7 +57495,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -57525,7 +57525,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -57556,7 +57556,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -57586,7 +57586,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -57617,7 +57617,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -57647,7 +57647,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -57678,7 +57678,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -57708,7 +57708,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -57739,7 +57739,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -57760,7 +57760,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -57790,7 +57790,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -57820,7 +57820,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -57851,7 +57851,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -57881,7 +57881,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -57912,7 +57912,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -57942,7 +57942,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -57973,7 +57973,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -58003,7 +58003,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -58034,7 +58034,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -58064,7 +58064,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -58095,7 +58095,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -58125,7 +58125,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -58156,7 +58156,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -58186,7 +58186,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -58217,7 +58217,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -58247,7 +58247,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -58278,7 +58278,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -58308,7 +58308,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -58339,7 +58339,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -58369,7 +58369,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -58400,7 +58400,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -58430,7 +58430,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -58461,7 +58461,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -58491,7 +58491,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -58522,7 +58522,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -58552,7 +58552,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -58583,7 +58583,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -58613,7 +58613,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -58644,7 +58644,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -58674,7 +58674,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -58705,7 +58705,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -58735,7 +58735,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -58766,7 +58766,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -58796,7 +58796,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -58827,7 +58827,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -58857,7 +58857,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -58888,7 +58888,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -58918,7 +58918,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -58949,7 +58949,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -58979,7 +58979,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -59010,7 +59010,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -59040,7 +59040,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -59071,7 +59071,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -59101,7 +59101,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -59132,7 +59132,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -59162,7 +59162,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -59193,7 +59193,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -59223,7 +59223,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -59254,7 +59254,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -59284,7 +59284,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -59315,7 +59315,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -59345,7 +59345,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -59376,7 +59376,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -59406,7 +59406,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -59437,7 +59437,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -59467,7 +59467,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -59498,7 +59498,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -59528,7 +59528,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -59559,7 +59559,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -59589,7 +59589,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -59620,7 +59620,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -59650,7 +59650,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -59681,7 +59681,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -59711,7 +59711,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -59742,7 +59742,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -59772,7 +59772,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -59803,7 +59803,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -59833,7 +59833,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -59864,7 +59864,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -59894,7 +59894,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -59925,7 +59925,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -59955,7 +59955,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -59986,7 +59986,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -60016,7 +60016,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -60047,7 +60047,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -60077,7 +60077,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -60108,7 +60108,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -60138,7 +60138,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -60169,7 +60169,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -60199,7 +60199,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -60230,7 +60230,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -60260,7 +60260,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -60291,7 +60291,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -60321,7 +60321,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -60352,7 +60352,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -60382,7 +60382,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -60413,7 +60413,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -60443,7 +60443,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -60474,7 +60474,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -60504,7 +60504,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -60535,7 +60535,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -60565,7 +60565,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -60596,7 +60596,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -60626,7 +60626,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -60657,7 +60657,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -60687,7 +60687,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -60718,7 +60718,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -60752,7 +60752,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -60783,7 +60783,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -60813,7 +60813,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -60844,7 +60844,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -60874,7 +60874,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -60905,7 +60905,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -60935,7 +60935,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -60966,7 +60966,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -60996,7 +60996,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -61027,7 +61027,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -61057,7 +61057,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -61088,7 +61088,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -61118,7 +61118,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -61149,7 +61149,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -61179,7 +61179,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -61210,7 +61210,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -61240,7 +61240,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -61271,7 +61271,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -61301,7 +61301,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -61332,7 +61332,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -61362,7 +61362,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -61393,7 +61393,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -61423,7 +61423,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -61454,7 +61454,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -61484,7 +61484,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -61515,7 +61515,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -61545,7 +61545,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -61576,7 +61576,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -61606,7 +61606,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -61637,7 +61637,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -61667,7 +61667,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -61698,7 +61698,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -61728,7 +61728,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -61759,7 +61759,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -61789,7 +61789,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -61820,7 +61820,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -61850,7 +61850,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -61881,7 +61881,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -61911,7 +61911,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -61942,7 +61942,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -61972,7 +61972,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62003,7 +62003,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -62033,7 +62033,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62064,7 +62064,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -62094,7 +62094,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62125,7 +62125,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -62155,7 +62155,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62186,7 +62186,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -62216,7 +62216,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62247,7 +62247,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -62277,7 +62277,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62308,7 +62308,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -62338,7 +62338,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62369,7 +62369,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -62399,7 +62399,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62430,7 +62430,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -62460,7 +62460,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62491,7 +62491,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -62521,7 +62521,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62552,7 +62552,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -62582,7 +62582,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62613,7 +62613,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -62643,7 +62643,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62674,7 +62674,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -62704,7 +62704,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62735,7 +62735,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -62765,7 +62765,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62796,7 +62796,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -62817,7 +62817,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62847,7 +62847,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62877,7 +62877,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62908,7 +62908,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -62938,7 +62938,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -62969,7 +62969,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -62999,7 +62999,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -63030,7 +63030,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -63060,7 +63060,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -63091,7 +63091,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -63121,7 +63121,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -63152,7 +63152,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -63182,7 +63182,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -63213,7 +63213,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -63243,7 +63243,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -63274,7 +63274,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -63304,7 +63304,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -63335,7 +63335,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -63365,7 +63365,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -63396,7 +63396,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -63426,7 +63426,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -63457,7 +63457,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -63487,7 +63487,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -63518,7 +63518,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -63548,7 +63548,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -63579,7 +63579,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -63609,7 +63609,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -63640,7 +63640,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -63670,7 +63670,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -63701,7 +63701,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -63731,7 +63731,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -63762,7 +63762,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -63792,7 +63792,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -63823,7 +63823,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -63853,7 +63853,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -63884,7 +63884,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -63914,7 +63914,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -63945,7 +63945,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -63975,7 +63975,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -64006,7 +64006,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -64036,7 +64036,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -64067,7 +64067,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -64097,7 +64097,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -64128,7 +64128,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -64158,7 +64158,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -64189,7 +64189,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -64219,7 +64219,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -64250,7 +64250,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -64280,7 +64280,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -64311,7 +64311,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -64341,7 +64341,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -64372,7 +64372,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -64402,7 +64402,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -64433,7 +64433,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -64463,7 +64463,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -64494,7 +64494,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -64524,7 +64524,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -64555,7 +64555,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -64585,7 +64585,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -64616,7 +64616,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -64646,7 +64646,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -64677,7 +64677,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -64707,7 +64707,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -64738,7 +64738,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -64768,7 +64768,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -64799,7 +64799,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -64829,7 +64829,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -64860,7 +64860,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -64890,7 +64890,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -64921,7 +64921,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -64951,7 +64951,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -64982,7 +64982,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -65012,7 +65012,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -65043,7 +65043,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -65073,7 +65073,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -65104,7 +65104,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -65134,7 +65134,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -65165,7 +65165,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -65195,7 +65195,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -65226,7 +65226,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -65256,7 +65256,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -65287,7 +65287,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -65317,7 +65317,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -65348,7 +65348,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -65378,7 +65378,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -65409,7 +65409,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -65439,7 +65439,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -65470,7 +65470,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -65500,7 +65500,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -65531,7 +65531,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -65561,7 +65561,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -65592,7 +65592,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -65622,7 +65622,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -65653,7 +65653,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -65683,7 +65683,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -65714,7 +65714,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -65744,7 +65744,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -65775,7 +65775,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -65809,7 +65809,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -65840,7 +65840,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -65870,7 +65870,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -65901,7 +65901,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -65931,7 +65931,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -65962,7 +65962,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -65992,7 +65992,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -66023,7 +66023,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -66053,7 +66053,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -66084,7 +66084,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -66114,7 +66114,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -66145,7 +66145,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -66175,7 +66175,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -66206,7 +66206,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -66236,7 +66236,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -66267,7 +66267,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -66297,7 +66297,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -66328,7 +66328,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -66358,7 +66358,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -66389,7 +66389,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -66419,7 +66419,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -66450,7 +66450,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -66480,7 +66480,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -66511,7 +66511,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -66541,7 +66541,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -66572,7 +66572,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -66602,7 +66602,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -66633,7 +66633,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -66663,7 +66663,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -66694,7 +66694,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -66724,7 +66724,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -66755,7 +66755,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -66785,7 +66785,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -66816,7 +66816,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -66846,7 +66846,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -66877,7 +66877,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -66907,7 +66907,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -66938,7 +66938,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -66968,7 +66968,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -66999,7 +66999,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -67029,7 +67029,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -67060,7 +67060,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -67090,7 +67090,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -67121,7 +67121,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -67151,7 +67151,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -67182,7 +67182,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -67212,7 +67212,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -67243,7 +67243,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -67273,7 +67273,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -67304,7 +67304,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -67334,7 +67334,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -67365,7 +67365,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -67395,7 +67395,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -67426,7 +67426,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -67456,7 +67456,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -67487,7 +67487,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -67517,7 +67517,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -67548,7 +67548,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -67578,7 +67578,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -67609,7 +67609,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -67639,7 +67639,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -67670,7 +67670,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -67700,7 +67700,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -67731,7 +67731,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -67761,7 +67761,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -67792,7 +67792,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -67822,7 +67822,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -67853,7 +67853,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -67883,7 +67883,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -67913,7 +67913,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -67944,7 +67944,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -67974,7 +67974,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -68005,7 +68005,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -68035,7 +68035,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -68066,7 +68066,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -68096,7 +68096,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -68127,7 +68127,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -68157,7 +68157,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -68188,7 +68188,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -68218,7 +68218,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -68249,7 +68249,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -68279,7 +68279,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -68310,7 +68310,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -68340,7 +68340,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -68371,7 +68371,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -68401,7 +68401,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -68432,7 +68432,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -68462,7 +68462,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -68493,7 +68493,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -68523,7 +68523,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -68554,7 +68554,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -68584,7 +68584,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -68615,7 +68615,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -68645,7 +68645,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -68676,7 +68676,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -68706,7 +68706,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -68737,7 +68737,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -68767,7 +68767,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -68798,7 +68798,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -68828,7 +68828,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -68859,7 +68859,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -68889,7 +68889,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -68920,7 +68920,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -68950,7 +68950,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -68981,7 +68981,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -69011,7 +69011,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -69042,7 +69042,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -69072,7 +69072,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -69103,7 +69103,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -69133,7 +69133,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -69164,7 +69164,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -69194,7 +69194,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -69225,7 +69225,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -69255,7 +69255,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -69286,7 +69286,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -69316,7 +69316,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -69347,7 +69347,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -69377,7 +69377,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -69408,7 +69408,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -69438,7 +69438,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -69469,7 +69469,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -69499,7 +69499,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -69530,7 +69530,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -69560,7 +69560,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -69591,7 +69591,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -69621,7 +69621,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -69652,7 +69652,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -69682,7 +69682,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -69713,7 +69713,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -69743,7 +69743,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -69774,7 +69774,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -69804,7 +69804,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -69835,7 +69835,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -69865,7 +69865,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -69896,7 +69896,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -69926,7 +69926,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -69957,7 +69957,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -69987,7 +69987,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -70018,7 +70018,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -70048,7 +70048,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -70079,7 +70079,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -70109,7 +70109,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -70140,7 +70140,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -70170,7 +70170,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -70201,7 +70201,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -70231,7 +70231,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -70262,7 +70262,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -70292,7 +70292,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -70323,7 +70323,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -70353,7 +70353,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -70384,7 +70384,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -70414,7 +70414,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -70445,7 +70445,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -70475,7 +70475,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -70506,7 +70506,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -70536,7 +70536,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -70567,7 +70567,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -70597,7 +70597,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -70628,7 +70628,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -70658,7 +70658,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -70689,7 +70689,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -70719,7 +70719,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -70750,7 +70750,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -70780,7 +70780,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -70811,7 +70811,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -70845,7 +70845,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -70876,7 +70876,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -70906,7 +70906,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -70937,7 +70937,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -70967,7 +70967,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -70998,7 +70998,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -71028,7 +71028,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -71059,7 +71059,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -71089,7 +71089,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -71120,7 +71120,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -71150,7 +71150,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -71181,7 +71181,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -71211,7 +71211,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -71242,7 +71242,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -71272,7 +71272,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -71303,7 +71303,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -71333,7 +71333,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -71364,7 +71364,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -71394,7 +71394,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -71425,7 +71425,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -71455,7 +71455,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -71486,7 +71486,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -71516,7 +71516,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -71547,7 +71547,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -71577,7 +71577,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -71608,7 +71608,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -71638,7 +71638,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -71669,7 +71669,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -71699,7 +71699,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -71730,7 +71730,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -71760,7 +71760,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -71791,7 +71791,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -71821,7 +71821,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -71852,7 +71852,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -71882,7 +71882,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -71913,7 +71913,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -71943,7 +71943,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -71974,7 +71974,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -72004,7 +72004,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -72035,7 +72035,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -72065,7 +72065,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -72096,7 +72096,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -72126,7 +72126,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -72157,7 +72157,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -72187,7 +72187,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -72218,7 +72218,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -72248,7 +72248,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -72279,7 +72279,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -72309,7 +72309,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -72340,7 +72340,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -72370,7 +72370,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -72401,7 +72401,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -72422,7 +72422,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -72452,7 +72452,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -72483,7 +72483,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -72513,7 +72513,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -72544,7 +72544,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -72574,7 +72574,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -72605,7 +72605,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -72635,7 +72635,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -72666,7 +72666,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -72696,7 +72696,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -72727,7 +72727,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -72757,7 +72757,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -72788,7 +72788,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -72818,7 +72818,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -72849,7 +72849,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -72879,7 +72879,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -72910,7 +72910,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -72940,7 +72940,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -72970,7 +72970,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -73001,7 +73001,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -73031,7 +73031,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -73062,7 +73062,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -73092,7 +73092,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -73123,7 +73123,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -73153,7 +73153,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -73184,7 +73184,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -73214,7 +73214,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -73245,7 +73245,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -73275,7 +73275,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -73306,7 +73306,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -73336,7 +73336,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -73367,7 +73367,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -73397,7 +73397,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -73428,7 +73428,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -73458,7 +73458,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -73489,7 +73489,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -73519,7 +73519,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -73550,7 +73550,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -73580,7 +73580,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -73611,7 +73611,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -73641,7 +73641,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -73672,7 +73672,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -73702,7 +73702,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -73733,7 +73733,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -73763,7 +73763,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -73794,7 +73794,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -73824,7 +73824,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -73855,7 +73855,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -73885,7 +73885,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -73916,7 +73916,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -73946,7 +73946,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -73977,7 +73977,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -74007,7 +74007,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -74038,7 +74038,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -74068,7 +74068,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -74099,7 +74099,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -74129,7 +74129,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -74160,7 +74160,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -74190,7 +74190,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -74221,7 +74221,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -74251,7 +74251,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -74282,7 +74282,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -74312,7 +74312,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -74343,7 +74343,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -74373,7 +74373,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -74404,7 +74404,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -74434,7 +74434,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -74465,7 +74465,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -74495,7 +74495,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -74526,7 +74526,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -74556,7 +74556,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -74587,7 +74587,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -74617,7 +74617,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -74648,7 +74648,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -74678,7 +74678,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -74709,7 +74709,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -74739,7 +74739,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -74770,7 +74770,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -74800,7 +74800,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -74831,7 +74831,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -74861,7 +74861,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -74892,7 +74892,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -74922,7 +74922,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -74953,7 +74953,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -74983,7 +74983,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -75014,7 +75014,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -75044,7 +75044,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -75075,7 +75075,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -75105,7 +75105,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -75136,7 +75136,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -75166,7 +75166,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -75197,7 +75197,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -75227,7 +75227,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -75258,7 +75258,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -75288,7 +75288,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -75319,7 +75319,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -75349,7 +75349,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -75380,7 +75380,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -75410,7 +75410,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -75441,7 +75441,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -75471,7 +75471,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -75502,7 +75502,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -75532,7 +75532,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -75563,7 +75563,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -75593,7 +75593,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -75624,7 +75624,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -75654,7 +75654,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -75685,7 +75685,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -75715,7 +75715,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -75746,7 +75746,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -75776,7 +75776,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -75807,7 +75807,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -75837,7 +75837,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -75868,7 +75868,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -75893,7 +75893,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -75923,7 +75923,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -75954,7 +75954,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -75984,7 +75984,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -76015,7 +76015,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -76045,7 +76045,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -76076,7 +76076,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -76106,7 +76106,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -76137,7 +76137,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -76167,7 +76167,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -76198,7 +76198,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -76228,7 +76228,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -76259,7 +76259,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -76289,7 +76289,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -76320,7 +76320,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -76350,7 +76350,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -76381,7 +76381,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -76411,7 +76411,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -76442,7 +76442,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -76472,7 +76472,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -76503,7 +76503,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -76533,7 +76533,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -76564,7 +76564,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -76594,7 +76594,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -76625,7 +76625,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -76655,7 +76655,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -76686,7 +76686,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -76716,7 +76716,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -76747,7 +76747,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -76777,7 +76777,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -76808,7 +76808,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -76838,7 +76838,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -76869,7 +76869,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -76899,7 +76899,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -76930,7 +76930,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -76960,7 +76960,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -76991,7 +76991,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -77021,7 +77021,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -77052,7 +77052,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -77082,7 +77082,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -77113,7 +77113,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -77143,7 +77143,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -77174,7 +77174,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -77204,7 +77204,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -77235,7 +77235,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -77256,7 +77256,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -77286,7 +77286,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -77317,7 +77317,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -77347,7 +77347,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -77378,7 +77378,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -77408,7 +77408,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -77439,7 +77439,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -77469,7 +77469,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -77500,7 +77500,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -77521,7 +77521,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -77551,7 +77551,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -77582,7 +77582,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -77612,7 +77612,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -77643,7 +77643,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -77673,7 +77673,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -77704,7 +77704,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -77734,7 +77734,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -77765,7 +77765,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -77795,7 +77795,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -77826,7 +77826,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -77856,7 +77856,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -77887,7 +77887,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -77917,7 +77917,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -77948,7 +77948,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -77978,7 +77978,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -78009,7 +78009,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -78030,7 +78030,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -78060,7 +78060,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -78090,7 +78090,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -78121,7 +78121,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -78151,7 +78151,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -78182,7 +78182,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -78212,7 +78212,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -78243,7 +78243,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -78273,7 +78273,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -78304,7 +78304,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -78334,7 +78334,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -78365,7 +78365,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -78395,7 +78395,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -78426,7 +78426,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -78456,7 +78456,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -78487,7 +78487,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -78517,7 +78517,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -78548,7 +78548,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -78578,7 +78578,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -78609,7 +78609,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -78639,7 +78639,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -78670,7 +78670,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -78700,7 +78700,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -78731,7 +78731,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -78761,7 +78761,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -78792,7 +78792,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -78822,7 +78822,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -78853,7 +78853,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -78883,7 +78883,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -78914,7 +78914,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -78944,7 +78944,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -78975,7 +78975,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -79005,7 +79005,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -79036,7 +79036,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -79066,7 +79066,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -79097,7 +79097,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -79127,7 +79127,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -79158,7 +79158,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -79188,7 +79188,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -79219,7 +79219,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -79249,7 +79249,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -79280,7 +79280,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -79310,7 +79310,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -79341,7 +79341,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -79371,7 +79371,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -79402,7 +79402,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -79432,7 +79432,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -79463,7 +79463,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -79493,7 +79493,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -79524,7 +79524,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -79554,7 +79554,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -79585,7 +79585,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -79615,7 +79615,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -79646,7 +79646,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -79676,7 +79676,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -79707,7 +79707,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -79737,7 +79737,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -79768,7 +79768,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -79798,7 +79798,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -79829,7 +79829,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -79859,7 +79859,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -79890,7 +79890,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -79920,7 +79920,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -79951,7 +79951,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -79981,7 +79981,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -80012,7 +80012,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -80042,7 +80042,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -80073,7 +80073,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -80103,7 +80103,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -80134,7 +80134,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -80164,7 +80164,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -80195,7 +80195,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -80225,7 +80225,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -80256,7 +80256,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -80286,7 +80286,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -80317,7 +80317,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -80347,7 +80347,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -80378,7 +80378,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -80408,7 +80408,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -80439,7 +80439,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -80469,7 +80469,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -80500,7 +80500,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -80530,7 +80530,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -80561,7 +80561,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -80591,7 +80591,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -80622,7 +80622,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -80652,7 +80652,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -80683,7 +80683,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -80713,7 +80713,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -80744,7 +80744,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -80774,7 +80774,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -80805,7 +80805,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -80835,7 +80835,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -80866,7 +80866,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -80896,7 +80896,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -80927,7 +80927,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -80957,7 +80957,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -80988,7 +80988,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -81013,7 +81013,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -81043,7 +81043,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -81074,7 +81074,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -81104,7 +81104,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -81135,7 +81135,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -81165,7 +81165,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -81196,7 +81196,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -81226,7 +81226,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -81257,7 +81257,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -81287,7 +81287,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -81318,7 +81318,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -81348,7 +81348,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -81379,7 +81379,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -81409,7 +81409,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -81440,7 +81440,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -81470,7 +81470,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -81501,7 +81501,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -81531,7 +81531,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -81562,7 +81562,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -81592,7 +81592,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -81623,7 +81623,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -81653,7 +81653,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -81684,7 +81684,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -81714,7 +81714,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -81745,7 +81745,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -81775,7 +81775,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -81806,7 +81806,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -81836,7 +81836,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -81867,7 +81867,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -81897,7 +81897,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -81928,7 +81928,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -81958,7 +81958,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -81989,7 +81989,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -82019,7 +82019,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -82050,7 +82050,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -82080,7 +82080,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -82111,7 +82111,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -82141,7 +82141,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -82172,7 +82172,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -82202,7 +82202,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -82233,7 +82233,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -82263,7 +82263,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -82294,7 +82294,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -82324,7 +82324,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -82355,7 +82355,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -82376,7 +82376,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -82406,7 +82406,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -82437,7 +82437,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -82467,7 +82467,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -82498,7 +82498,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -82528,7 +82528,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -82559,7 +82559,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -82589,7 +82589,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -82620,7 +82620,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -82650,7 +82650,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -82681,7 +82681,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -82711,7 +82711,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -82742,7 +82742,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -82772,7 +82772,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -82803,7 +82803,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -82833,7 +82833,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -82864,7 +82864,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -82894,7 +82894,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -82925,7 +82925,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -82955,7 +82955,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -82986,7 +82986,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -83016,7 +83016,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -83047,7 +83047,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -83077,7 +83077,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -83108,7 +83108,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -83129,7 +83129,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -83159,7 +83159,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -83189,7 +83189,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -83220,7 +83220,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -83250,7 +83250,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -83281,7 +83281,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -83311,7 +83311,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -83342,7 +83342,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -83372,7 +83372,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -83403,7 +83403,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -83433,7 +83433,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -83464,7 +83464,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -83494,7 +83494,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -83525,7 +83525,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -83555,7 +83555,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -83586,7 +83586,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -83616,7 +83616,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -83647,7 +83647,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -83677,7 +83677,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -83708,7 +83708,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -83738,7 +83738,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -83769,7 +83769,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -83799,7 +83799,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -83830,7 +83830,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -83860,7 +83860,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -83891,7 +83891,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -83921,7 +83921,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -83952,7 +83952,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -83982,7 +83982,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -84013,7 +84013,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -84043,7 +84043,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -84074,7 +84074,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -84104,7 +84104,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -84135,7 +84135,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -84165,7 +84165,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -84196,7 +84196,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -84226,7 +84226,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -84257,7 +84257,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -84287,7 +84287,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -84318,7 +84318,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -84348,7 +84348,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -84379,7 +84379,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -84409,7 +84409,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -84440,7 +84440,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -84470,7 +84470,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -84501,7 +84501,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -84531,7 +84531,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -84562,7 +84562,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -84592,7 +84592,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -84623,7 +84623,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -84653,7 +84653,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -84684,7 +84684,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -84714,7 +84714,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -84745,7 +84745,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -84775,7 +84775,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -84806,7 +84806,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -84836,7 +84836,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -84867,7 +84867,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -84897,7 +84897,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -84928,7 +84928,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -84958,7 +84958,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -84989,7 +84989,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -85019,7 +85019,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -85050,7 +85050,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -85080,7 +85080,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -85111,7 +85111,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -85141,7 +85141,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -85172,7 +85172,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -85202,7 +85202,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -85233,7 +85233,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -85263,7 +85263,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -85294,7 +85294,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -85324,7 +85324,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -85355,7 +85355,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -85385,7 +85385,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -85416,7 +85416,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -85446,7 +85446,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -85477,7 +85477,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -85507,7 +85507,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -85538,7 +85538,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -85568,7 +85568,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -85599,7 +85599,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -85629,7 +85629,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -85660,7 +85660,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -85690,7 +85690,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -85721,7 +85721,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -85751,7 +85751,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -85782,7 +85782,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -85812,7 +85812,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -85843,7 +85843,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -85873,7 +85873,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -85904,7 +85904,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -85934,7 +85934,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -85965,7 +85965,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -85995,7 +85995,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -86026,7 +86026,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -86056,7 +86056,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -86087,7 +86087,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -86112,7 +86112,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -86142,7 +86142,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -86173,7 +86173,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -86203,7 +86203,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -86234,7 +86234,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -86264,7 +86264,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -86295,7 +86295,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -86325,7 +86325,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -86356,7 +86356,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -86386,7 +86386,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -86417,7 +86417,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -86447,7 +86447,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -86478,7 +86478,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -86508,7 +86508,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -86539,7 +86539,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -86569,7 +86569,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -86600,7 +86600,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -86630,7 +86630,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -86661,7 +86661,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -86691,7 +86691,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -86722,7 +86722,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -86752,7 +86752,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -86783,7 +86783,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -86813,7 +86813,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -86844,7 +86844,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -86874,7 +86874,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -86905,7 +86905,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -86935,7 +86935,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -86966,7 +86966,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -86996,7 +86996,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -87027,7 +87027,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -87057,7 +87057,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -87088,7 +87088,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -87118,7 +87118,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -87149,7 +87149,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -87179,7 +87179,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -87210,7 +87210,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -87240,7 +87240,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -87271,7 +87271,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -87301,7 +87301,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -87332,7 +87332,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -87362,7 +87362,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -87393,7 +87393,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -87423,7 +87423,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -87454,7 +87454,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -87475,7 +87475,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -87505,7 +87505,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -87536,7 +87536,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -87566,7 +87566,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -87597,7 +87597,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -87627,7 +87627,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -87658,7 +87658,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -87688,7 +87688,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -87719,7 +87719,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -87740,7 +87740,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -87770,7 +87770,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -87801,7 +87801,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -87831,7 +87831,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -87862,7 +87862,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -87892,7 +87892,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -87923,7 +87923,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -87953,7 +87953,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -87984,7 +87984,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -88014,7 +88014,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -88045,7 +88045,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -88075,7 +88075,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -88106,7 +88106,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -88136,7 +88136,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -88167,7 +88167,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -88197,7 +88197,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -88228,7 +88228,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -88258,7 +88258,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -88288,7 +88288,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -88319,7 +88319,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -88349,7 +88349,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -88380,7 +88380,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -88410,7 +88410,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -88441,7 +88441,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -88471,7 +88471,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -88502,7 +88502,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -88532,7 +88532,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -88563,7 +88563,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -88593,7 +88593,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -88624,7 +88624,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -88654,7 +88654,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -88685,7 +88685,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -88715,7 +88715,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -88746,7 +88746,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -88776,7 +88776,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -88807,7 +88807,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -88837,7 +88837,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -88868,7 +88868,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -88898,7 +88898,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -88929,7 +88929,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -88959,7 +88959,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -88990,7 +88990,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -89020,7 +89020,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -89051,7 +89051,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -89081,7 +89081,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -89112,7 +89112,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -89142,7 +89142,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -89173,7 +89173,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -89203,7 +89203,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -89234,7 +89234,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -89264,7 +89264,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -89295,7 +89295,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -89325,7 +89325,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -89356,7 +89356,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -89386,7 +89386,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -89417,7 +89417,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -89447,7 +89447,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -89478,7 +89478,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -89508,7 +89508,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -89539,7 +89539,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -89569,7 +89569,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -89600,7 +89600,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -89630,7 +89630,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -89661,7 +89661,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -89691,7 +89691,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -89722,7 +89722,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -89752,7 +89752,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -89783,7 +89783,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -89813,7 +89813,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -89844,7 +89844,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -89874,7 +89874,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -89905,7 +89905,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -89935,7 +89935,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -89966,7 +89966,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -89996,7 +89996,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -90027,7 +90027,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -90057,7 +90057,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -90088,7 +90088,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -90118,7 +90118,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -90149,7 +90149,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -90179,7 +90179,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -90210,7 +90210,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -90240,7 +90240,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -90271,7 +90271,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -90301,7 +90301,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -90332,7 +90332,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -90362,7 +90362,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -90393,7 +90393,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -90423,7 +90423,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -90454,7 +90454,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -90484,7 +90484,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -90515,7 +90515,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -90545,7 +90545,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -90576,7 +90576,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -90606,7 +90606,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -90637,7 +90637,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -90667,7 +90667,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -90698,7 +90698,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -90728,7 +90728,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -90759,7 +90759,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -90789,7 +90789,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -90820,7 +90820,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -90850,7 +90850,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -90881,7 +90881,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -90911,7 +90911,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -90942,7 +90942,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -90972,7 +90972,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -91003,7 +91003,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -91033,7 +91033,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -91064,7 +91064,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -91094,7 +91094,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -91125,7 +91125,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -91155,7 +91155,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -91186,7 +91186,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -91220,7 +91220,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -91251,7 +91251,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -91281,7 +91281,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -91312,7 +91312,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -91342,7 +91342,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -91373,7 +91373,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -91403,7 +91403,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -91434,7 +91434,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -91464,7 +91464,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -91495,7 +91495,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -91525,7 +91525,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -91556,7 +91556,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -91586,7 +91586,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -91617,7 +91617,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -91647,7 +91647,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -91678,7 +91678,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -91708,7 +91708,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -91739,7 +91739,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -91769,7 +91769,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -91800,7 +91800,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -91830,7 +91830,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -91861,7 +91861,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -91891,7 +91891,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -91922,7 +91922,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -91952,7 +91952,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -91983,7 +91983,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -92013,7 +92013,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -92044,7 +92044,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -92074,7 +92074,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -92105,7 +92105,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -92135,7 +92135,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -92166,7 +92166,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -92196,7 +92196,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -92227,7 +92227,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -92257,7 +92257,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -92288,7 +92288,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -92318,7 +92318,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -92349,7 +92349,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -92379,7 +92379,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -92410,7 +92410,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -92440,7 +92440,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -92471,7 +92471,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -92501,7 +92501,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -92532,7 +92532,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -92553,7 +92553,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -92583,7 +92583,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -92614,7 +92614,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -92644,7 +92644,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -92675,7 +92675,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -92705,7 +92705,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -92736,7 +92736,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -92766,7 +92766,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -92797,7 +92797,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -92818,7 +92818,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -92848,7 +92848,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -92879,7 +92879,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -92909,7 +92909,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -92940,7 +92940,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -92970,7 +92970,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -93001,7 +93001,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -93031,7 +93031,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -93062,7 +93062,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -93092,7 +93092,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -93123,7 +93123,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -93153,7 +93153,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -93184,7 +93184,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -93214,7 +93214,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -93245,7 +93245,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -93275,7 +93275,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -93306,7 +93306,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -93336,7 +93336,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -93366,7 +93366,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -93397,7 +93397,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -93427,7 +93427,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -93458,7 +93458,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -93488,7 +93488,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -93519,7 +93519,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -93549,7 +93549,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -93580,7 +93580,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -93610,7 +93610,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -93641,7 +93641,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -93671,7 +93671,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -93702,7 +93702,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -93732,7 +93732,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -93763,7 +93763,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -93793,7 +93793,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -93824,7 +93824,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -93854,7 +93854,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -93885,7 +93885,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -93915,7 +93915,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -93946,7 +93946,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -93976,7 +93976,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -94007,7 +94007,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -94037,7 +94037,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -94068,7 +94068,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -94098,7 +94098,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -94129,7 +94129,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -94159,7 +94159,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -94190,7 +94190,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -94220,7 +94220,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -94251,7 +94251,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -94281,7 +94281,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -94312,7 +94312,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -94342,7 +94342,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -94373,7 +94373,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -94403,7 +94403,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -94434,7 +94434,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -94464,7 +94464,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -94495,7 +94495,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -94525,7 +94525,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -94556,7 +94556,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -94586,7 +94586,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -94617,7 +94617,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -94647,7 +94647,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -94678,7 +94678,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -94708,7 +94708,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -94739,7 +94739,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -94769,7 +94769,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -94800,7 +94800,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -94830,7 +94830,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -94861,7 +94861,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -94891,7 +94891,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -94922,7 +94922,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -94952,7 +94952,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -94983,7 +94983,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -95013,7 +95013,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -95044,7 +95044,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -95074,7 +95074,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -95105,7 +95105,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -95135,7 +95135,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -95166,7 +95166,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -95196,7 +95196,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -95227,7 +95227,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -95257,7 +95257,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -95288,7 +95288,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -95318,7 +95318,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -95349,7 +95349,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -95379,7 +95379,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -95410,7 +95410,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -95440,7 +95440,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -95471,7 +95471,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -95501,7 +95501,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -95532,7 +95532,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -95562,7 +95562,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -95593,7 +95593,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -95623,7 +95623,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -95654,7 +95654,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -95684,7 +95684,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -95715,7 +95715,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -95745,7 +95745,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -95776,7 +95776,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -95806,7 +95806,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -95837,7 +95837,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -95867,7 +95867,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -95898,7 +95898,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -95928,7 +95928,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -95959,7 +95959,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -95989,7 +95989,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -96020,7 +96020,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -96050,7 +96050,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -96081,7 +96081,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -96111,7 +96111,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -96142,7 +96142,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -96172,7 +96172,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -96203,7 +96203,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -96233,7 +96233,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -96264,7 +96264,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -96298,7 +96298,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -96329,7 +96329,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -96359,7 +96359,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -96390,7 +96390,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -96420,7 +96420,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -96451,7 +96451,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -96481,7 +96481,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -96512,7 +96512,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -96542,7 +96542,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -96573,7 +96573,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -96603,7 +96603,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -96634,7 +96634,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -96664,7 +96664,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -96695,7 +96695,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -96725,7 +96725,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -96756,7 +96756,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -96786,7 +96786,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -96817,7 +96817,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -96847,7 +96847,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -96878,7 +96878,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -96908,7 +96908,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -96939,7 +96939,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -96969,7 +96969,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -97000,7 +97000,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -97030,7 +97030,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -97061,7 +97061,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -97091,7 +97091,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -97122,7 +97122,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -97152,7 +97152,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -97183,7 +97183,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -97213,7 +97213,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -97244,7 +97244,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -97274,7 +97274,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -97305,7 +97305,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -97335,7 +97335,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -97366,7 +97366,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -97396,7 +97396,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -97427,7 +97427,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -97457,7 +97457,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -97488,7 +97488,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -97518,7 +97518,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -97549,7 +97549,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -97579,7 +97579,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -97610,7 +97610,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -97631,7 +97631,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -97661,7 +97661,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -97692,7 +97692,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -97722,7 +97722,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -97753,7 +97753,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -97783,7 +97783,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -97814,7 +97814,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -97844,7 +97844,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -97875,7 +97875,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -97905,7 +97905,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -97936,7 +97936,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -97966,7 +97966,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -97997,7 +97997,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -98027,7 +98027,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -98058,7 +98058,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -98088,7 +98088,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -98119,7 +98119,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -98149,7 +98149,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -98180,7 +98180,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -98210,7 +98210,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -98241,7 +98241,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -98271,7 +98271,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -98302,7 +98302,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -98332,7 +98332,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -98363,7 +98363,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -98384,7 +98384,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -98414,7 +98414,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -98444,7 +98444,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -98475,7 +98475,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -98505,7 +98505,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -98536,7 +98536,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -98566,7 +98566,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -98597,7 +98597,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -98627,7 +98627,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -98658,7 +98658,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -98688,7 +98688,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -98719,7 +98719,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -98749,7 +98749,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -98780,7 +98780,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -98810,7 +98810,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -98841,7 +98841,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -98871,7 +98871,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -98902,7 +98902,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -98932,7 +98932,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -98963,7 +98963,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -98993,7 +98993,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -99024,7 +99024,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -99054,7 +99054,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -99085,7 +99085,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -99115,7 +99115,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -99146,7 +99146,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -99176,7 +99176,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -99207,7 +99207,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -99237,7 +99237,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -99268,7 +99268,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -99298,7 +99298,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -99329,7 +99329,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -99359,7 +99359,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -99390,7 +99390,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -99420,7 +99420,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -99451,7 +99451,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -99481,7 +99481,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -99512,7 +99512,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -99542,7 +99542,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -99573,7 +99573,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -99603,7 +99603,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -99634,7 +99634,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -99664,7 +99664,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -99695,7 +99695,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -99725,7 +99725,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -99756,7 +99756,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -99786,7 +99786,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -99817,7 +99817,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -99847,7 +99847,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -99878,7 +99878,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -99908,7 +99908,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -99939,7 +99939,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -99969,7 +99969,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -100000,7 +100000,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -100030,7 +100030,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -100061,7 +100061,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -100091,7 +100091,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -100122,7 +100122,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -100152,7 +100152,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -100183,7 +100183,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -100213,7 +100213,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -100244,7 +100244,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -100274,7 +100274,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -100305,7 +100305,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -100335,7 +100335,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -100366,7 +100366,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -100396,7 +100396,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -100427,7 +100427,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -100457,7 +100457,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -100488,7 +100488,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -100518,7 +100518,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -100549,7 +100549,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -100579,7 +100579,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -100610,7 +100610,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -100640,7 +100640,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -100671,7 +100671,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -100701,7 +100701,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -100732,7 +100732,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -100762,7 +100762,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -100793,7 +100793,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -100823,7 +100823,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -100854,7 +100854,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -100884,7 +100884,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -100915,7 +100915,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -100945,7 +100945,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -100976,7 +100976,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -101006,7 +101006,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -101037,7 +101037,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -101067,7 +101067,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -101098,7 +101098,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -101128,7 +101128,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -101159,7 +101159,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -101189,7 +101189,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -101220,7 +101220,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -101250,7 +101250,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -101281,7 +101281,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -101311,7 +101311,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -101342,7 +101342,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -101376,7 +101376,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -101407,7 +101407,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -101437,7 +101437,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -101468,7 +101468,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -101498,7 +101498,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -101529,7 +101529,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -101559,7 +101559,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -101590,7 +101590,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -101620,7 +101620,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -101651,7 +101651,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -101681,7 +101681,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -101712,7 +101712,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -101742,7 +101742,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -101773,7 +101773,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -101803,7 +101803,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -101834,7 +101834,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -101864,7 +101864,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -101895,7 +101895,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -101925,7 +101925,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -101956,7 +101956,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -101986,7 +101986,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -102017,7 +102017,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -102047,7 +102047,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -102078,7 +102078,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -102108,7 +102108,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -102139,7 +102139,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -102169,7 +102169,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -102200,7 +102200,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -102230,7 +102230,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -102261,7 +102261,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -102291,7 +102291,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -102322,7 +102322,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -102352,7 +102352,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -102383,7 +102383,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -102413,7 +102413,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -102444,7 +102444,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -102474,7 +102474,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -102505,7 +102505,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -102535,7 +102535,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -102566,7 +102566,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -102596,7 +102596,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -102627,7 +102627,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -102657,7 +102657,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -102688,7 +102688,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -102709,7 +102709,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -102739,7 +102739,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -102770,7 +102770,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -102800,7 +102800,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -102831,7 +102831,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -102861,7 +102861,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -102892,7 +102892,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -102922,7 +102922,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -102953,7 +102953,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -102974,7 +102974,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -103004,7 +103004,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -103035,7 +103035,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -103065,7 +103065,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -103096,7 +103096,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -103126,7 +103126,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -103157,7 +103157,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -103187,7 +103187,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -103218,7 +103218,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -103248,7 +103248,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -103279,7 +103279,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -103309,7 +103309,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -103340,7 +103340,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -103370,7 +103370,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -103401,7 +103401,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -103431,7 +103431,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -103462,7 +103462,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -103483,7 +103483,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -103513,7 +103513,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -103543,7 +103543,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -103574,7 +103574,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -103604,7 +103604,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -103635,7 +103635,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -103665,7 +103665,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -103696,7 +103696,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -103726,7 +103726,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -103757,7 +103757,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -103787,7 +103787,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -103818,7 +103818,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -103848,7 +103848,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -103879,7 +103879,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -103909,7 +103909,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -103940,7 +103940,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -103970,7 +103970,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -104001,7 +104001,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -104031,7 +104031,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -104062,7 +104062,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -104092,7 +104092,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -104123,7 +104123,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -104153,7 +104153,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -104184,7 +104184,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -104214,7 +104214,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -104245,7 +104245,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -104275,7 +104275,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -104306,7 +104306,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -104336,7 +104336,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -104367,7 +104367,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -104397,7 +104397,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -104428,7 +104428,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -104458,7 +104458,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -104489,7 +104489,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -104519,7 +104519,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -104550,7 +104550,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -104580,7 +104580,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -104611,7 +104611,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -104641,7 +104641,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -104672,7 +104672,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -104702,7 +104702,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -104733,7 +104733,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -104763,7 +104763,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -104794,7 +104794,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -104824,7 +104824,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -104855,7 +104855,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -104885,7 +104885,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -104916,7 +104916,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -104946,7 +104946,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -104977,7 +104977,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -105007,7 +105007,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -105038,7 +105038,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -105068,7 +105068,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -105099,7 +105099,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -105129,7 +105129,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -105160,7 +105160,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -105190,7 +105190,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -105221,7 +105221,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -105251,7 +105251,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -105282,7 +105282,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -105312,7 +105312,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -105343,7 +105343,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -105373,7 +105373,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -105404,7 +105404,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -105434,7 +105434,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -105465,7 +105465,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -105495,7 +105495,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -105526,7 +105526,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -105556,7 +105556,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -105587,7 +105587,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -105617,7 +105617,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -105648,7 +105648,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -105678,7 +105678,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -105709,7 +105709,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -105739,7 +105739,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -105770,7 +105770,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -105800,7 +105800,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -105831,7 +105831,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -105861,7 +105861,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -105892,7 +105892,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -105922,7 +105922,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -105953,7 +105953,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -105983,7 +105983,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -106014,7 +106014,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -106044,7 +106044,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -106075,7 +106075,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -106105,7 +106105,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -106136,7 +106136,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -106166,7 +106166,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -106197,7 +106197,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -106227,7 +106227,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -106258,7 +106258,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -106288,7 +106288,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -106319,7 +106319,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -106349,7 +106349,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -106380,7 +106380,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600, @@ -106410,7 +106410,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": false, "io_timeout": 3600, @@ -106441,7 +106441,7 @@ "pool": "Chrome-perf" } ], - "expiration": 36000, + "expiration": 72000, "hard_timeout": 10800, "ignore_task_failure": true, "io_timeout": 3600,
diff --git a/testing/buildbot/filters/fuchsia.base_unittests.filter b/testing/buildbot/filters/fuchsia.base_unittests.filter index b1ac2f7..efbfe79 100644 --- a/testing/buildbot/filters/fuchsia.base_unittests.filter +++ b/testing/buildbot/filters/fuchsia.base_unittests.filter
@@ -1,8 +1,5 @@ # TODO(fuchsia): Being ported, see https://crbug.com/706592. --ActivityTrackerTest.CreateWithFileTest --ActivityTrackerTest.ProcessDeathTest --ActivityTrackerTest.ThreadDeathTest -FilePathWatcherTest.DeleteAndRecreate -FilePathWatcherTest.DeleteDuringNotify -FilePathWatcherTest.DeletedFile @@ -18,9 +15,6 @@ -FilePathWatcherTest.NonExistentDirectory -FilePathWatcherTest.RecursiveWatch -FilePathWatcherTest.WatchDirectory --FilePersistentMemoryAllocatorTest.AcceptableTest --FilePersistentMemoryAllocatorTest.CreationTest --FilePersistentMemoryAllocatorTest.ExtendTest -FileProxyTest.SetTimes -FileUtilProxyTest.Touch -FileUtilTest.FileToFILE @@ -28,15 +22,10 @@ -NativeLibraryTest.LoadLibrary -NativeLibraryTest.LoadLibraryPreferOwnSymbols -PathServiceTest.Get --PersistentHistogramAllocatorTest.CreateSpareFile --PersistentHistogramAllocatorTest.CreateWithFile --PersistentHistogramAllocatorTest.RangesDeDuplication --PersistentHistogramAllocatorTest.StatisticsRecorderMerge -PlatformThreadTest.ThreadPriorityCurrentThread -ProcessMemoryDumpTest.CountResidentBytes -ProcessMemoryDumpTest.CountResidentBytesInSharedMemory -ProcessMemoryDumpTest.TakeAllDumpsFrom --ProcessTest.Move -ProcessTest.Terminate -ProcessTest.TerminateCurrentProcessImmediatelyWithNonZeroExitCode -ProcessTest.TerminateCurrentProcessImmediatelyWithZeroExitCode @@ -48,11 +37,6 @@ -SysInfoTest.AmountOfMem -SysInfoTest.AmountOfTotalDiskSpace -TrackedObjectsTest.ReuseRetiredThreadData --VerifyPathControlledByUserTest.BadPaths --VerifyPathControlledByUserTest.GroupWriteTest --VerifyPathControlledByUserTest.OwnershipChecks --VerifyPathControlledByUserTest.Symlinks --VerifyPathControlledByUserTest.WriteBitChecks # CancelableSyncSocket tests fail: https://crbug.com/741783 -CancelableSyncSocket*
diff --git a/testing/buildbot/filters/fuchsia.media_unittests.filter b/testing/buildbot/filters/fuchsia.media_unittests.filter index 236c722..bbe7692 100644 --- a/testing/buildbot/filters/fuchsia.media_unittests.filter +++ b/testing/buildbot/filters/fuchsia.media_unittests.filter
@@ -5,6 +5,7 @@ # These tests are slow and may flake under qemu. crbug.com/745094 -Pipeline* +-MediaRemotingIntegrationTest* # These tests depend on base::CancelableSyncSocket, which is currently # broken, see https://crbug.com/741783
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 63838cdd..71a4061 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -1112,7 +1112,7 @@ ], }, "webkit_unit_tests": { - "label": "//third_party/WebKit/Source/web:webkit_unit_tests", + "label": "//third_party/WebKit/Source/controller:webkit_unit_tests", "type": "console_test_launcher", }, "webview_instrumentation_test_apk": {
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index d8bea7a..486d9f8 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -2005,51 +2005,6 @@ ] } ], - "PasswordProtectionPasswordFieldOnFocusPing": [ - { - "platforms": [ - "chromeos", - "linux", - "mac", - "win" - ], - "experiments": [ - { - "name": "SBEROnlyNoIncognito2", - "params": { - "extended_reporting": "true", - "history_sync": "false", - "incognito": "false" - }, - "enable_features": [ - "PasswordFieldOnFocusPinging" - ] - } - ] - } - ], - "PasswordProtectionProtectedPasswordEntryPing": [ - { - "platforms": [ - "chromeos", - "linux", - "mac", - "win" - ], - "experiments": [ - { - "name": "AllPopulation", - "params": { - "all_population": "true", - "incognito": "true" - }, - "enable_features": [ - "ProtectedPasswordEntryPinging" - ] - } - ] - } - ], "PasswordSeparatedSigninFlow": [ { "platforms": [ @@ -2907,6 +2862,24 @@ ] } ], + "SyncPasswordReuseEvent": [ + { + "platforms": [ + "chromeos", + "linux", + "mac", + "win" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "SyncPasswordReuseEvent" + ] + } + ] + } + ], "SyncUSSAutocomplete": [ { "platforms": [
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index ad63042..6cdac92 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -15554,7 +15554,6 @@ crbug.com/591099 svg/dom/svg-root-lengths.html [ Failure ] crbug.com/591099 svg/dom/svg2-inheritance.html [ Failure ] crbug.com/591099 svg/dom/svgangle-units.html [ Crash Timeout ] -crbug.com/591099 svg/dom/svgpath-getPathSegAtLength.html [ Failure ] crbug.com/591099 svg/dom/text-rotate-live.html [ Failure ] crbug.com/591099 svg/dom/title-in-shadow-tree.html [ Crash Failure ] crbug.com/591099 svg/dom/tooltip-title-with-use.html [ Crash Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService index 03517aa2..4b08a86 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
@@ -780,15 +780,8 @@ Bug(none) http/tests/misc/link-rel-prefetch.html [ Failure ] Bug(none) http/tests/misc/onload-detach-during-csp-frame-src-none.html [ Failure ] Bug(none) http/tests/misc/redirect-to-about-blank.html [ Timeout ] -Bug(none) http/tests/misc/resource-timing-sizes-cache-worker.html [ Failure ] -Bug(none) http/tests/misc/resource-timing-sizes-cache.html [ Failure ] -Bug(none) http/tests/misc/resource-timing-sizes-content-encoding-worker.html [ Failure ] -Bug(none) http/tests/misc/resource-timing-sizes-content-encoding.html [ Failure ] -Bug(none) http/tests/misc/resource-timing-sizes-redirect-worker.html [ Failure ] -Bug(none) http/tests/misc/resource-timing-sizes-redirect.html [ Failure ] Bug(none) http/tests/misc/resource-timing-sizes-sync-xhr-transfer-size.html [ Timeout ] Bug(none) http/tests/misc/resource-timing-sizes-tags.html [ Failure Timeout ] -Bug(none) http/tests/misc/resource-timing-sizes-xhr-fetch-worker.html [ Failure ] Bug(none) http/tests/misc/resource-timing-sizes-xhr-fetch.html [ Timeout ] Bug(none) http/tests/misc/tests-finishing-simultaneously.html [ Timeout ] Bug(none) http/tests/misc/webtiming-ssl.php [ Timeout ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index dbc5b4f..22404cef 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -92,15 +92,50 @@ crbug.com/693568 virtual/gpu/fast/canvas/canvas-imageSmoothingQuality.html [ Failure ] + # Looks like a filuare to get a paint on time. Test could be changed to use runAfterLayoutAndPaint # instead of a timeout, which may fix things. crbug.com/713049 images/color-profile-reflection.html [ Failure Pass ] crbug.com/713049 virtual/gpu-rasterization/images/color-profile-reflection.html [ Failure Pass Timeout ] crbug.com/713049 virtual/exotic-color-space/images/color-profile-reflection.html [ Failure Pass ] +# Reftest with slightly different pixels values. +# Should make a pixel test to keep coverage. +crbug.com/713891 virtual/exotic-color-space/images/animated-png.html [ Pass Failure ] + crbug.com/717389 [ Linux Debug ] virtual/gpu/fast/canvas/canvas-clip-rule.html [ Crash ] crbug.com/717389 [ Win7 Debug ] virtual/gpu/fast/canvas/canvas-clip-rule.html [ Timeout ] +# Flakily timing out or failing. +# TODO(ccameron): Investigate this. +crbug.com/730267 virtual/gpu-rasterization/images/color-profile-group.html [ Pass Timeout Failure ] +crbug.com/730267 virtual/gpu-rasterization/images/color-profile-layer.html [ Pass Timeout Failure ] +crbug.com/730267 virtual/gpu-rasterization/images/color-profile-layer-filter.html [ Pass Timeout Failure ] + +crbug.com/736052 compositing/overflow/composited-scroll-with-fractional-translation.html [ Failure ] +crbug.com/736052 virtual/prefer_compositing_to_lcd_text/compositing/overflow/composited-scroll-with-fractional-translation.html [ Failure ] + +# Awaiting rebaseline after skia roll. +crbug.com/739559 virtual/gpu-rasterization/images/color-profile-background-image-space.html [ Failure Pass ] +crbug.com/739559 virtual/gpu-rasterization/images/color-profile-mask-image-svg.html [ Failure Pass ] +crbug.com/739559 virtual/gpu-rasterization/images/color-profile-svg-fill-text.html [ Failure Pass ] +crbug.com/739559 virtual/gpu-rasterization/images/color-profile-svg.html [ Failure Pass ] +crbug.com/739559 virtual/gpu-rasterization/images/cross-fade-background-size.html [ Failure Pass ] +crbug.com/739559 virtual/gpu-rasterization/images/cross-fade-overflow-position.html [ Failure Pass ] +crbug.com/739559 virtual/gpu-rasterization/images/cross-fade-tiled.html [ Failure Pass ] + +crbug.com/746578 fast/css/transformed-mask.html [ NeedsManualRebaseline ] +crbug.com/746578 fast/reflections/reflection-masks-opacity.html [ NeedsManualRebaseline ] +crbug.com/746578 fast/reflections/reflection-masks.html [ NeedsManualRebaseline ] +crbug.com/746578 svg/filters/feImage-preserveAspectratio.svg [ NeedsManualRebaseline ] + +crbug.com/747502 paint/roundedrects/input-with-rounded-rect-and-shadow.html [ NeedsManualRebaseline ] +crbug.com/747502 fast/borders/border-radius-with-box-shadow.html [ NeedsManualRebaseline ] +crbug.com/747502 paint/roundedrects/circle-with-shadow.html [ NeedsManualRebaseline ] + +crbug.com/749760 compositing/overflow/relpos-under-abspos-border-radius.html [ Failure ] +crbug.com/749760 virtual/prefer_compositing_to_lcd_text/compositing/overflow/relpos-under-abspos-border-radius.html [ Failure ] + # ====== Paint team owned tests to here ====== #### external/wpt/css/css-position-3 @@ -987,9 +1022,6 @@ crbug.com/492664 external/wpt/css/css-writing-modes-3/clip-rect-vrl-008.xht [ Failure ] crbug.com/492664 external/wpt/css/css-writing-modes-3/line-box-direction-vrl-009.xht [ Failure ] -crbug.com/749760 compositing/overflow/relpos-under-abspos-border-radius.html [ Failure ] -crbug.com/749760 virtual/prefer_compositing_to_lcd_text/compositing/overflow/relpos-under-abspos-border-radius.html [ Failure ] - crbug.com/637255 [ Win10 ] media/video-transformed.html [ Pass Failure ] # These tests pass but images do not match because tests are stricter than the spec. @@ -1288,9 +1320,6 @@ crbug.com/658304 [ Win Linux ] fast/forms/select/input-select-after-resize.html [ Crash Timeout Pass ] -crbug.com/736052 compositing/overflow/composited-scroll-with-fractional-translation.html [ Failure ] -crbug.com/736052 virtual/prefer_compositing_to_lcd_text/compositing/overflow/composited-scroll-with-fractional-translation.html [ Failure ] - # We don't support requesting flex line breaks and it is not clear that we should. # See https://lists.w3.org/Archives/Public/www-style/2015May/0065.html crbug.com/473481 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-break-request-horiz-001a.html [ Failure ] @@ -1456,11 +1485,6 @@ crbug.com/527270 accessibility/name-calc-img.html [ Failure Pass Timeout ] -crbug.com/746578 fast/css/transformed-mask.html [ NeedsManualRebaseline ] -crbug.com/746578 fast/reflections/reflection-masks-opacity.html [ NeedsManualRebaseline ] -crbug.com/746578 fast/reflections/reflection-masks.html [ NeedsManualRebaseline ] -crbug.com/746578 svg/filters/feImage-preserveAspectratio.svg [ NeedsManualRebaseline ] - # Win7 does not support the needed DirectWrite APIs for font fallback crbug.com/459056 [ Win7 ] fast/text/font-fallback-win.html [ Failure ] @@ -1792,6 +1816,7 @@ crbug.com/626703 external/wpt/encoding/eof-utf-8-two.html [ Failure ] crbug.com/626703 external/wpt/fetch/api/abort/general.html [ Timeout ] crbug.com/626703 virtual/mojo-blobs/external/wpt/fetch/api/abort/general.html [ Timeout ] +crbug.com/626703 virtual/outofblink-cors/external/wpt/fetch/api/abort/general.html [ Timeout ] crbug.com/626703 external/wpt/page-visibility/onvisibilitychange.html [ Timeout ] crbug.com/626703 external/wpt/webrtc/RTCIceTransport.html [ Timeout ] crbug.com/626703 external/wpt/webrtc/RTCPeerConnection-setLocalDescription-answer.html [ Timeout ] @@ -2231,10 +2256,6 @@ crbug.com/435547 http/tests/cachestorage/serviceworker/ignore-search-with-credentials.html [ Skip ] crbug.com/435547 virtual/mojo-loading/http/tests/cachestorage/serviceworker/ignore-search-with-credentials.html [ Skip ] -crbug.com/747502 paint/roundedrects/input-with-rounded-rect-and-shadow.html [ NeedsManualRebaseline ] -crbug.com/747502 fast/borders/border-radius-with-box-shadow.html [ NeedsManualRebaseline ] -crbug.com/747502 paint/roundedrects/circle-with-shadow.html [ NeedsManualRebaseline ] - crbug.com/697971 [ Mac10.12 ] fast/text/flexbox-selection-nested.html [ Skip ] crbug.com/697971 [ Mac10.12 ] fast/text/flexbox-selection.html [ Skip ] crbug.com/678481 http/tests/inspector/appcache/appcache-manifest-with-non-existing-file.html [ Skip ] @@ -2306,15 +2327,6 @@ crbug.com/707359 [ Mac ] fast/css-grid-layout/grid-self-baseline-vertical-rl-04.html [ Failure ] crbug.com/707359 [ Mac ] fast/css-grid-layout/grid-self-baseline-vertical-rl-05.html [ Failure ] -# Flakily timing out or failing. -# TODO(ccameron): Investigate this. -crbug.com/730267 virtual/gpu-rasterization/images/color-profile-group.html [ Pass Timeout Failure ] -crbug.com/730267 virtual/gpu-rasterization/images/color-profile-layer.html [ Pass Timeout Failure ] -crbug.com/730267 virtual/gpu-rasterization/images/color-profile-layer-filter.html [ Pass Timeout Failure ] - -# Reftest with slightly different pixels values, can be left disabled. -crbug.com/713891 virtual/exotic-color-space/images/animated-png.html [ Pass Failure ] - # [selectors-4] crbug.com/706118 external/wpt/css/selectors4/focus-within-004.html [ Failure ] crbug.com/706118 external/wpt/css/selectors4/hover-001-manual.html [ Skip ] @@ -2596,7 +2608,6 @@ crbug.com/709227 external/wpt/offscreen-canvas/the-offscreen-canvas/size.attributes.parse.onlyspace.worker.html [ Failure ] crbug.com/709227 external/wpt/offscreen-canvas/the-offscreen-canvas/size.attributes.parse.percent.worker.html [ Failure ] crbug.com/709227 external/wpt/offscreen-canvas/the-offscreen-canvas/size.attributes.parse.trailingjunk.worker.html [ Failure ] -crbug.com/709227 external/wpt/performance-timeline/po-disconnect.any.worker.html [ Failure ] crbug.com/709227 external/wpt/user-timing/invoke_with_timing_attributes.worker.html [ Failure ] crbug.com/709227 external/wpt/websockets/closing-handshake/002.html?wss [ Failure ] crbug.com/709227 external/wpt/websockets/closing-handshake/003.html?wss [ Failure ] @@ -2652,7 +2663,6 @@ crbug.com/709227 external/wpt/websockets/unload-a-document/002.html?wss [ Failure ] crbug.com/709227 external/wpt/performance-timeline/po-callback-mutate.any.html [ Failure ] crbug.com/709227 external/wpt/performance-timeline/po-callback-mutate.any.worker.html [ Failure ] -crbug.com/709227 external/wpt/performance-timeline/po-disconnect.any.html [ Failure ] # Timeouts crbug.com/709227 external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-idb.any.worker.html [ Timeout ] @@ -2731,12 +2741,15 @@ # Importing 'fetch' tests from WPT. crbug.com/705490 external/wpt/fetch/api/basic/error-after-response.html [ Timeout Pass ] crbug.com/705490 virtual/mojo-blobs/external/wpt/fetch/api/basic/error-after-response.html [ Timeout Pass ] +crbug.com/705490 virtual/outofblink-cors/external/wpt/fetch/api/basic/error-after-response.html [ Timeout Pass ] # Non-deterministic output, as the failing subtests dump timestamps. crbug.com/705490 external/wpt/fetch/api/request/request-cache-reload.html [ Failure ] crbug.com/705490 external/wpt/fetch/api/request/request-cache-no-store.html [ Failure ] crbug.com/705490 virtual/mojo-blobs/external/wpt/fetch/api/request/request-cache-reload.html [ Failure ] crbug.com/705490 virtual/mojo-blobs/external/wpt/fetch/api/request/request-cache-no-store.html [ Failure ] +crbug.com/705490 virtual/outofblink-cors/external/wpt/fetch/api/request/request-cache-reload.html [ Failure ] +crbug.com/705490 virtual/outofblink-cors/external/wpt/fetch/api/request/request-cache-no-store.html [ Failure ] # This test has device ID strings in failure messages which change on every test run. crbug.com/679742 external/wpt/mediacapture-streams/MediaStreamTrack-getSettings.https.html [ Failure ] @@ -2897,15 +2910,6 @@ crbug.com/737959 virtual/off-main-thread-fetch/http/tests/misc/image-input-type-outlives-gc-without-crashing.html [ Failure Pass Crash ] crbug.com/737959 virtual/off-main-thread-fetch/http/tests/misc/embed-image-load-outlives-gc-without-crashing.html [ Failure Pass Crash ] -# Awaiting rebaseline after skia roll. -crbug.com/739559 virtual/gpu-rasterization/images/color-profile-background-image-space.html [ Failure Pass ] -crbug.com/739559 virtual/gpu-rasterization/images/color-profile-mask-image-svg.html [ Failure Pass ] -crbug.com/739559 virtual/gpu-rasterization/images/color-profile-svg-fill-text.html [ Failure Pass ] -crbug.com/739559 virtual/gpu-rasterization/images/color-profile-svg.html [ Failure Pass ] -crbug.com/739559 virtual/gpu-rasterization/images/cross-fade-background-size.html [ Failure Pass ] -crbug.com/739559 virtual/gpu-rasterization/images/cross-fade-overflow-position.html [ Failure Pass ] -crbug.com/739559 virtual/gpu-rasterization/images/cross-fade-tiled.html [ Failure Pass ] - # These tests are failing on Mac-10.12 when using an Intel GPU. crbug.com/736177 [ Mac10.12 ] css2.1/t1202-counter-04-b.html [ Failure Pass ] crbug.com/736177 [ Mac10.12 ] css2.1/t1202-counters-04-b.html [ Failure Pass ] @@ -2919,9 +2923,18 @@ crbug.com/736177 [ Mac10.12 ] fast/css/h1-in-section-elements.html [ Failure Pass ] crbug.com/736177 [ Mac10.12 ] fast/css/rem-calc-dynamic-scaling.html [ Failure Pass ] crbug.com/736177 [ Mac10.12 ] fast/css/rem-dynamic-scaling.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 ] fast/css/text-overflow-input.html [ Failure Pass ] crbug.com/736177 [ Mac10.12 ] fast/dom/HTMLMeterElement/meter-optimums.html [ Failure Pass ] crbug.com/736177 [ Mac10.12 ] fast/dynamic/012.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 ] fast/forms/control-restrict-line-height.html [ Failure Pass ] crbug.com/736177 [ Mac10.12 ] fast/forms/form-element-geometry.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 ] fast/forms/input-appearance-height.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 ] fast/forms/placeholder-position.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 ] fast/forms/search/search-appearance-basic.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 ] fast/forms/search/search-cancel-button-style-sharing.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 ] fast/forms/search/search-display-none-cancel-button.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 ] fast/forms/search/search-rtl.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 ] fast/forms/search/searchfield-heights.html [ Failure Pass ] crbug.com/736177 [ Mac10.12 ] fast/inline/absolute-positioned-inline-in-centred-block.html [ Failure Pass ] crbug.com/736177 [ Mac10.12 ] fast/inline/left-right-center-inline-alignment-in-ltr-and-rtl-blocks.html [ Failure Pass ] crbug.com/736177 [ Mac10.12 ] fast/lists/ordered-list-with-no-ol-tag.html [ Failure Pass ] @@ -3009,8 +3022,6 @@ crbug.com/626703 [ Win7 ] external/wpt/image-decodes/image-decode-path-changes.html [ Pass Crash ] # Sheriff failures 2017-07-20 -crbug.com/746926 [ Win Debug ] virtual/outofblink-cors/webexposed/global-interface-listing.html [ Timeout ] - crbug.com/747163 [ Linux ] imagecapture/MediaStreamTrack-applyConstraints.html [ Pass Crash ] crbug.com/747163 [ Linux ] imagecapture/MediaStreamTrack-getSettings.html [ Pass Crash ] @@ -3029,4 +3040,11 @@ # Sheriff failure 2017-08-07 crbug.com/708499 [ Win7 Mac10.11 Retina Debug ] virtual/wheelscrolllatching/fast/compositor-wheel-scroll-latching/touchpad-scroll-impl-to-main.html [ Failure Pass ] -crbug.com/752845 [ Win7 Debug ] inspector/sha1.html [ Crash ] +crbug.com/752845 [ Win ] inspector/sha1.html [ Pass Crash ] + +# Ganesh dither changes +crbug.com/753462 virtual/gpu/fast/canvas/canvas-text-alignment.html [ NeedsManualRebaseline ] +crbug.com/753462 virtual/gpu/fast/canvas/fillrect_gradient.html [ NeedsManualRebaseline ] +crbug.com/753462 virtual/gpu/fast/canvas/gradient-add-second-start-end-stop.html [ NeedsManualRebaseline ] + +crbug.com/746904 [ Win ] fast/text/ellipsis-in-relative-inline.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites index d98db35c..f566a8c5 100644 --- a/third_party/WebKit/LayoutTests/VirtualTestSuites +++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -550,8 +550,8 @@ }, { "prefix": "outofblink-cors", - "base": "webexposed", - "args": ["--enable-features=OutOfBlinkCORS"] + "base": "external/wpt/fetch", + "args": ["--enable-features=OutOfBlinkCORS,LoadingWithMojo"] }, { "prefix": "presentation",
diff --git a/third_party/WebKit/LayoutTests/accessibility/editable-root.html b/third_party/WebKit/LayoutTests/accessibility/editable-root.html new file mode 100644 index 0000000..b83338d --- /dev/null +++ b/third_party/WebKit/LayoutTests/accessibility/editable-root.html
@@ -0,0 +1,54 @@ +<!DOCTYPE html> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> + +<div id="main" role="main"> + + <input id="input" type="text" value="Line 1"> + + <div id="contenteditable-textbox" role="textbox" contenteditable="true"> + <input id="inner-input" value="Line 1"> + <textarea id="inner-textarea" rows="1" cols="40">Line 2</textarea> + </div> + + <div id="contenteditable-div" contenteditable> + <p id="paragraph1">Line 1<br> + Line 2</p> + <p id="paragraph2">Line 3</p> + </div> + +</div> + +<script> + test(function() { + var axInput = accessibilityController.accessibleElementById('input'); + assert_true(axInput.isEditableRoot); + }, 'An input element is an editable root.'); + + test(function() { + var axContentEditable = accessibilityController.accessibleElementById('contenteditable-textbox'); + assert_true(axContentEditable.isEditableRoot); + }, 'A content editable with a role of textbox is an editable root.'); + + test(function() { + var axInnerInput = accessibilityController.accessibleElementById('inner-input'); + assert_true(axInnerInput.isEditableRoot); + }, 'An input element embedded inside a content editable is an editable root.'); + + test(function() { + var axInnerTextarea = accessibilityController.accessibleElementById('inner-textarea'); + assert_true(axInnerTextarea.isEditableRoot); + }, 'A textarea embedded inside a content editable is an editable root.'); + + test(function() { + var axContentEditable = accessibilityController.accessibleElementById('contenteditable-div'); + var axParagraph1 = accessibilityController.accessibleElementById('paragraph1'); + var axParagraph2 = accessibilityController.accessibleElementById('paragraph2'); + assert_true(axContentEditable.isEditableRoot); + assert_false(axParagraph1.isEditableRoot); + assert_false(axParagraph2.isEditableRoot); + }, 'A paragraph within a content editable is not an editable root but the content editable is.'); + + if (window.testRunner) + document.getElementById("main").style.display = "none"; +</script>
diff --git a/third_party/WebKit/LayoutTests/custom-elements/spec/define-builtin-element.html b/third_party/WebKit/LayoutTests/custom-elements/spec/define-builtin-element.html index 98ab92c..fa2dc321 100644 --- a/third_party/WebKit/LayoutTests/custom-elements/spec/define-builtin-element.html +++ b/third_party/WebKit/LayoutTests/custom-elements/spec/define-builtin-element.html
@@ -62,5 +62,14 @@ assert_not_equals(new A().localName, 'defined-name', 'localName should not be defined-name'); }, 'localName set to data element interface for extends'); + +test_with_window((w) => { + class A extends w.HTMLTimeElement {} + w.customElements.define('defined-name', A, { extends: 'time' }); + assert_equals(new A().localName, 'time', + 'localName should be time element interface for extends'); + assert_not_equals(new A().localName, 'defined-name', + 'localName should not be defined-name'); +}, 'localName set to time element interface for extends'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/editing/assert_selection.html b/third_party/WebKit/LayoutTests/editing/assert_selection.html index c66e881e..9445f2ac 100644 --- a/third_party/WebKit/LayoutTests/editing/assert_selection.html +++ b/third_party/WebKit/LayoutTests/editing/assert_selection.html
@@ -170,7 +170,7 @@ '<b id="abc">^abc</b>', '<span id="mno">mno</span>', '</div>', - ].join(''), + ], {dumpAs: 'flattree'}), 'dump flat tree for shadow DOM V0'); test(() => assert_selection(
diff --git a/third_party/WebKit/LayoutTests/editing/assert_selection.js b/third_party/WebKit/LayoutTests/editing/assert_selection.js index dd110cc..dfce7ae0 100644 --- a/third_party/WebKit/LayoutTests/editing/assert_selection.js +++ b/third_party/WebKit/LayoutTests/editing/assert_selection.js
@@ -895,12 +895,12 @@ /** * @param {string} passedInputText * @param {function(!Selection)|string} - * @param {string} expectedText + * @param {string} passedExpectedText * @param {Object=} opt_options * @return {!Sample} */ function assertSelection( - passedInputText, tester, expectedText, opt_options = {}) { + passedInputText, tester, passedExpectedText, opt_options = {}) { const kDescription = 'description'; const kDumpAs = 'dumpAs'; const kRemoveSampleIfSucceeded = 'removeSampleIfSucceeded'; @@ -927,6 +927,14 @@ throw new Error('InputText must be a string or an array of strings.'); })(); + const expectedText = (() => { + if (typeof(passedExpectedText) === 'string') + return passedExpectedText; + if (Array.isArray(passedExpectedText)) + return passedExpectedText.join(""); + throw new Error('ExpectedText must be a string or an array of strings.'); + })(); + checkExpectedText(expectedText); const sample = new Sample(inputText); if (typeof(tester) === 'function') {
diff --git a/third_party/WebKit/LayoutTests/editing/selection/mouse/selectstart_modify_crash.html b/third_party/WebKit/LayoutTests/editing/selection/mouse/selectstart_modify_crash.html new file mode 100644 index 0000000..f030c3b --- /dev/null +++ b/third_party/WebKit/LayoutTests/editing/selection/mouse/selectstart_modify_crash.html
@@ -0,0 +1,32 @@ +<!doctype html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<body> +<script> +// For http://crbug.com/748570 + +document.addEventListener('selectstart', () => { + document.body.innerHTML = '<textarea></textarea>'; +}); + +promise_test(() => { + return new Promise((resolve, reject) => { + assert_not_equals(window.chrome, undefined); + assert_not_equals(window.chrome.gpuBenchmarking, undefined); + // Click body + chrome.gpuBenchmarking.pointerActionSequence( + [{ + source: 'mouse', + actions: [ + { + name: 'pointerDown', + button: 'left', + x: 0, + y: 0, + }, + ], + }], resolve) + }).then(() => assert_true(true, 'Pass if not crashed')); +}, 'selectstart to modify'); +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index 0da3080..ea475f0 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -65113,6 +65113,16 @@ {} ] ], + ".well-known/README.md": [ + [ + {} + ] + ], + ".well-known/idp-proxy/README.md": [ + [ + {} + ] + ], ".well-known/idp-proxy/mock-idp.js": [ [ {} @@ -79153,6 +79163,11 @@ {} ] ], + "css/css-transforms-2/OWNERS": [ + [ + {} + ] + ], "css/css-transforms-2/css-rotate-2d-3d-001-ref.html": [ [ {} @@ -100323,6 +100338,11 @@ {} ] ], + "images/OWNERS": [ + [ + {} + ] + ], "images/anim-gr.gif": [ [ {} @@ -174810,6 +174830,14 @@ "99b5beb84b30521fa4c4a8a061acc309ee3d0d4a", "support" ], + ".well-known/README.md": [ + "04a3fdbfc71c56c334f20d931dc7b427af2cce30", + "support" + ], + ".well-known/idp-proxy/README.md": [ + "ff5a09cfac1bf14fee4c6c057bac351e3229706a", + "support" + ], ".well-known/idp-proxy/mock-idp.js": [ "c6687ea38b936e06efda7e48c443250c289f3c62", "support" @@ -210714,6 +210742,10 @@ "786a0165a65aa3e68c887bcf83a33a074ed9c8da", "reftest" ], + "css/css-transforms-2/OWNERS": [ + "86257012c615c6580cea602a1ee2f8617dcbb336", + "support" + ], "css/css-transforms-2/backface-visibility-hidden-001.html": [ "d12cfa3b31b7f98d0ff5693bfde49247d34cb156", "reftest" @@ -229387,7 +229419,7 @@ "testharness" ], "hr-time/timeOrigin.html": [ - "b121bee0f0c59cbd5e6b9860ebad694132842fc9", + "3bb4eb8162169e582fea93a7cb1f6257325a0606", "testharness" ], "hr-time/timing-attack.html": [ @@ -245262,6 +245294,10 @@ "72ad817fc93645a5d507fb6ce7b4892d9ee903e3", "testharness" ], + "images/OWNERS": [ + "bdefdf4bd84d02d2bff2eb4f48f0d54e6155d248", + "support" + ], "images/anim-gr.gif": [ "d348de95f364f6654edc197ac5c72ebd4339f11b", "support" @@ -267011,11 +267047,11 @@ "testharness" ], "streams/piping/pipe-through-expected.txt": [ - "3c930f7edd42c8506671fdb3faf507d6d50b94ca", + "be12efb52e04d9e3c1b890a0eeb75a27a2a41d67", "support" ], "streams/piping/pipe-through.dedicatedworker-expected.txt": [ - "3c930f7edd42c8506671fdb3faf507d6d50b94ca", + "be12efb52e04d9e3c1b890a0eeb75a27a2a41d67", "support" ], "streams/piping/pipe-through.dedicatedworker.html": [ @@ -267031,7 +267067,7 @@ "support" ], "streams/piping/pipe-through.serviceworker.https-expected.txt": [ - "e149dc3f3d85f40e6405fea302772e9697188810", + "3379509d63688229b4318c0947cb25bd4abdb595", "support" ], "streams/piping/pipe-through.serviceworker.https.html": [ @@ -267039,7 +267075,7 @@ "testharness" ], "streams/piping/pipe-through.sharedworker-expected.txt": [ - "3c930f7edd42c8506671fdb3faf507d6d50b94ca", + "be12efb52e04d9e3c1b890a0eeb75a27a2a41d67", "support" ], "streams/piping/pipe-through.sharedworker.html": [ @@ -267743,7 +267779,7 @@ "support" ], "svg/OWNERS": [ - "80579a1e88af8e60c7446f34446b90bd3e9cf8c7", + "f1806810416353aa3a92927fcdc7fb407960b41e", "support" ], "svg/README.md": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/.well-known/README.md b/third_party/WebKit/LayoutTests/external/wpt/.well-known/README.md new file mode 100644 index 0000000..dde8aa2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/.well-known/README.md
@@ -0,0 +1,9 @@ +Well-Known URI Testing +====================== + +This directory is used for testing resources that are loaded based on the +well-known URI standard. [[RFC5785](https://tools.ietf.org/html/rfc5785)] + +For other kinds of resource files, they should either be placed at +[/common](../common) or the respective subdirectories for the +particular standard.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/.well-known/idp-proxy/README.md b/third_party/WebKit/LayoutTests/external/wpt/.well-known/idp-proxy/README.md new file mode 100644 index 0000000..dc5795c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/.well-known/idp-proxy/README.md
@@ -0,0 +1,12 @@ +Identity Provider Proxy +======================= + +This directory is used for hosting the mock identity provider proxy script +for testing the identity provider feature in WebRTC. +[[ietf-rtcweb-security-arch](https://tools.ietf.org/html/draft-ietf-rtcweb-security-arch-12#section-5.6.5)] +[[webrtc-pc](https://w3c.github.io/webrtc-pc/#sec.identity-proxy)] + +The script for identity provider proxy must be hosted at /.well-known/idp-proxy +instead of the usual [/webrtc](../../webrtc) directory as it follows the +well-known URI standard that derives the script URI from a given domain name. +[[RFC5785](https://tools.ietf.org/html/rfc5785)]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces-expected.txt index cfb03ed2..74040ad 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces-expected.txt
@@ -9,13 +9,13 @@ PASS BackgroundFetchManager interface: existence and properties of interface prototype object's "constructor" property PASS BackgroundFetchManager interface: operation fetch(DOMString,[object Object],[object Object],BackgroundFetchOptions) PASS BackgroundFetchManager interface: operation get(DOMString) -PASS BackgroundFetchManager interface: operation getTags() +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: attribute tag +PASS BackgroundFetchRegistration interface: attribute id PASS BackgroundFetchRegistration interface: attribute icons PASS BackgroundFetchRegistration interface: attribute totalDownloadSize PASS BackgroundFetchRegistration interface: attribute title
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces-worker.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces-worker.https-expected.txt index e378d604..ca4bf05 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces-worker.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces-worker.https-expected.txt
@@ -13,13 +13,13 @@ PASS BackgroundFetchManager interface: existence and properties of interface prototype object's "constructor" property PASS BackgroundFetchManager interface: operation fetch(DOMString,[object Object],[object Object],BackgroundFetchOptions) PASS BackgroundFetchManager interface: operation get(DOMString) -PASS BackgroundFetchManager interface: operation getTags() +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: attribute tag +PASS BackgroundFetchRegistration interface: attribute id PASS BackgroundFetchRegistration interface: attribute icons PASS BackgroundFetchRegistration interface: attribute totalDownloadSize PASS BackgroundFetchRegistration interface: attribute title @@ -44,7 +44,7 @@ PASS BackgroundFetchEvent interface object name FAIL BackgroundFetchEvent interface: existence and properties of interface prototype object Cannot read property 'has_extended_attribute' of undefined PASS BackgroundFetchEvent interface: existence and properties of interface prototype object's "constructor" property -PASS BackgroundFetchEvent interface: attribute tag +PASS BackgroundFetchEvent interface: attribute id FAIL BackgroundFetchEndEvent interface: existence and properties of interface object assert_own_property: self does not have own property "BackgroundFetchEndEvent" expected property "BackgroundFetchEndEvent" missing FAIL BackgroundFetchEndEvent interface object length assert_own_property: self does not have own property "BackgroundFetchEndEvent" expected property "BackgroundFetchEndEvent" missing FAIL BackgroundFetchEndEvent interface object name assert_own_property: self does not have own property "BackgroundFetchEndEvent" expected property "BackgroundFetchEndEvent" missing
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces.idl b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces.idl index 56edb5d6..d8b2fed 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces.idl +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces.idl
@@ -8,9 +8,9 @@ [Exposed=(Window,Worker)] interface BackgroundFetchManager { - Promise<BackgroundFetchRegistration> fetch(DOMString tag, (RequestInfo or sequence<RequestInfo>) requests, optional BackgroundFetchOptions options); - Promise<BackgroundFetchRegistration?> get(DOMString tag); - Promise<FrozenArray<DOMString>> getTags(); + Promise<BackgroundFetchRegistration> fetch(DOMString id, (RequestInfo or sequence<RequestInfo>) requests, optional BackgroundFetchOptions options); + Promise<BackgroundFetchRegistration?> get(DOMString id); + Promise<FrozenArray<DOMString>> getIds(); // TODO: in future this should become an async iterator for BackgroundFetchRegistration objects }; @@ -32,7 +32,7 @@ [Exposed=(Window,Worker)] interface BackgroundFetchRegistration { - readonly attribute DOMString tag; + readonly attribute DOMString id; readonly attribute FrozenArray<IconDefinition> icons; readonly attribute long totalDownloadSize; readonly attribute DOMString title; @@ -65,11 +65,11 @@ [Constructor(DOMString type, BackgroundFetchEventInit init), Exposed=ServiceWorker] interface BackgroundFetchEvent : ExtendableEvent { - readonly attribute DOMString tag; + readonly attribute DOMString id; }; dictionary BackgroundFetchEventInit : ExtendableEventInit { - required DOMString tag; + required DOMString id; }; // 3.4.2. BackgroundFetchEndEvent
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces.worker-expected.txt index fd4ad38a..6434ce8 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces.worker-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces.worker-expected.txt
@@ -10,13 +10,13 @@ PASS BackgroundFetchManager interface: existence and properties of interface prototype object's "constructor" property PASS BackgroundFetchManager interface: operation fetch(DOMString,[object Object],[object Object],BackgroundFetchOptions) PASS BackgroundFetchManager interface: operation get(DOMString) -PASS BackgroundFetchManager interface: operation getTags() +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: attribute tag +PASS BackgroundFetchRegistration interface: attribute id PASS BackgroundFetchRegistration interface: attribute icons PASS BackgroundFetchRegistration interface: attribute totalDownloadSize PASS BackgroundFetchRegistration interface: attribute title
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-cloneNode-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-cloneNode-expected.txt index ce39686..b7328f6 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-cloneNode-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-cloneNode-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 133 tests; 130 PASS, 3 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 133 tests; 131 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS createElement(a) PASS createElement(abbr) PASS createElement(acronym) @@ -111,7 +111,7 @@ PASS createElement(template) PASS createElement(textarea) PASS createElement(th) -FAIL createElement(time) assert_true: HTMLTimeElement is not supported expected true got false +PASS createElement(time) PASS createElement(title) PASS createElement(tr) PASS createElement(tt)
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces-expected.txt index 351d192..25a4c2c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 5193 tests; 4996 PASS, 197 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 5193 tests; 5005 PASS, 188 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Test driver PASS Document interface: attribute domain PASS Document interface: attribute referrer @@ -1030,15 +1030,15 @@ PASS HTMLDataElement must be primary interface of document.createElement("data") PASS Stringification of document.createElement("data") PASS HTMLDataElement interface: document.createElement("data") must inherit property "value" with the proper type (0) -FAIL HTMLTimeElement interface: existence and properties of interface object assert_own_property: self does not have own property "HTMLTimeElement" expected property "HTMLTimeElement" missing -FAIL HTMLTimeElement interface object length assert_own_property: self does not have own property "HTMLTimeElement" expected property "HTMLTimeElement" missing -FAIL HTMLTimeElement interface object name assert_own_property: self does not have own property "HTMLTimeElement" expected property "HTMLTimeElement" missing -FAIL HTMLTimeElement interface: existence and properties of interface prototype object assert_own_property: self does not have own property "HTMLTimeElement" expected property "HTMLTimeElement" missing -FAIL HTMLTimeElement interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "HTMLTimeElement" expected property "HTMLTimeElement" missing -FAIL HTMLTimeElement interface: attribute dateTime assert_own_property: self does not have own property "HTMLTimeElement" expected property "HTMLTimeElement" missing -FAIL HTMLTimeElement must be primary interface of document.createElement("time") assert_own_property: self does not have own property "HTMLTimeElement" expected property "HTMLTimeElement" missing -FAIL Stringification of document.createElement("time") assert_equals: class string of document.createElement("time") expected "[object HTMLTimeElement]" but got "[object HTMLUnknownElement]" -FAIL HTMLTimeElement interface: document.createElement("time") must inherit property "dateTime" with the proper type (0) assert_inherits: property "dateTime" not found in prototype chain +PASS HTMLTimeElement interface: existence and properties of interface object +PASS HTMLTimeElement interface object length +PASS HTMLTimeElement interface object name +PASS HTMLTimeElement interface: existence and properties of interface prototype object +PASS HTMLTimeElement interface: existence and properties of interface prototype object's "constructor" property +PASS HTMLTimeElement interface: attribute dateTime +PASS HTMLTimeElement must be primary interface of document.createElement("time") +PASS Stringification of document.createElement("time") +PASS HTMLTimeElement interface: document.createElement("time") must inherit property "dateTime" with the proper type (0) PASS HTMLSpanElement interface: existence and properties of interface object PASS HTMLSpanElement interface object length PASS HTMLSpanElement interface object name
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-text-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-text-expected.txt index 76ee833..cebdaf01 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-text-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-text-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 7799 tests; 7755 PASS, 44 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 7799 tests; 7787 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS a.title: 32 tests PASS a.lang: 32 tests PASS a.dir: 62 tests @@ -116,38 +116,7 @@ PASS time.hidden: 33 tests PASS time.accessKey: 32 tests PASS time.tabIndex: 24 tests -FAIL time.dateTime: typeof IDL attribute assert_equals: expected "string" but got "undefined" -FAIL time.dateTime: IDL get with DOM attribute unset assert_equals: expected (string) "" but got (undefined) undefined -FAIL time.dateTime: setAttribute() to "" assert_equals: IDL get expected (string) "" but got (undefined) undefined -FAIL time.dateTime: setAttribute() to " \0\x01\x02\x03\x04\x05\x06\x07 \b\t\n\v\f\r\x0e\x0f \x10\x11\x12\x13\x14\x15\x16\x17 \x18\x19\x1a\x1b\x1c\x1d\x1e\x1f foo " assert_equals: IDL get expected (string) " \0\x01\x02\x03\x04\x05\x06\x07 \b\t\n\v\f\r\x0e\x0f \x10\x11\x12\x13\x14\x15\x16\x17 \x18\x19\x1a\x1b\x1c\x1d\x1e\x1f foo " but got (undefined) undefined -FAIL time.dateTime: setAttribute() to undefined assert_equals: IDL get expected (string) "undefined" but got (undefined) undefined -FAIL time.dateTime: setAttribute() to 7 assert_equals: IDL get expected (string) "7" but got (undefined) undefined -FAIL time.dateTime: setAttribute() to 1.5 assert_equals: IDL get expected (string) "1.5" but got (undefined) undefined -FAIL time.dateTime: setAttribute() to true assert_equals: IDL get expected (string) "true" but got (undefined) undefined -FAIL time.dateTime: setAttribute() to false assert_equals: IDL get expected (string) "false" but got (undefined) undefined -FAIL time.dateTime: setAttribute() to object "[object Object]" assert_equals: IDL get expected (string) "[object Object]" but got (undefined) undefined -FAIL time.dateTime: setAttribute() to NaN assert_equals: IDL get expected (string) "NaN" but got (undefined) undefined -FAIL time.dateTime: setAttribute() to Infinity assert_equals: IDL get expected (string) "Infinity" but got (undefined) undefined -FAIL time.dateTime: setAttribute() to -Infinity assert_equals: IDL get expected (string) "-Infinity" but got (undefined) undefined -FAIL time.dateTime: setAttribute() to "\0" assert_equals: IDL get expected (string) "\0" but got (undefined) undefined -FAIL time.dateTime: setAttribute() to null assert_equals: IDL get expected (string) "null" but got (undefined) undefined -FAIL time.dateTime: setAttribute() to object "test-toString" assert_equals: IDL get expected (string) "test-toString" but got (undefined) undefined -FAIL time.dateTime: setAttribute() to object "test-valueOf" assert_equals: IDL get expected (string) "test-valueOf" but got (undefined) undefined -FAIL time.dateTime: IDL set to "" assert_equals: getAttribute() expected "" but got "test-valueOf" -FAIL time.dateTime: IDL set to " \0\x01\x02\x03\x04\x05\x06\x07 \b\t\n\v\f\r\x0e\x0f \x10\x11\x12\x13\x14\x15\x16\x17 \x18\x19\x1a\x1b\x1c\x1d\x1e\x1f foo " assert_equals: getAttribute() expected " \0\x01\x02\x03\x04\x05\x06\x07 \b\t\n\v\f\r\x0e\x0f \x10\x11\x12\x13\x14\x15\x16\x17 \x18\x19\x1a\x1b\x1c\x1d\x1e\x1f foo " but got "test-valueOf" -FAIL time.dateTime: IDL set to undefined assert_equals: getAttribute() expected "undefined" but got "test-valueOf" -FAIL time.dateTime: IDL set to 7 assert_equals: getAttribute() expected "7" but got "test-valueOf" -FAIL time.dateTime: IDL set to 1.5 assert_equals: getAttribute() expected "1.5" but got "test-valueOf" -FAIL time.dateTime: IDL set to true assert_equals: getAttribute() expected "true" but got "test-valueOf" -FAIL time.dateTime: IDL set to false assert_equals: getAttribute() expected "false" but got "test-valueOf" -FAIL time.dateTime: IDL set to object "[object Object]" assert_equals: getAttribute() expected "[object Object]" but got "test-valueOf" -FAIL time.dateTime: IDL set to NaN assert_equals: getAttribute() expected "NaN" but got "test-valueOf" -FAIL time.dateTime: IDL set to Infinity assert_equals: getAttribute() expected "Infinity" but got "test-valueOf" -FAIL time.dateTime: IDL set to -Infinity assert_equals: getAttribute() expected "-Infinity" but got "test-valueOf" -FAIL time.dateTime: IDL set to "\0" assert_equals: getAttribute() expected "\0" but got "test-valueOf" -FAIL time.dateTime: IDL set to null assert_equals: getAttribute() expected "null" but got "test-valueOf" -FAIL time.dateTime: IDL set to object "test-toString" assert_equals: getAttribute() expected "test-toString" but got "test-valueOf" -FAIL time.dateTime: IDL set to object "test-valueOf" assert_equals: IDL get expected (string) "test-valueOf" but got (object) object "test-valueOf" +PASS time.dateTime: 32 tests PASS code.title: 32 tests PASS code.lang: 32 tests PASS code.dir: 62 tests
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/interfaces-expected.txt index 0ffcb77..efef9f7 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/interfaces-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/interfaces-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 293 tests; 286 PASS, 7 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 293 tests; 288 PASS, 5 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Interfaces for a PASS Interfaces for A PASS Interfaces for abbr @@ -269,8 +269,8 @@ PASS Interfaces for TH PASS Interfaces for thead PASS Interfaces for THEAD -FAIL Interfaces for time assert_equals: Element time should have HTMLTimeElement as its primary interface. expected "[object HTMLTimeElement]" but got "[object HTMLUnknownElement]" -FAIL Interfaces for TIME assert_equals: Element TIME should have HTMLTimeElement as its primary interface. expected "[object HTMLTimeElement]" but got "[object HTMLUnknownElement]" +PASS Interfaces for time +PASS Interfaces for TIME PASS Interfaces for title PASS Interfaces for TITLE PASS Interfaces for tr
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/selectors/pseudo-classes/placeholder-shown-type-change.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/selectors/pseudo-classes/placeholder-shown-type-change.html new file mode 100644 index 0000000..206ae80c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/selectors/pseudo-classes/placeholder-shown-type-change.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Selector: pseudo-class :placeholder-shown input type change</title> +<link rel="author" title="Rune Lillesveen" href="mailto:rune@opera.com"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#pseudo-classes"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + span { + color: red; + } + :placeholder-shown + span { + color: green; + } +</style> +<input id="input" type="submit" placeholder="placeholder"></input> +<span id="sibling">This text should be green.</span> +<script> + test(() => { + assert_equals(getComputedStyle(sibling).color, "rgb(255, 0, 0)", + "Not matching :placeholder-shown for type=submit"); + + input.type = "text"; + assert_equals(getComputedStyle(sibling).color, "rgb(0, 128, 0)", + "Matching :placeholder-shown for type=text"); + }, "Evaluation of :placeholder-shown changes for input type change."); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/selectors/pseudo-classes/readwrite-readonly-type-change.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/selectors/pseudo-classes/readwrite-readonly-type-change.html new file mode 100644 index 0000000..90ef1d25 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/selectors/pseudo-classes/readwrite-readonly-type-change.html
@@ -0,0 +1,36 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Selector: pseudo-classes (:read-write, :read-only) input type change</title> +<link rel="author" title="Rune Lillesveen" href="mailto:rune@opera.com"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#pseudo-classes"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + span { + color: red; + background-color: pink; + } + :required + span { + color: green; + } + :not(:optional) + span { + background-color: lime; + } +</style> +<input id="hiddenInput" type="hidden" required> +<span id="sibling">This text should be green on lime background.</span> +<script> + test(() => { + assert_equals(getComputedStyle(sibling).color, "rgb(255, 0, 0)", + "Not matching :required for type=hidden"); + assert_equals(getComputedStyle(sibling).backgroundColor, "rgb(255, 192, 203)", + "Matching :optional for type=hidden"); + + hiddenInput.type = "text"; + + assert_equals(getComputedStyle(sibling).color, "rgb(0, 128, 0)", + "Matching :required for type=text"); + assert_equals(getComputedStyle(sibling).backgroundColor, "rgb(0, 255, 0)", + "Matching :not(:optional) for type=text"); + }, "Evaluation of :required and :optional changes for input type change."); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/selectors/pseudo-classes/required-optional-hidden.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/selectors/pseudo-classes/required-optional-hidden.html index 277d8ce3..fe3d6e2f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/selectors/pseudo-classes/required-optional-hidden.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/selectors/pseudo-classes/required-optional-hidden.html
@@ -32,5 +32,5 @@ "Matching :required for type=text"); assert_equals(getComputedStyle(sibling).backgroundColor, "rgb(0, 255, 0)", "Matching :not(:optional) for type=text"); - }, "Evalutaion of :required and :optional changes for input type change."); + }, "Evaluation of :required and :optional changes for input type change."); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/text-level-semantics/the-time-element/001-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/text-level-semantics/the-time-element/001-expected.txt deleted file mode 100644 index e8ac5a3..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/text-level-semantics/the-time-element/001-expected.txt +++ /dev/null
@@ -1,11 +0,0 @@ -This is a testharness.js-based test. -PASS HTML parsing should locate 4 time elements in this document -FAIL HTMLTimeElement should be exposed for prototyping assert_true: expected true got false -FAIL the time elements should be instanceof HTMLTimeElement Right-hand side of 'instanceof' is not an object -FAIL the datetime attribute should be reflected by the .dateTime property assert_equals: expected (string) "2000-02-01T03:04:05Z" but got (undefined) undefined -FAIL the dateTime IDL property should default to an empty string assert_equals: typeof test expected "string" but got "undefined" -PASS the dateTime property should be read/write -FAIL the datetime attribute should be reflected by the .dateTime property even if it is invalid assert_equals: expected (string) "go fish" but got (undefined) undefined -FAIL the datetime attribute should not reflect the textContent assert_equals: expected (string) "" but got (undefined) undefined -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-text-rendering-in-worker-expected.html b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-text-rendering-in-worker-expected.html index d33a0ae..f81de91 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-text-rendering-in-worker-expected.html +++ b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-text-rendering-in-worker-expected.html
@@ -5,18 +5,18 @@ <script> var ctx = document.getElementById("output").getContext("2d"); -ctx.font = "italic 12px arial"; +ctx.font = "italic 12px sans-serif"; ctx.fillStyle = "red"; ctx.fillText("it's", 10, 10); -ctx.font = "bold 30px arial"; +ctx.font = "bold 30px sans-serif"; ctx.fillStyle = "orange"; ctx.textAlign = "center"; ctx.fillText("SUNNY", 80, 50); ctx.textBaseline = "top"; ctx.textAlign = "left"; -ctx.font = "italic 50px times"; +ctx.font = "italic 50px serif"; var p = ctx.measureText("outside"); ctx.fillStyle = "purple";
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-text-rendering-in-worker.html b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-text-rendering-in-worker.html index 0fa9dd95..4b36625 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-text-rendering-in-worker.html +++ b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-text-rendering-in-worker.html
@@ -6,18 +6,18 @@ var ofc = new OffscreenCanvas(400, 400); var ctx = ofc.getContext("2d"); - ctx.font = "italic 12px arial"; + ctx.font = "italic 12px sans-serif"; ctx.fillStyle = "red"; ctx.fillText("it's", 10, 10); - ctx.font = "bold 30px arial"; + ctx.font = "bold 30px sans-serif"; ctx.fillStyle = "orange"; ctx.textAlign = "center"; ctx.fillText("SUNNY", 80, 50); ctx.textBaseline = "top"; ctx.textAlign = "left"; - ctx.font = "italic 50px times"; + ctx.font = "italic 50px serif"; var p = ctx.measureText("outside"); ctx.fillStyle = "purple";
diff --git a/third_party/WebKit/LayoutTests/fast/dom/non-numeric-values-numeric-parameters.html b/third_party/WebKit/LayoutTests/fast/dom/non-numeric-values-numeric-parameters.html index ed789814..aaa147bc 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/non-numeric-values-numeric-parameters.html +++ b/third_party/WebKit/LayoutTests/fast/dom/non-numeric-values-numeric-parameters.html
@@ -454,7 +454,6 @@ ../../../../WebCore/svg/SVGNumberList.idl: SVGNumber insertItemBefore(in SVGNumber item, in unsigned long index) ../../../../WebCore/svg/SVGNumberList.idl: SVGNumber replaceItem(in SVGNumber item, in unsigned long index) ../../../../WebCore/svg/SVGNumberList.idl: SVGNumber removeItem(in unsigned long index) -../../../../WebCore/svg/SVGPathElement.idl: unsigned long getPathSegAtLength(in float distance); ../../../../WebCore/svg/SVGPointList.idl: [Custom] SVGPoint getItem(in unsigned long index) ../../../../WebCore/svg/SVGPointList.idl: [Custom] SVGPoint insertItemBefore(in SVGPoint item, in unsigned long index) ../../../../WebCore/svg/SVGPointList.idl: [Custom] SVGPoint replaceItem(in SVGPoint item, in unsigned long index) @@ -497,7 +496,6 @@ ../../../../WebCore/svg/SVGNumber.idl: interface [Conditional=SVG, PODType=float] SVGNumber { ../../../../WebCore/svg/SVGPathElement.idl: float getTotalLength(); ../../../../WebCore/svg/SVGPathElement.idl: SVGPoint getPointAtLength(in float distance); -../../../../WebCore/svg/SVGPathElement.idl: unsigned long getPathSegAtLength(in float distance); ../../../../WebCore/svg/SVGSVGElement.idl: float getCurrentTime(); ../../../../WebCore/svg/SVGSVGElement.idl: void setCurrentTime(in float seconds); ../../../../WebCore/svg/SVGTextContentElement.idl: float getComputedTextLength();
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/paint-footer-crash.html b/third_party/WebKit/LayoutTests/fast/multicol/paint-footer-crash.html new file mode 100644 index 0000000..5559c38 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/multicol/paint-footer-crash.html
@@ -0,0 +1,9 @@ +<!DOCTYPE html> +<div style="columns:1;"> + <div style="display:table-footer-group; break-inside:avoid; outline-style:outset;"></div> +</div> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script> + test(() => { }, "No crash or assertion failure."); +</script>
diff --git a/third_party/WebKit/LayoutTests/html/text_level_semantics/time-rendering-expected.html b/third_party/WebKit/LayoutTests/html/text_level_semantics/time-rendering-expected.html new file mode 100644 index 0000000..fa583bf --- /dev/null +++ b/third_party/WebKit/LayoutTests/html/text_level_semantics/time-rendering-expected.html
@@ -0,0 +1,2 @@ +<!DOCTYPE html> +<p>one <span>two</span> three</p> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/html/text_level_semantics/time-rendering.html b/third_party/WebKit/LayoutTests/html/text_level_semantics/time-rendering.html new file mode 100644 index 0000000..9cfeefc --- /dev/null +++ b/third_party/WebKit/LayoutTests/html/text_level_semantics/time-rendering.html
@@ -0,0 +1,2 @@ +<!DOCTYPE html> +<p>one <time>two</time> three</p> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-click-event.https.html b/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-click-event.https.html index 91e652a..4a2bacb7 100644 --- a/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-click-event.https.html +++ b/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-click-event.https.html
@@ -9,7 +9,7 @@ <h1>BackgroundFetchClickEvent</h1> <p>This test validates that the BackgroundFetchClickEvent is exposed and can -be constructed with a tag and a valid state.</p> +be constructed with an id and a valid state.</p> <script> 'use strict';
diff --git a/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-event.https.html b/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-event.https.html index eeef8e6c..326079265 100644 --- a/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-event.https.html +++ b/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-event.https.html
@@ -9,7 +9,7 @@ <h1>BackgroundFetchEvent</h1> <p>This test validates that the BackgroundFetchEvent is exposed and can -be constructed with a tag.</p> +be constructed with an id.</p> <script> 'use strict';
diff --git a/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-fail-event.https.html b/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-fail-event.https.html index aaf8c13..f70f731 100644 --- a/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-fail-event.https.html +++ b/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-fail-event.https.html
@@ -9,7 +9,7 @@ <h1>BackgroundFetchFailEvent</h1> <p>This test validates that the BackgroundFetchFailEvent is exposed, and can be -constructed with a tag and a sequence of settled responses.</p> +constructed with an id and a sequence of settled responses.</p> <script> 'use strict';
diff --git a/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-manager-fetch.https.html b/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-manager-fetch.https.html index 40286c4a..f01b8a7 100644 --- a/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-manager-fetch.https.html +++ b/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-manager-fetch.https.html
@@ -16,13 +16,13 @@ const workerUrl = 'resources/empty-worker.js'; const scope = 'resources/scope/' + location.pathname; -const tag = 'my-background-fetch'; +const id = 'my-background-fetch'; promise_test(function(test) { return service_worker_unregister_and_register(test, workerUrl, scope) .then(registration => { assert_equals(null, registration.active); - return registration.backgroundFetch.fetch('tag', ['resources/non-existing-file.png']); + return registration.backgroundFetch.fetch('id', ['resources/non-existing-file.png']); }) .then(unreached_fulfillment(test), error => { assert_equals(error.name, 'TypeError'); @@ -37,7 +37,7 @@ registration = r; return wait_for_state(test, r.installing, 'activated'); }) - .then(() => registration.backgroundFetch.fetch(tag, null)) + .then(() => registration.backgroundFetch.fetch(id, null)) .then(() => unreached_fulfillment(test), () => true /* pass */); }, 'BackgroundFetchManager.fetch() throws when given a null request.'); @@ -49,7 +49,7 @@ registration = r; return wait_for_state(test, r.installing, 'activated'); }) - .then(() => registration.backgroundFetch.fetch(tag, [])) + .then(() => registration.backgroundFetch.fetch(id, [])) .then(() => unreached_fulfillment(test), () => true /* pass */); }, 'BackgroundFetchManager.fetch() throws when given an empty sequence.'); @@ -61,7 +61,7 @@ registration = r; return wait_for_state(test, r.installing, 'activated'); }) - .then(() => registration.backgroundFetch.fetch(tag, ['resources/non-existing-file.png', null])) + .then(() => registration.backgroundFetch.fetch(id, ['resources/non-existing-file.png', null])) .then(() => unreached_fulfillment(test), () => true /* pass */); }, 'BackgroundFetchManager.fetch() throws when given a sequence with a null request.'); @@ -91,10 +91,10 @@ registration = r; return wait_for_state(test, r.installing, 'activated'); }) - .then(() => registration.backgroundFetch.fetch(tag, ['resources/non-existing-file.png'], options)) + .then(() => registration.backgroundFetch.fetch(id, ['resources/non-existing-file.png'], options)) .then(backgroundFetchRegistration => { assert_true(backgroundFetchRegistration instanceof BackgroundFetchRegistration); - assert_equals(backgroundFetchRegistration.tag, tag); + assert_equals(backgroundFetchRegistration.id, id); assert_object_equals(backgroundFetchRegistration.icons, options.icons); assert_equals(backgroundFetchRegistration.totalDownloadSize, options.totalDownloadSize); assert_equals(backgroundFetchRegistration.title, options.title);
diff --git a/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-manager-get.https.html b/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-manager-get.https.html index fcdd961b..73eff2a 100644 --- a/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-manager-get.https.html +++ b/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-manager-get.https.html
@@ -20,7 +20,7 @@ return service_worker_unregister_and_register(test, workerUrl, scope) .then(registration => { assert_equals(null, registration.active); - return registration.backgroundFetch.get('tag'); + return registration.backgroundFetch.get('id'); }) .then(unreached_fulfillment(test), error => { assert_equals(error.name, 'TypeError'); @@ -36,7 +36,7 @@ registration = r; return wait_for_state(test, r.installing, 'activated'); }) - .then(() => registration.backgroundFetch.get('invalid-fetch-tag')) + .then(() => registration.backgroundFetch.get('invalid-fetch-id')) .then(backgroundFetchRegistration => { assert_equals(backgroundFetchRegistration, null); }); @@ -44,7 +44,7 @@ }, 'BackgroundFetchManager.get() returns NULL for non-existing fetches.'); promise_test(function(test) { - const tag = 'my-tag'; + const id = 'my-id'; const options = { icons: [ { @@ -69,14 +69,14 @@ registration = r; return wait_for_state(test, r.installing, 'activated'); }) - .then(() => registration.backgroundFetch.fetch(tag, ['resources/non-existing-file.png'], options)) + .then(() => registration.backgroundFetch.fetch(id, ['resources/non-existing-file.png'], options)) .then(backgroundFetchRegistration => { assert_true(backgroundFetchRegistration instanceof BackgroundFetchRegistration); - return registration.backgroundFetch.get(tag) + return registration.backgroundFetch.get(id) .then(secondBackgroundFetchRegistration => { assert_true(secondBackgroundFetchRegistration instanceof BackgroundFetchRegistration); - assert_equals(secondBackgroundFetchRegistration.tag, tag); + assert_equals(secondBackgroundFetchRegistration.id, id); assert_object_equals(secondBackgroundFetchRegistration.icons, options.icons); assert_equals(secondBackgroundFetchRegistration.totalDownloadSize, options.totalDownloadSize); assert_equals(secondBackgroundFetchRegistration.title, options.title); @@ -85,7 +85,7 @@ }, 'BackgroundFetchManager.get() can return created fetches.'); promise_test(function(test) { - const tag = 'my-tag'; + const id = 'my-id'; let registration = null; @@ -94,16 +94,16 @@ registration = r; return wait_for_state(test, r.installing, 'activated'); }) - .then(() => registration.backgroundFetch.fetch(tag, ['resources/non-existing-file.png'])) + .then(() => registration.backgroundFetch.fetch(id, ['resources/non-existing-file.png'])) .then(backgroundFetchRegistration => { assert_true(backgroundFetchRegistration instanceof BackgroundFetchRegistration); - return registration.backgroundFetch.get(tag); + return registration.backgroundFetch.get(id); }) .then(secondBackgroundFetchRegistration => { assert_true(secondBackgroundFetchRegistration instanceof BackgroundFetchRegistration); return secondBackgroundFetchRegistration.abort(); }) - .then(() => registration.backgroundFetch.get(tag)) + .then(() => registration.backgroundFetch.get(id)) .then(thirdBackgroundFetchRegistration => { assert_equals(thirdBackgroundFetchRegistration, null); });
diff --git a/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-manager-getTags.https.html b/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-manager-getTags.https.html index 381d68d..49900d5 100644 --- a/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-manager-getTags.https.html +++ b/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-manager-getTags.https.html
@@ -1,12 +1,12 @@ <!doctype html> <meta charset="utf-8"> -<title>Background Fetch API: getTags() tests</title> +<title>Background Fetch API: getIds() tests</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/serviceworker/resources/test-helpers.js"></script> -<h1>BackgroundFetchManager.getTags()</h1> -<p>This test validates the behaviour of the getTags() method.</p> +<h1>BackgroundFetchManager.getIds()</h1> +<p>This test validates the behaviour of the getIds() method.</p> <!-- TODO(peter): Move this to the WPT directory when it's merged. --> @@ -20,13 +20,13 @@ return service_worker_unregister_and_register(test, workerUrl, scope) .then(registration => { assert_equals(null, registration.active); - return registration.backgroundFetch.getTags(); + return registration.backgroundFetch.getIds(); }) .then(unreached_fulfillment(test), error => { assert_equals(error.name, 'TypeError'); }); -}, 'BackgroundFetchManager.getTags() requires an activated Service Worker.'); +}, 'BackgroundFetchManager.getIds() requires an activated Service Worker.'); promise_test(function(test) { let registration = null; @@ -36,16 +36,16 @@ registration = r; return wait_for_state(test, r.installing, 'activated'); }) - .then(() => registration.backgroundFetch.getTags()) - .then(tags => { - assert_true(Array.isArray(tags)); - assert_equals(tags.length, 0); + .then(() => registration.backgroundFetch.getIds()) + .then(ids => { + assert_true(Array.isArray(ids)); + assert_equals(ids.length, 0); }); -}, 'BackgroundFetchManager.getTags() returns an empty sequence by default.'); +}, 'BackgroundFetchManager.getIds() returns an empty sequence by default.'); promise_test(function(test) { - const tags = ['first-tag', 'second-tag', 'third-tag']; + const ids = ['first-id', 'second-id', 'third-id']; let registration = null; @@ -56,13 +56,13 @@ }) .then(() => { return Promise.all( - tags.map(tag => registration.backgroundFetch.fetch(tag, ['resources/non-existing-file.png']))); + ids.map(id => registration.backgroundFetch.fetch(id, ['resources/non-existing-file.png']))); }) - .then(() => registration.backgroundFetch.getTags()) - .then(receivedTags => { - assert_array_equals(receivedTags, tags); + .then(() => registration.backgroundFetch.getIds()) + .then(receivedIds => { + assert_array_equals(receivedIds, ids); }); -}, 'BackgroundFetchManager.getTags() returns a sequence of active fetches.'); +}, 'BackgroundFetchManager.getIds() returns a sequence of active fetches.'); </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-registration-abort.https.html b/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-registration-abort.https.html index ecfcee3c..220fa8ff 100644 --- a/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-registration-abort.https.html +++ b/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetch-registration-abort.https.html
@@ -18,7 +18,7 @@ const scope = 'resources/scope/' + location.pathname; promise_test(function(test) { - const tag = 'my-background-fetch'; + const id = 'my-background-fetch'; let registration = null; let backgroundFetchRegistration = null; @@ -28,7 +28,7 @@ registration = r; return wait_for_state(test, r.installing, 'activated'); }) - .then(() => registration.backgroundFetch.fetch(tag, ['resources/non-existing-file.png'])) + .then(() => registration.backgroundFetch.fetch(id, ['resources/non-existing-file.png'])) .then(r => { backgroundFetchRegistration = r;
diff --git a/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetched-event.https.html b/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetched-event.https.html index 50300de..82cb092 100644 --- a/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetched-event.https.html +++ b/third_party/WebKit/LayoutTests/http/tests/background_fetch/background-fetched-event.https.html
@@ -10,7 +10,7 @@ <h1>BackgroundFetchedEvent</h1> <p>This test validates that the BackgroundFetchedEvent is exposed, and can be -constructed with a tag and a sequence of settled responses.</p> +constructed with an id and a sequence of settled responses.</p> <script> 'use strict';
diff --git a/third_party/WebKit/LayoutTests/http/tests/background_fetch/resources/background-fetch-click-event-worker.js b/third_party/WebKit/LayoutTests/http/tests/background_fetch/resources/background-fetch-click-event-worker.js index 1103782a..a5032d5 100644 --- a/third_party/WebKit/LayoutTests/http/tests/background_fetch/resources/background-fetch-click-event-worker.js +++ b/third_party/WebKit/LayoutTests/http/tests/background_fetch/resources/background-fetch-click-event-worker.js
@@ -5,25 +5,25 @@ test(function() { assert_own_property(self, 'BackgroundFetchClickEvent'); - // The `tag` and `state` are required in the BackgroundFetchClickEventInit. + // The `id` and `state` are required in the BackgroundFetchClickEventInit. assert_throws(null, () => new BackgroundFetchClickEvent('BackgroundFetchClickEvent')); assert_throws(null, () => new BackgroundFetchClickEvent('BackgroundFetchClickEvent', {})); - assert_throws(null, () => new BackgroundFetchClickEvent('BackgroundFetchClickEvent', { tag: 'foo' })); - assert_throws(null, () => new BackgroundFetchClickEvent('BackgroundFetchClickEvent', { tag: 'foo', state: 'foo' })); + assert_throws(null, () => new BackgroundFetchClickEvent('BackgroundFetchClickEvent', { id: 'foo' })); + assert_throws(null, () => new BackgroundFetchClickEvent('BackgroundFetchClickEvent', { id: 'foo', state: 'foo' })); // The `state` must be one of { pending, succeeded, failed }. This should not throw. for (let state of ['pending', 'succeeded', 'failed']) - new BackgroundFetchClickEvent('BackgroundFetchClickEvent', { tag: 'foo', state }); + new BackgroundFetchClickEvent('BackgroundFetchClickEvent', { id: 'foo', state }); const event = new BackgroundFetchClickEvent('BackgroundFetchClickEvent', { - tag: 'my-tag', + id: 'my-id', state: 'succeeded' }); assert_equals(event.type, 'BackgroundFetchClickEvent'); assert_equals(event.cancelable, false); assert_equals(event.bubbles, false); - assert_equals(event.tag, 'my-tag'); + assert_equals(event.id, 'my-id'); assert_equals(event.state, 'succeeded'); assert_inherits(event, 'waitUntil');
diff --git a/third_party/WebKit/LayoutTests/http/tests/background_fetch/resources/background-fetch-event-worker.js b/third_party/WebKit/LayoutTests/http/tests/background_fetch/resources/background-fetch-event-worker.js index 6f90ebd7..5a83f469 100644 --- a/third_party/WebKit/LayoutTests/http/tests/background_fetch/resources/background-fetch-event-worker.js +++ b/third_party/WebKit/LayoutTests/http/tests/background_fetch/resources/background-fetch-event-worker.js
@@ -5,18 +5,18 @@ test(function() { assert_own_property(self, 'BackgroundFetchEvent'); - // The `tag` is required in the BackgroundFetchEventInit. + // The `id` is required in the BackgroundFetchEventInit. assert_throws(null, () => new BackgroundFetchEvent('BackgroundFetchEvent')); assert_throws(null, () => new BackgroundFetchEvent('BackgroundFetchEvent', {})); const event = new BackgroundFetchEvent('BackgroundFetchEvent', { - tag: 'my-tag' + id: 'my-id' }); assert_equals(event.type, 'BackgroundFetchEvent'); assert_equals(event.cancelable, false); assert_equals(event.bubbles, false); - assert_equals(event.tag, 'my-tag'); + assert_equals(event.id, 'my-id'); assert_inherits(event, 'waitUntil');
diff --git a/third_party/WebKit/LayoutTests/http/tests/background_fetch/resources/background-fetch-fail-event-worker.js b/third_party/WebKit/LayoutTests/http/tests/background_fetch/resources/background-fetch-fail-event-worker.js index e824692..069731d 100644 --- a/third_party/WebKit/LayoutTests/http/tests/background_fetch/resources/background-fetch-fail-event-worker.js +++ b/third_party/WebKit/LayoutTests/http/tests/background_fetch/resources/background-fetch-fail-event-worker.js
@@ -5,13 +5,13 @@ test(function() { assert_own_property(self, 'BackgroundFetchFailEvent'); - // The `tag` and `fetches` are required options in the + // The `id` and `fetches` are required options in the // BackgroundFetchFailEventInit. The latter must be a sequence of // BackgroundFetchSettledFetch instances. assert_throws(null, () => new BackgroundFetchFailEvent('BackgroundFetchFailEvent')); assert_throws(null, () => new BackgroundFetchFailEvent('BackgroundFetchFailEvent', {})); - assert_throws(null, () => new BackgroundFetchFailEvent('BackgroundFetchFailEvent', { tag: 'foo' })); - assert_throws(null, () => new BackgroundFetchFailEvent('BackgroundFetchFailEvent', { tag: 'foo', fetches: 'bar' })); + assert_throws(null, () => new BackgroundFetchFailEvent('BackgroundFetchFailEvent', { id: 'foo' })); + assert_throws(null, () => new BackgroundFetchFailEvent('BackgroundFetchFailEvent', { id: 'foo', fetches: 'bar' })); const fetches = [ new BackgroundFetchSettledFetch(new Request('non-existing-image.png'), new Response()), @@ -19,14 +19,14 @@ ]; const event = new BackgroundFetchFailEvent('BackgroundFetchFailEvent', { - tag: 'my-tag', + id: 'my-id', fetches }); assert_equals(event.type, 'BackgroundFetchFailEvent'); assert_equals(event.cancelable, false); assert_equals(event.bubbles, false); - assert_equals(event.tag, 'my-tag'); + assert_equals(event.id, 'my-id'); assert_true(Array.isArray(event.fetches)); assert_array_equals(event.fetches, fetches);
diff --git a/third_party/WebKit/LayoutTests/http/tests/background_fetch/resources/background-fetched-event-worker.js b/third_party/WebKit/LayoutTests/http/tests/background_fetch/resources/background-fetched-event-worker.js index 7a5eb3a..03c2165 100644 --- a/third_party/WebKit/LayoutTests/http/tests/background_fetch/resources/background-fetched-event-worker.js +++ b/third_party/WebKit/LayoutTests/http/tests/background_fetch/resources/background-fetched-event-worker.js
@@ -5,13 +5,13 @@ test(function() { assert_own_property(self, 'BackgroundFetchedEvent'); - // The `tag` and `fetches` are required options in the + // The `id` and `fetches` are required options in the // BackgroundFetchedEventInit. The latter must be a sequence of // BackgroundFetchSettledFetch instances. assert_throws(null, () => new BackgroundFetchedEvent('BackgroundFetchedEvent')); assert_throws(null, () => new BackgroundFetchedEvent('BackgroundFetchedEvent', {})); - assert_throws(null, () => new BackgroundFetchedEvent('BackgroundFetchedEvent', { tag: 'foo' })); - assert_throws(null, () => new BackgroundFetchedEvent('BackgroundFetchedEvent', { tag: 'foo', fetches: 'bar' })); + assert_throws(null, () => new BackgroundFetchedEvent('BackgroundFetchedEvent', { id: 'foo' })); + assert_throws(null, () => new BackgroundFetchedEvent('BackgroundFetchedEvent', { id: 'foo', fetches: 'bar' })); const fetches = [ new BackgroundFetchSettledFetch(new Request('non-existing-image.png'), new Response()), @@ -19,14 +19,14 @@ ]; const event = new BackgroundFetchedEvent('BackgroundFetchedEvent', { - tag: 'my-tag', + id: 'my-id', fetches }); assert_equals(event.type, 'BackgroundFetchedEvent'); assert_equals(event.cancelable, false); assert_equals(event.bubbles, false); - assert_equals(event.tag, 'my-tag'); + assert_equals(event.id, 'my-id'); assert_true(Array.isArray(event.fetches)); assert_array_equals(event.fetches, fetches);
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/resource-har-conversion-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/resource-har-conversion-expected.txt index 0338503..50ee8198 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/resource-har-conversion-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/resource-har-conversion-expected.txt
@@ -219,7 +219,7 @@ status : 200 statusText : "OK" } - serverIPAddress : "" + serverIPAddress : "127.0.0.1" startedDateTime : <plausible> time : <number> timings : <object>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/form-action-leak-path-on-redirect-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/form-action-leak-path-on-redirect-expected.txt index 6c3b169..4dce236 100644 --- a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/form-action-leak-path-on-redirect-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/form-action-leak-path-on-redirect-expected.txt
@@ -7,6 +7,7 @@ HTTP_CACHE_CONTROL = max-age=0 HTTP_CONNECTION = keep-alive HTTP_HOST = 127.0.0.1:8000 +HTTP_ORIGIN = http://127.0.0.1:8000 HTTP_REFERER = http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-leak-path-on-redirect.html HTTP_UPGRADE_INSECURE_REQUESTS = 1
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-allowed-with-redirect-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-allowed-with-redirect-expected.txt index ada4c163..6e56cbd 100644 --- a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-allowed-with-redirect-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-allowed-with-redirect-expected.txt
@@ -7,6 +7,7 @@ HTTP_CACHE_CONTROL = max-age=0 HTTP_CONNECTION = keep-alive HTTP_HOST = 127.0.0.1:8000 +HTTP_ORIGIN = http://127.0.0.1:8000 HTTP_REFERER = http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-allowed-with-redirect.html HTTP_UPGRADE_INSECURE_REQUESTS = 1
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-default-ignored-with-redirect-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-default-ignored-with-redirect-expected.txt index 8fff341..0103e8b 100644 --- a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-default-ignored-with-redirect-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-default-ignored-with-redirect-expected.txt
@@ -7,6 +7,7 @@ HTTP_CACHE_CONTROL = max-age=0 HTTP_CONNECTION = keep-alive HTTP_HOST = 127.0.0.1:8000 +HTTP_ORIGIN = http://127.0.0.1:8000 HTTP_REFERER = http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-default-ignored-with-redirect.html HTTP_UPGRADE_INSECURE_REQUESTS = 1
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-allowed-with-redirect-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-allowed-with-redirect-expected.txt index bd4a1e0..e43ebdf 100644 --- a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-allowed-with-redirect-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-allowed-with-redirect-expected.txt
@@ -7,6 +7,7 @@ HTTP_CACHE_CONTROL = max-age=0 HTTP_CONNECTION = keep-alive HTTP_HOST = 127.0.0.1:8000 +HTTP_ORIGIN = http://127.0.0.1:8000 HTTP_REFERER = http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-get-allowed-with-redirect.html HTTP_UPGRADE_INSECURE_REQUESTS = 1
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 42dbc399e..01d4bc5 100644 --- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -9,7 +9,7 @@ method constructor interface BackgroundFetchEvent : ExtendableEvent attribute @@toStringTag - getter tag + getter id method constructor interface BackgroundFetchFailEvent : BackgroundFetchEvent attribute @@toStringTag @@ -24,11 +24,11 @@ method constructor method fetch method get - method getTags + method getIds interface BackgroundFetchRegistration attribute @@toStringTag getter icons - getter tag + getter id getter title getter totalDownloadSize method abort
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/css/css-get-background-colors-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/css/css-get-background-colors-expected.txt index ae710ed..1da7010 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/css/css-get-background-colors-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/css/css-get-background-colors-expected.txt
@@ -6,101 +6,101 @@ Running test: testNoBgColor No background color: should be white -{"backgroundColors":["rgb(255, 255, 255)"]} +{"backgroundColors":["rgb(255, 255, 255)"],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testOpaqueBgColor Opaque background color: should be red -{"backgroundColors":["rgb(255, 0, 0)"]} +{"backgroundColors":["rgb(255, 0, 0)"],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testLayeredOpaqueBgColors Opaque background color in front of another opaque background color: should be blue -{"backgroundColors":["rgb(0, 0, 255)"]} +{"backgroundColors":["rgb(0, 0, 255)"],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testOneSemitransparentBgColor Semi-transparent background color: should be light red -{"backgroundColors":["rgb(255, 127, 127)"]} +{"backgroundColors":["rgb(255, 127, 127)"],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testTwoSemitransparentBgColors Two layered semi-transparent background colors: should be medium red -{"backgroundColors":["rgb(255, 63, 63)"]} +{"backgroundColors":["rgb(255, 63, 63)"],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testOpaqueGradientBackground Opaque gradient: should be red and black -{"backgroundColors":["rgb(255, 0, 0)","rgb(0, 0, 0)"]} +{"backgroundColors":["rgb(255, 0, 0)","rgb(0, 0, 0)"],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testOpaqueGradientBackgroundBehindScrim Opaque gradient behind semi-transparent color: should be light red and 50% grey -{"backgroundColors":["rgb(255, 128, 128)","rgb(128, 128, 128)"]} +{"backgroundColors":["rgb(255, 128, 128)","rgb(128, 128, 128)"],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testOpaqueGradientBackgroundWithColorBackground Opaque gradient and solid color background on same element: should be red and black -{"backgroundColors":["rgb(255, 0, 0)","rgb(0, 0, 0)"]} +{"backgroundColors":["rgb(255, 0, 0)","rgb(0, 0, 0)"],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testPartiallyTransparentGradientBackground Semi-transparent gradient: should be light red and 50% grey -{"backgroundColors":["rgb(255, 127, 127)","rgb(127, 127, 127)"]} +{"backgroundColors":["rgb(255, 127, 127)","rgb(127, 127, 127)"],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testPartiallyTransparentGradientAndColorBackground Semi-transparent gradient and solid color on same element: should be dark red and 50% grey -{"backgroundColors":["rgb(128, 0, 0)","rgb(128, 128, 128)"]} +{"backgroundColors":["rgb(128, 0, 0)","rgb(128, 128, 128)"],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testTwoPartiallyTransparentGradientBackgrounds Layered semi-transparent gradients: should be empty array -{"backgroundColors":[]} +{"backgroundColors":[],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testPartiallyOverlappingBackground Partially overlapping background: should be empty array -{"backgroundColors":[]} +{"backgroundColors":[],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: smallerBackground Background smaller than text: should be empty array -{"backgroundColors":[]} +{"backgroundColors":[],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testObscuredPartiallyOverlappingBackground Red background obscuring partially overlapping blue background: should be red only -{"backgroundColors":["rgb(255, 0, 0)"]} +{"backgroundColors":["rgb(255, 0, 0)"],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testBackgroundImage Background image: should be empty array -{"backgroundColors":[]} +{"backgroundColors":[],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testBackgroundImageAndBgColor Background image with background color: should be empty array -{"backgroundColors":[]} +{"backgroundColors":[],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testBackgroundImageBehindScrim Background image behind scrim: should be semi-transparent white -{"backgroundColors":["rgba(255, 255, 255, 0.5)"]} +{"backgroundColors":["rgba(255, 255, 255, 0.5)"],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testForegroundImage Image behind text: should be empty array -{"backgroundColors":[]} +{"backgroundColors":[],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testForegroundImageBehindScrim Image behind scrim: should be semi-transparent white -{"backgroundColors":["rgba(255, 255, 255, 0.5)"]} +{"backgroundColors":["rgba(255, 255, 255, 0.5)"],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testForegroundCanvas Canvas behind text: should be empty array -{"backgroundColors":[]} +{"backgroundColors":[],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testForegroundEmbed Embed behind text: should be empty array -{"backgroundColors":[]} +{"backgroundColors":[],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testForegroundObject Object behind text: should be empty array -{"backgroundColors":[]} +{"backgroundColors":[],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testForegroundPicture Picture behind text: should be empty array -{"backgroundColors":[]} +{"backgroundColors":[],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testForegroundSVG SVG behind text: should be empty array -{"backgroundColors":[]} +{"backgroundColors":[],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"} Running test: testForegroundVideo Video behind text: should be empty array -{"backgroundColors":[]} +{"backgroundColors":[],"computedFontSize":"16px","computedFontWeight":"400","computedBodyFontSize":"16px"}
diff --git a/third_party/WebKit/LayoutTests/media/remoteplayback/prompt-twice-throws.html b/third_party/WebKit/LayoutTests/media/remoteplayback/prompt-twice-throws.html index 5712a66..1f363b9 100644 --- a/third_party/WebKit/LayoutTests/media/remoteplayback/prompt-twice-throws.html +++ b/third_party/WebKit/LayoutTests/media/remoteplayback/prompt-twice-throws.html
@@ -36,18 +36,17 @@ btn.onclick = function() { internals.mediaPlayerRemoteRouteAvailabilityChanged(v, true); - v.remote.prompt(); + v.remote.prompt().then( + test.step_func(function() {}), + test.step_func(function() {})); - btn.onclick = function() { - v.remote.prompt().then( - test.unreached_func(), - test.step_func_done(function(e) { - assert_equals(e.name, 'OperationError'); - assert_equals(e.message, 'A prompt is already being shown for this media element.'); - })); - btn.onclick = null; - }; - clickOnElem(btn); + v.remote.prompt().then( + test.unreached_func(), + test.step_func_done(function(e) { + assert_equals(e.name, 'OperationError'); + assert_equals(e.message, 'A prompt is already being shown for this media element.'); + })); + btn.onclick = null; } clickOnElem(btn);
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt index 42d9055..5bd6643 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -3038,6 +3038,11 @@ setter selectionStart setter value setter wrap +interface HTMLTimeElement : HTMLElement + attribute @@toStringTag + getter dateTime + method constructor + setter dateTime interface HTMLTitleElement : HTMLElement attribute @@toStringTag getter text @@ -5351,7 +5356,6 @@ interface SVGPathElement : SVGGeometryElement attribute @@toStringTag method constructor - method getPathSegAtLength interface SVGPatternElement : SVGElement attribute @@toStringTag getter height
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.txt deleted file mode 100644 index 44eb3b02..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.txt +++ /dev/null
@@ -1,42 +0,0 @@ - -Color Actual Expected dE --------------------------------------------- -Dark Skin 114,80,64 115,80,64 1 -Light Skin 195,150,130 195,151,130 1 -Blue Sky 94,123,156 94,123,156 0 -Foliage 88,108,65 88,108,65 0 -Blue Flower 130,129,177 130,129,177 0 -Bluish Green 100,190,171 100,190,171 0 --------------------------------------------- -Orange 217,121,37 217,122,37 1 -Purplish Blue 72,90,166 72,91,165 1 -Moderate Red 194,84,97 194,84,98 1 -Purple 90,60,106 91,59,107 2 -Yellow Green 160,188,60 160,188,60 0 -Orange Yellow 231,163,42 230,163,42 1 --------------------------------------------- -Blue 47,60,153 46,60,153 1 -Green 70,149,69 71,150,69 1 -Red 177,45,56 177,44,56 1 -Yellow 239,200,27 238,200,27 1 -Magenta 187,82,147 187,82,148 1 -Cyan (*) 0,135,166 0,135,166 0 --------------------------------------------- -White 243,242,236 243,242,237 1 -Neutral 8 202,202,200 201,201,201 2 -Neutral 6.5 160,161,160 161,161,161 1 -Neutral 5 123,121,120 122,122,121 2 -Neutral 3.5 83,83,83 83,83,83 0 -Black 50,50,50 50,49,50 1 --------------------------------------------- - -Result: total RMS color error: 1.04 - * Munsell Cyan is outside 255 sRGB gamut - - - - - - - -
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt index eb6e9da3..22783cfc7 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -2967,6 +2967,11 @@ setter selectionStart setter value setter wrap +interface HTMLTimeElement : HTMLElement + attribute @@toStringTag + getter dateTime + method constructor + setter dateTime interface HTMLTitleElement : HTMLElement attribute @@toStringTag getter text @@ -5280,7 +5285,6 @@ interface SVGPathElement : SVGGeometryElement attribute @@toStringTag method constructor - method getPathSegAtLength interface SVGPatternElement : SVGElement attribute @@toStringTag getter height
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/v0/event-path.html b/third_party/WebKit/LayoutTests/shadow-dom/v0/event-path.html new file mode 100644 index 0000000..990d366 --- /dev/null +++ b/third_party/WebKit/LayoutTests/shadow-dom/v0/event-path.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<img id="img" src="../../images/resources/test-load.jpg"> +<script> + +// Basic functionality test for Event.path. +img.onload = function(e) { + test(function() { + assert_array_equals(e.composedPath(), e.path); + }, "Event.composedPath() should be the same as Event.path."); +}; + +</script>
diff --git a/third_party/WebKit/LayoutTests/svg/css/path-element.html b/third_party/WebKit/LayoutTests/svg/css/path-element.html index c8ac1e2..6016eb9 100644 --- a/third_party/WebKit/LayoutTests/svg/css/path-element.html +++ b/third_party/WebKit/LayoutTests/svg/css/path-element.html
@@ -24,11 +24,6 @@ }, "Test for getPointAtLength using computed style"); test(function() { var test = document.getElementById("test"); - assert_equals(test.getPathSegAtLength(50), 2); -}, "Test for getPathSegAtLength using computed style"); - -test(function() { - var test = document.getElementById("test"); assert_equals(getComputedStyle(test).d, "path('M 0 0 H 30 V 40')"); }, "Test for CSS d using computed style"); test(function() {
diff --git a/third_party/WebKit/LayoutTests/svg/dom/SVGGeometryElement-valid-arguments.html b/third_party/WebKit/LayoutTests/svg/dom/SVGGeometryElement-valid-arguments.html index 76fb2f4..b5db2f4 100644 --- a/third_party/WebKit/LayoutTests/svg/dom/SVGGeometryElement-valid-arguments.html +++ b/third_party/WebKit/LayoutTests/svg/dom/SVGGeometryElement-valid-arguments.html
@@ -9,9 +9,5 @@ assert_throws(new TypeError(), function() { pathElement.getPointAtLength(); }); assert_throws(new TypeError(), function() { pathElement.getPointAtLength(NaN); }); assert_throws(new TypeError(), function() { pathElement.getPointAtLength(Infinity); }); - - assert_throws(new TypeError(), function() { pathElement.getPathSegAtLength(); }); - assert_throws(new TypeError(), function() { pathElement.getPathSegAtLength(NaN); }); - assert_throws(new TypeError(), function() { pathElement.getPathSegAtLength(Infinity); }); }); </script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/svg/dom/path-queries-pathLength.html b/third_party/WebKit/LayoutTests/svg/dom/path-queries-pathLength.html index 462acfc..cbf357e 100644 --- a/third_party/WebKit/LayoutTests/svg/dom/path-queries-pathLength.html +++ b/third_party/WebKit/LayoutTests/svg/dom/path-queries-pathLength.html
@@ -21,9 +21,4 @@ assert_approx_equals(point.x, 100, 1e-5); assert_approx_equals(point.y, 50, 1e-5); }, document.title+', getPointAtLength'); - -test(function() { - assert_equals(path.getPathSegAtLength(50), 1); - assert_equals(path.getPathSegAtLength(150), 2); -}, document.title+', getPathSegAtLength'); </script>
diff --git a/third_party/WebKit/LayoutTests/svg/dom/script-tests/svgpath-getPathSegAtLength.js b/third_party/WebKit/LayoutTests/svg/dom/script-tests/svgpath-getPathSegAtLength.js deleted file mode 100644 index d1c48aa..0000000 --- a/third_party/WebKit/LayoutTests/svg/dom/script-tests/svgpath-getPathSegAtLength.js +++ /dev/null
@@ -1,26 +0,0 @@ -description("Test SVG path.getPathSegAtLength()."); -/* - getPathSegAtLength() returns the index into pathSegList which is distance units along the path. - Parameters - in float distance The distance along the path, relative to the start of the path, as a distance in the current user coordinate system. - Return value - unsigned long The index of the path segment, where the first path segment is number 0. - - See specification for detail: http://www.w3.org/TR/SVG/paths.html#DistanceAlongAPath -*/ - -path = document.createElementNS("http://www.w3.org/2000/svg", "path"); -path.setAttributeNS(null, "d", "M0 0 L0 5 L5 5 L 5 0"); -shouldBe("path.getPathSegAtLength(0)", "0"); -shouldBe("path.getPathSegAtLength(1)", "1"); -shouldBe("path.getPathSegAtLength(5)", "1"); -shouldBe("path.getPathSegAtLength(6)", "2"); -shouldBe("path.getPathSegAtLength(10)", "2"); -shouldBe("path.getPathSegAtLength(11)", "3"); -// WebKit/Opera/FF all return the last path segment if the distance exceeds the actual path length: -shouldBe("path.getPathSegAtLength(16)", "3"); -shouldBe("path.getPathSegAtLength(20)", "3"); -shouldBe("path.getPathSegAtLength(24)", "3"); -shouldBe("path.getPathSegAtLength(25)", "3"); -shouldBe("path.getPathSegAtLength(100)", "3"); -successfullyParsed = true;
diff --git a/third_party/WebKit/LayoutTests/svg/dom/svgpath-getPathSegAtLength-expected.txt b/third_party/WebKit/LayoutTests/svg/dom/svgpath-getPathSegAtLength-expected.txt deleted file mode 100644 index a9da2c9e..0000000 --- a/third_party/WebKit/LayoutTests/svg/dom/svgpath-getPathSegAtLength-expected.txt +++ /dev/null
@@ -1,21 +0,0 @@ -CONSOLE WARNING: line 1: SVGPathElement.getPathSegAtLength is deprecated and will be removed in M62, around October 2017. See https://www.chromestatus.com/features/5638783282184192 for more details. -Test SVG path.getPathSegAtLength(). - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - - -PASS path.getPathSegAtLength(0) is 0 -PASS path.getPathSegAtLength(1) is 1 -PASS path.getPathSegAtLength(5) is 1 -PASS path.getPathSegAtLength(6) is 2 -PASS path.getPathSegAtLength(10) is 2 -PASS path.getPathSegAtLength(11) is 3 -PASS path.getPathSegAtLength(16) is 3 -PASS path.getPathSegAtLength(20) is 3 -PASS path.getPathSegAtLength(24) is 3 -PASS path.getPathSegAtLength(25) is 3 -PASS path.getPathSegAtLength(100) is 3 -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/WebKit/LayoutTests/svg/dom/svgpath-getPathSegAtLength.html b/third_party/WebKit/LayoutTests/svg/dom/svgpath-getPathSegAtLength.html deleted file mode 100644 index 8af985f0..0000000 --- a/third_party/WebKit/LayoutTests/svg/dom/svgpath-getPathSegAtLength.html +++ /dev/null
@@ -1,11 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> -<html> -<head> -<script src="../../resources/js-test.js"></script> -</head> -<body> -<p id="description"></p> -<div id="console"></div> -<script src="script-tests/svgpath-getPathSegAtLength.js"></script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/virtual/outofblink-cors/external/wpt/fetch/README.txt b/third_party/WebKit/LayoutTests/virtual/outofblink-cors/external/wpt/fetch/README.txt new file mode 100644 index 0000000..796ccc4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/virtual/outofblink-cors/external/wpt/fetch/README.txt
@@ -0,0 +1,4 @@ +This directory is for testing out-of-blink CORS implementation. + +We use "external/wpt/fetch" directory for testing basic loading +functionalities through fetching html files.
diff --git a/third_party/WebKit/LayoutTests/virtual/outofblink-cors/webexposed/README.txt b/third_party/WebKit/LayoutTests/virtual/outofblink-cors/webexposed/README.txt deleted file mode 100644 index 7b18999..0000000 --- a/third_party/WebKit/LayoutTests/virtual/outofblink-cors/webexposed/README.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This directory is for testing out-of-blink CORS implementation. - -We use "webexposed" directory for testing basic loading functionalities -through fetching html files.
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 36585769..08615099 100644 --- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -9,7 +9,7 @@ method constructor interface BackgroundFetchEvent : ExtendableEvent attribute @@toStringTag - getter tag + getter id method constructor interface BackgroundFetchFailEvent : BackgroundFetchEvent attribute @@toStringTag @@ -24,11 +24,11 @@ method constructor method fetch method get - method getTags + method getIds interface BackgroundFetchRegistration attribute @@toStringTag getter icons - getter tag + getter id getter title getter totalDownloadSize method abort
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-dedicated-worker-expected.txt index b0f6b6c..ccfb3a5 100644 --- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -14,11 +14,11 @@ [Worker] method constructor [Worker] method fetch [Worker] method get -[Worker] method getTags +[Worker] method getIds [Worker] interface BackgroundFetchRegistration [Worker] attribute @@toStringTag [Worker] getter icons -[Worker] getter tag +[Worker] getter id [Worker] getter title [Worker] getter totalDownloadSize [Worker] method abort
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt index 525ba22e..553a40d 100644 --- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
@@ -418,11 +418,11 @@ method constructor method fetch method get - method getTags + method getIds interface BackgroundFetchRegistration attribute @@toStringTag getter icons - getter tag + getter id getter title getter totalDownloadSize method abort @@ -3559,6 +3559,11 @@ setter selectionStart setter value setter wrap +interface HTMLTimeElement : HTMLElement + attribute @@toStringTag + getter dateTime + method constructor + setter dateTime interface HTMLTitleElement : HTMLElement attribute @@toStringTag getter text @@ -6164,7 +6169,6 @@ interface SVGPathElement : SVGGeometryElement attribute @@toStringTag method constructor - method getPathSegAtLength interface SVGPatternElement : SVGElement attribute @@toStringTag getter height
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-shared-worker-expected.txt index b3bfa3df..c799c559 100644 --- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -14,11 +14,11 @@ [Worker] method constructor [Worker] method fetch [Worker] method get -[Worker] method getTags +[Worker] method getIds [Worker] interface BackgroundFetchRegistration [Worker] attribute @@toStringTag [Worker] getter icons -[Worker] getter tag +[Worker] getter id [Worker] getter title [Worker] getter totalDownloadSize [Worker] method abort
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 5e8e1dce..018d600d 100644 --- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -6,7 +6,7 @@ getter state method constructor interface BackgroundFetchEvent : ExtendableEvent - getter tag + getter id method constructor interface BackgroundFetchFailEvent : BackgroundFetchEvent getter fetches @@ -18,10 +18,10 @@ method constructor method fetch method get - method getTags + method getIds interface BackgroundFetchRegistration getter icons - getter tag + getter id getter title getter totalDownloadSize method abort
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt index 8376c79..2e14e424 100644 --- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
@@ -986,6 +986,8 @@ property insertRow property rows property vAlign +html element time + property dateTime html element title property text html element tr
diff --git a/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt index 937837f..e28e681a 100644 --- a/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
@@ -1001,6 +1001,8 @@ property insertRow property rows property vAlign +html element time + property dateTime html element title property text html element tr
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt index 062035f..fb412129 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -14,11 +14,11 @@ [Worker] method constructor [Worker] method fetch [Worker] method get -[Worker] method getTags +[Worker] method getIds [Worker] interface BackgroundFetchRegistration [Worker] attribute @@toStringTag [Worker] getter icons -[Worker] getter tag +[Worker] getter id [Worker] getter title [Worker] getter totalDownloadSize [Worker] method abort
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 76ec6fa..f1c0e7d 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -418,11 +418,11 @@ method constructor method fetch method get - method getTags + method getIds interface BackgroundFetchRegistration attribute @@toStringTag getter icons - getter tag + getter id getter title getter totalDownloadSize method abort @@ -3559,6 +3559,11 @@ setter selectionStart setter value setter wrap +interface HTMLTimeElement : HTMLElement + attribute @@toStringTag + getter dateTime + method constructor + setter dateTime interface HTMLTitleElement : HTMLElement attribute @@toStringTag getter text @@ -6171,7 +6176,6 @@ interface SVGPathElement : SVGGeometryElement attribute @@toStringTag method constructor - method getPathSegAtLength interface SVGPatternElement : SVGElement attribute @@toStringTag getter height
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt index 8d398b5..798c08b 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -14,11 +14,11 @@ [Worker] method constructor [Worker] method fetch [Worker] method get -[Worker] method getTags +[Worker] method getIds [Worker] interface BackgroundFetchRegistration [Worker] attribute @@toStringTag [Worker] getter icons -[Worker] getter tag +[Worker] getter id [Worker] getter title [Worker] getter totalDownloadSize [Worker] method abort
diff --git a/third_party/WebKit/PRESUBMIT.py b/third_party/WebKit/PRESUBMIT.py index 39c2849..5cb3f74 100644 --- a/third_party/WebKit/PRESUBMIT.py +++ b/third_party/WebKit/PRESUBMIT.py
@@ -203,7 +203,7 @@ def source_file_filter(path): return input_api.FilterSourceFile(path, white_list=[r'third_party/WebKit/Source/.*\.(h|cpp)$'], - black_list=[r'third_party/WebKit/Source/(platform|wtf|web)/']) + black_list=[r'third_party/WebKit/Source/(platform|wtf|web|controller)/']) comment_re = input_api.re.compile(r'^\s*//') result = []
diff --git a/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp index 2b02bcf..b473122 100644 --- a/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
@@ -116,10 +116,14 @@ void LocalWindowProxy::Initialize() { TRACE_EVENT1("v8", "LocalWindowProxy::initialize", "isMainWindow", GetFrame()->IsMainFrame()); - SCOPED_BLINK_UMA_HISTOGRAM_TIMER( - GetFrame()->IsMainFrame() - ? "Blink.Binding.InitializeMainLocalWindowProxy" - : "Blink.Binding.InitializeNonMainLocalWindowProxy"); + DEFINE_STATIC_LOCAL( + CustomCountHistogram, main_frame_hist, + ("Blink.Binding.InitializeMainLocalWindowProxy", 0, 10000000, 50)); + DEFINE_STATIC_LOCAL( + CustomCountHistogram, non_main_frame_hist, + ("Blink.Binding.InitializeNonMainLocalWindowProxy", 0, 10000000, 50)); + ScopedUsHistogramTimer timer(GetFrame()->IsMainFrame() ? main_frame_hist + : non_main_frame_hist); ScriptForbiddenScope::AllowUserAgentScript allow_script;
diff --git a/third_party/WebKit/Source/controller/BUILD.gn b/third_party/WebKit/Source/controller/BUILD.gn index 517009d8..dbcd693 100644 --- a/third_party/WebKit/Source/controller/BUILD.gn +++ b/third_party/WebKit/Source/controller/BUILD.gn
@@ -49,3 +49,62 @@ configs += remove_webcore_symbols_config } } + +group("webkit_unit_tests_data") { + data = [ + "../core/testing/data/", + "../core/paint/test_data/", + ] +} + +test("webkit_unit_tests") { + visibility = [] # Allow re-assignment of list. + visibility = [ "*" ] + + sources = [ + "tests/RunAllTests.cpp", + ] + sources += bindings_unittest_files + + deps = [ + ":controller", + "//base", + "//base:i18n", + "//base/test:test_support", + "//content/test:test_support", + "//gpu:test_support", + "//services/device/public/interfaces:interfaces_blink", + "//testing/gmock", + "//testing/gtest", + "//third_party/WebKit/Source/core:unit_tests", + "//third_party/WebKit/Source/modules:unit_tests", + "//third_party/WebKit/Source/modules/exported:test_support", + "//third_party/WebKit/Source/platform:test_support", + "//third_party/WebKit/Source/platform:unit_tests", + "//third_party/WebKit/Source/platform/wtf", + "//third_party/libwebp", + "//third_party/zlib", + "//url", + "//v8", + ] + + data_deps = [ + ":webkit_unit_tests_data", + "//content/shell:pak", + ] + + configs += [ + "//third_party/WebKit/Source:config", + "//third_party/WebKit/Source:inside_blink", + "//third_party/WebKit/Source/core:blink_core_pch", + ] + + if (is_android) { + deps += [ + "//base:base_java", + "//content/public/android:content_java", + "//content/shell/android:content_shell_assets", + "//net/android:net_java", + ] + } +}
diff --git a/third_party/WebKit/Source/web/tests/DEPS b/third_party/WebKit/Source/controller/tests/DEPS similarity index 90% rename from third_party/WebKit/Source/web/tests/DEPS rename to third_party/WebKit/Source/controller/tests/DEPS index 1e11e25..e442447f 100644 --- a/third_party/WebKit/Source/web/tests/DEPS +++ b/third_party/WebKit/Source/controller/tests/DEPS
@@ -1,7 +1,6 @@ include_rules = [ "+base", "+mojo/public/cpp/bindings", - "+web/tests", ] specific_include_rules = {
diff --git a/third_party/WebKit/Source/web/tests/OWNERS b/third_party/WebKit/Source/controller/tests/OWNERS similarity index 100% rename from third_party/WebKit/Source/web/tests/OWNERS rename to third_party/WebKit/Source/controller/tests/OWNERS
diff --git a/third_party/WebKit/Source/web/tests/RunAllTests.cpp b/third_party/WebKit/Source/controller/tests/RunAllTests.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/RunAllTests.cpp rename to third_party/WebKit/Source/controller/tests/RunAllTests.cpp
diff --git a/third_party/WebKit/Source/core/animation/Animation.cpp b/third_party/WebKit/Source/core/animation/Animation.cpp index 483107e..3f18a8df 100644 --- a/third_party/WebKit/Source/core/animation/Animation.cpp +++ b/third_party/WebKit/Source/core/animation/Animation.cpp
@@ -31,9 +31,9 @@ #include "core/animation/Animation.h" #include "core/animation/AnimationTimeline.h" -#include "core/animation/CompositorPendingAnimations.h" #include "core/animation/DocumentTimeline.h" #include "core/animation/KeyframeEffectReadOnly.h" +#include "core/animation/PendingAnimations.h" #include "core/animation/css/CSSAnimations.h" #include "core/dom/DOMNodeIds.h" #include "core/dom/Document.h" @@ -887,8 +887,7 @@ compositor_state_->playback_rate != playback_rate_ || compositor_state_->start_time != start_time_) { compositor_pending_ = true; - TimelineInternal()->GetDocument()->GetCompositorPendingAnimations().Add( - this); + TimelineInternal()->GetDocument()->GetPendingAnimations().Add(this); } } @@ -1072,7 +1071,7 @@ void Animation::NotifyAnimationStarted(double monotonic_time, int group) { TimelineInternal() ->GetDocument() - ->GetCompositorPendingAnimations() + ->GetPendingAnimations() .NotifyCompositorAnimationStarted(monotonic_time, group); }
diff --git a/third_party/WebKit/Source/core/animation/AnimationTest.cpp b/third_party/WebKit/Source/core/animation/AnimationTest.cpp index 006024a5..df4ab43 100644 --- a/third_party/WebKit/Source/core/animation/AnimationTest.cpp +++ b/third_party/WebKit/Source/core/animation/AnimationTest.cpp
@@ -32,10 +32,10 @@ #include <memory> #include "core/animation/AnimationClock.h" -#include "core/animation/CompositorPendingAnimations.h" #include "core/animation/DocumentTimeline.h" #include "core/animation/ElementAnimations.h" #include "core/animation/KeyframeEffect.h" +#include "core/animation/PendingAnimations.h" #include "core/dom/DOMNodeIds.h" #include "core/dom/Document.h" #include "core/dom/QualifiedName.h" @@ -84,8 +84,7 @@ Optional<CompositorElementIdSet> composited_element_ids = Optional<CompositorElementIdSet>()) { document->GetAnimationClock().UpdateTime(time); - document->GetCompositorPendingAnimations().Update(composited_element_ids, - false); + document->GetPendingAnimations().Update(composited_element_ids, false); // The timeline does not know about our animation, so we have to explicitly // call update(). return animation->Update(kTimingUpdateForAnimationFrame);
diff --git a/third_party/WebKit/Source/core/animation/BUILD.gn b/third_party/WebKit/Source/core/animation/BUILD.gn index b9dd440..e849355 100644 --- a/third_party/WebKit/Source/core/animation/BUILD.gn +++ b/third_party/WebKit/Source/core/animation/BUILD.gn
@@ -101,8 +101,6 @@ "CompositorAnimator.h", "CompositorMutatorImpl.cpp", "CompositorMutatorImpl.h", - "CompositorPendingAnimations.cpp", - "CompositorPendingAnimations.h", "CustomCompositorAnimationManager.cpp", "CustomCompositorAnimationManager.h", "CustomCompositorAnimations.cpp", @@ -170,6 +168,8 @@ "PairwiseInterpolationValue.h", "PathInterpolationFunctions.cpp", "PathInterpolationFunctions.h", + "PendingAnimations.cpp", + "PendingAnimations.h", "PrimitiveInterpolation.h", "PropertyHandle.cpp", "PropertyHandle.h",
diff --git a/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp b/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp index f52e9191..9d9c8c80 100644 --- a/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp +++ b/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp
@@ -32,10 +32,10 @@ #include <memory> #include "core/animation/Animation.h" -#include "core/animation/CompositorPendingAnimations.h" #include "core/animation/DocumentTimeline.h" #include "core/animation/ElementAnimations.h" #include "core/animation/KeyframeEffect.h" +#include "core/animation/PendingAnimations.h" #include "core/animation/animatable/AnimatableDouble.h" #include "core/animation/animatable/AnimatableFilterOperations.h" #include "core/animation/animatable/AnimatableTransform.h" @@ -270,8 +270,8 @@ void SimulateFrame(double time) { document_->GetAnimationClock().UpdateTime(time); - document_->GetCompositorPendingAnimations().Update( - Optional<CompositorElementIdSet>(), false); + document_->GetPendingAnimations().Update(Optional<CompositorElementIdSet>(), + false); timeline_->ServiceAnimations(kTimingUpdateForAnimationFrame); }
diff --git a/third_party/WebKit/Source/core/animation/DocumentAnimations.cpp b/third_party/WebKit/Source/core/animation/DocumentAnimations.cpp index 1c2a0e6..91b0c96 100644 --- a/third_party/WebKit/Source/core/animation/DocumentAnimations.cpp +++ b/third_party/WebKit/Source/core/animation/DocumentAnimations.cpp
@@ -31,8 +31,8 @@ #include "core/animation/DocumentAnimations.h" #include "core/animation/AnimationClock.h" -#include "core/animation/CompositorPendingAnimations.h" #include "core/animation/DocumentTimeline.h" +#include "core/animation/PendingAnimations.h" #include "core/dom/Document.h" #include "core/dom/Element.h" #include "core/dom/Node.h" @@ -70,8 +70,7 @@ Optional<CompositorElementIdSet>& composited_element_ids) { DCHECK(document.Lifecycle().GetState() >= required_lifecycle_state); - if (document.GetCompositorPendingAnimations().Update( - composited_element_ids)) { + if (document.GetPendingAnimations().Update(composited_element_ids)) { DCHECK(document.View()); document.View()->ScheduleAnimation(); }
diff --git a/third_party/WebKit/Source/core/animation/DocumentAnimations.h b/third_party/WebKit/Source/core/animation/DocumentAnimations.h index 932af53..94176c9 100644 --- a/third_party/WebKit/Source/core/animation/DocumentAnimations.h +++ b/third_party/WebKit/Source/core/animation/DocumentAnimations.h
@@ -47,7 +47,8 @@ static void UpdateAnimationTimingIfNeeded(Document&); // Updates existing animations as part of generating a new (document - // lifecycle) frame. + // lifecycle) frame. Note that this considers and updates state for + // both composited and non-composited animations. static void UpdateAnimations( Document&, DocumentLifecycle::LifecycleState required_lifecycle_state,
diff --git a/third_party/WebKit/Source/core/animation/DocumentTimelineTest.cpp b/third_party/WebKit/Source/core/animation/DocumentTimelineTest.cpp index d4bfd9d..b2f4d1c 100644 --- a/third_party/WebKit/Source/core/animation/DocumentTimelineTest.cpp +++ b/third_party/WebKit/Source/core/animation/DocumentTimelineTest.cpp
@@ -33,9 +33,9 @@ #include <memory> #include "core/animation/AnimationClock.h" #include "core/animation/AnimationEffectReadOnly.h" -#include "core/animation/CompositorPendingAnimations.h" #include "core/animation/KeyframeEffect.h" #include "core/animation/KeyframeEffectModel.h" +#include "core/animation/PendingAnimations.h" #include "core/dom/Document.h" #include "core/dom/Element.h" #include "core/dom/QualifiedName.h" @@ -76,8 +76,8 @@ void UpdateClockAndService(double time) { document->GetAnimationClock().UpdateTime(time); - document->GetCompositorPendingAnimations().Update( - Optional<CompositorElementIdSet>(), false); + document->GetPendingAnimations().Update(Optional<CompositorElementIdSet>(), + false); timeline->ServiceAnimations(kTimingUpdateForAnimationFrame); timeline->ScheduleNextService(); }
diff --git a/third_party/WebKit/Source/core/animation/EffectStackTest.cpp b/third_party/WebKit/Source/core/animation/EffectStackTest.cpp index 720cf42..fc8cd7f78 100644 --- a/third_party/WebKit/Source/core/animation/EffectStackTest.cpp +++ b/third_party/WebKit/Source/core/animation/EffectStackTest.cpp
@@ -4,16 +4,16 @@ #include "core/animation/EffectStack.h" +#include <memory> #include "core/animation/AnimationClock.h" -#include "core/animation/CompositorPendingAnimations.h" #include "core/animation/DocumentTimeline.h" #include "core/animation/ElementAnimations.h" #include "core/animation/KeyframeEffectModel.h" #include "core/animation/LegacyStyleInterpolation.h" +#include "core/animation/PendingAnimations.h" #include "core/animation/animatable/AnimatableDouble.h" #include "core/testing/DummyPageHolder.h" #include "testing/gtest/include/gtest/gtest.h" -#include <memory> namespace blink { @@ -171,8 +171,7 @@ Play(MakeKeyframeEffect( MakeEffectModel(CSSPropertyFontSize, AnimatableDouble::Create(3))), 4); - document->GetCompositorPendingAnimations().Update( - Optional<CompositorElementIdSet>()); + document->GetPendingAnimations().Update(Optional<CompositorElementIdSet>()); ActiveInterpolationsMap interpolations; UpdateTimeline(11);
diff --git a/third_party/WebKit/Source/core/animation/CompositorPendingAnimations.cpp b/third_party/WebKit/Source/core/animation/PendingAnimations.cpp similarity index 94% rename from third_party/WebKit/Source/core/animation/CompositorPendingAnimations.cpp rename to third_party/WebKit/Source/core/animation/PendingAnimations.cpp index def6be2..b1454c82 100644 --- a/third_party/WebKit/Source/core/animation/CompositorPendingAnimations.cpp +++ b/third_party/WebKit/Source/core/animation/PendingAnimations.cpp
@@ -28,7 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "core/animation/CompositorPendingAnimations.h" +#include "core/animation/PendingAnimations.h" #include "core/animation/DocumentTimeline.h" #include "core/animation/KeyframeEffect.h" @@ -39,7 +39,7 @@ namespace blink { -void CompositorPendingAnimations::Add(Animation* animation) { +void PendingAnimations::Add(Animation* animation) { DCHECK(animation); DCHECK_EQ(pending_.Find(animation), kNotFound); pending_.push_back(animation); @@ -54,7 +54,7 @@ } } -bool CompositorPendingAnimations::Update( +bool PendingAnimations::Update( const Optional<CompositorElementIdSet>& composited_element_ids, bool start_on_compositor) { HeapVector<Member<Animation>> waiting_for_start_time; @@ -140,11 +140,10 @@ return false; } -void CompositorPendingAnimations::NotifyCompositorAnimationStarted( +void PendingAnimations::NotifyCompositorAnimationStarted( double monotonic_animation_start_time, int compositor_group) { - TRACE_EVENT0("blink", - "CompositorPendingAnimations::notifyCompositorAnimationStarted"); + TRACE_EVENT0("blink", "PendingAnimations::notifyCompositorAnimationStarted"); HeapVector<Member<Animation>> animations; animations.swap(waiting_for_compositor_animation_start_); @@ -167,7 +166,7 @@ } } -DEFINE_TRACE(CompositorPendingAnimations) { +DEFINE_TRACE(PendingAnimations) { visitor->Trace(pending_); visitor->Trace(waiting_for_compositor_animation_start_); }
diff --git a/third_party/WebKit/Source/core/animation/CompositorPendingAnimations.h b/third_party/WebKit/Source/core/animation/PendingAnimations.h similarity index 80% rename from third_party/WebKit/Source/core/animation/CompositorPendingAnimations.h rename to third_party/WebKit/Source/core/animation/PendingAnimations.h index 6bc95ee..8525032 100644 --- a/third_party/WebKit/Source/core/animation/CompositorPendingAnimations.h +++ b/third_party/WebKit/Source/core/animation/PendingAnimations.h
@@ -28,8 +28,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CompositorPendingAnimations_h -#define CompositorPendingAnimations_h +#ifndef PendingAnimations_h +#define PendingAnimations_h #include "core/CoreExport.h" #include "core/animation/Animation.h" @@ -42,18 +42,26 @@ namespace blink { +// Handles starting animations when they could potentially require +// interaction with the compositor. This can include both main-thread +// and compositor thread animations. For example, when the Document +// changes visibility state, all animations for the document's +// timeline are set to "compositor pending" which will include them in +// a consideration pass here. +// // Manages the starting of pending animations on the compositor following a // compositing update. +// // For CSS Animations, used to synchronize the start of main-thread animations // with compositor animations when both classes of CSS Animations are triggered -// by the same recalc -class CORE_EXPORT CompositorPendingAnimations final - : public GarbageCollectedFinalized<CompositorPendingAnimations> { +// by the same recalc. +class CORE_EXPORT PendingAnimations final + : public GarbageCollectedFinalized<PendingAnimations> { public: - explicit CompositorPendingAnimations(Document& document) + explicit PendingAnimations(Document& document) : timer_(TaskRunnerHelper::Get(TaskType::kUnspecedTimer, &document), this, - &CompositorPendingAnimations::TimerFired), + &PendingAnimations::TimerFired), compositor_group_(1) {} void Add(Animation*); @@ -73,7 +81,7 @@ HeapVector<Member<Animation>> pending_; HeapVector<Member<Animation>> waiting_for_compositor_animation_start_; - TaskRunnerTimer<CompositorPendingAnimations> timer_; + TaskRunnerTimer<PendingAnimations> timer_; int compositor_group_; };
diff --git a/third_party/WebKit/Source/core/core_idl_files.gni b/third_party/WebKit/Source/core/core_idl_files.gni index 97f56379..784fd4b 100644 --- a/third_party/WebKit/Source/core/core_idl_files.gni +++ b/third_party/WebKit/Source/core/core_idl_files.gni
@@ -245,6 +245,7 @@ "html/HTMLTableSectionElement.idl", "html/HTMLTemplateElement.idl", "html/HTMLTextAreaElement.idl", + "html/HTMLTimeElement.idl", "html/HTMLTitleElement.idl", "html/HTMLTrackElement.idl", "html/HTMLUListElement.idl",
diff --git a/third_party/WebKit/Source/core/css/BUILD.gn b/third_party/WebKit/Source/core/css/BUILD.gn index acba5f5a..9951d500 100644 --- a/third_party/WebKit/Source/core/css/BUILD.gn +++ b/third_party/WebKit/Source/core/css/BUILD.gn
@@ -222,6 +222,8 @@ "MediaValuesDynamic.h", "MediaValuesInitialViewport.cpp", "MediaValuesInitialViewport.h", + "OffscreenFontSelector.cpp", + "OffscreenFontSelector.h", "PageRuleCollector.cpp", "PageRuleCollector.h", "PropertyRegistration.cpp",
diff --git a/third_party/WebKit/Source/core/css/CSSFontSelector.cpp b/third_party/WebKit/Source/core/css/CSSFontSelector.cpp index 012423b..5acadcd 100644 --- a/third_party/WebKit/Source/core/css/CSSFontSelector.cpp +++ b/third_party/WebKit/Source/core/css/CSSFontSelector.cpp
@@ -87,40 +87,6 @@ DispatchInvalidationCallbacks(); } -static AtomicString FamilyNameFromSettings( - const GenericFontFamilySettings& settings, - const FontDescription& font_description, - const AtomicString& generic_family_name) { -#if defined(OS_ANDROID) - if (font_description.GenericFamily() == FontDescription::kStandardFamily) - return FontCache::GetGenericFamilyNameForScript( - FontFamilyNames::webkit_standard, font_description); - - if (generic_family_name.StartsWith("-webkit-")) - return FontCache::GetGenericFamilyNameForScript(generic_family_name, - font_description); -#else - UScriptCode script = font_description.GetScript(); - if (font_description.GenericFamily() == FontDescription::kStandardFamily) - return settings.Standard(script); - if (generic_family_name == FontFamilyNames::webkit_serif) - return settings.Serif(script); - if (generic_family_name == FontFamilyNames::webkit_sans_serif) - return settings.SansSerif(script); - if (generic_family_name == FontFamilyNames::webkit_cursive) - return settings.Cursive(script); - if (generic_family_name == FontFamilyNames::webkit_fantasy) - return settings.Fantasy(script); - if (generic_family_name == FontFamilyNames::webkit_monospace) - return settings.Fixed(script); - if (generic_family_name == FontFamilyNames::webkit_pictograph) - return settings.Pictograph(script); - if (generic_family_name == FontFamilyNames::webkit_standard) - return settings.Standard(script); -#endif - return g_empty_atom; -} - RefPtr<FontData> CSSFontSelector::GetFontData( const FontDescription& font_description, const AtomicString& family_name) {
diff --git a/third_party/WebKit/Source/core/css/OffscreenFontSelector.cpp b/third_party/WebKit/Source/core/css/OffscreenFontSelector.cpp new file mode 100644 index 0000000..430d30ac --- /dev/null +++ b/third_party/WebKit/Source/core/css/OffscreenFontSelector.cpp
@@ -0,0 +1,66 @@ +// 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 "core/css/OffscreenFontSelector.h" + +#include "build/build_config.h" +#include "core/css/CSSSegmentedFontFace.h" +#include "core/css/CSSValueList.h" +#include "core/css/FontFaceSet.h" +#include "core/css/resolver/StyleResolver.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/Settings.h" +#include "core/frame/UseCounter.h" +#include "core/loader/FrameLoader.h" +#include "platform/RuntimeEnabledFeatures.h" +#include "platform/fonts/FontCache.h" +#include "platform/fonts/FontSelectorClient.h" +#include "platform/fonts/SimpleFontData.h" +#include "platform/wtf/text/AtomicString.h" + +namespace blink { + +OffscreenFontSelector::OffscreenFontSelector( + const GenericFontFamilySettings& settings) + : generic_font_family_settings_(settings) {} + +OffscreenFontSelector::~OffscreenFontSelector() {} + +void OffscreenFontSelector::RegisterForInvalidationCallbacks( + FontSelectorClient* client) {} + +void OffscreenFontSelector::UnregisterForInvalidationCallbacks( + FontSelectorClient* client) {} + +RefPtr<FontData> OffscreenFontSelector::GetFontData( + const FontDescription& font_description, + const AtomicString& family_name) { + AtomicString settings_family_name = FamilyNameFromSettings( + generic_font_family_settings_, font_description, family_name); + if (settings_family_name.IsEmpty()) + return nullptr; + + return FontCache::GetFontCache()->GetFontData(font_description, + settings_family_name); +} + +void OffscreenFontSelector::WillUseFontData( + const FontDescription& font_description, + const AtomicString& family, + const String& text) {} + +void OffscreenFontSelector::WillUseRange( + const FontDescription& font_description, + const AtomicString& family, + const FontDataForRangeSet& range_set) {} + +void OffscreenFontSelector::ReportNotDefGlyph() const {} + +void OffscreenFontSelector::FontCacheInvalidated() {} + +DEFINE_TRACE(OffscreenFontSelector) { + FontSelector::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/css/OffscreenFontSelector.h b/third_party/WebKit/Source/core/css/OffscreenFontSelector.h new file mode 100644 index 0000000..494e33e --- /dev/null +++ b/third_party/WebKit/Source/core/css/OffscreenFontSelector.h
@@ -0,0 +1,64 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef OffscreenFontSelector_h +#define OffscreenFontSelector_h + +#include "core/CoreExport.h" +#include "core/css/FontFaceCache.h" +#include "platform/fonts/FontSelector.h" +#include "platform/fonts/GenericFontFamilySettings.h" +#include "platform/heap/Handle.h" +#include "platform/wtf/Forward.h" +#include "platform/wtf/HashMap.h" +#include "platform/wtf/HashSet.h" + +namespace blink { + +class FontDescription; + +class CORE_EXPORT OffscreenFontSelector : public FontSelector { + public: + static OffscreenFontSelector* Create( + const GenericFontFamilySettings& settings) { + return new OffscreenFontSelector(settings); + } + ~OffscreenFontSelector() override; + + unsigned Version() const override { return 1; } + + void ReportNotDefGlyph() const override; + + RefPtr<FontData> GetFontData(const FontDescription&, + const AtomicString&) override; + void WillUseFontData(const FontDescription&, + const AtomicString& family, + const String& text) override; + void WillUseRange(const FontDescription&, + const AtomicString& family_name, + const FontDataForRangeSet&) override; + + void RegisterForInvalidationCallbacks(FontSelectorClient*) override; + void UnregisterForInvalidationCallbacks(FontSelectorClient*) override; + + const GenericFontFamilySettings& GetGenericFontFamilySettings() const { + return generic_font_family_settings_; + } + + void FontCacheInvalidated() override; + + DECLARE_VIRTUAL_TRACE(); + + protected: + explicit OffscreenFontSelector(const GenericFontFamilySettings&); + + void DispatchInvalidationCallbacks(); + + private: + const GenericFontFamilySettings generic_font_family_settings_; +}; + +} // namespace blink + +#endif // OffscreenFontSelector_h
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index 1f9a43a86..5fedacd 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -47,9 +47,9 @@ #include "core/SVGNames.h" #include "core/XMLNSNames.h" #include "core/XMLNames.h" -#include "core/animation/CompositorPendingAnimations.h" #include "core/animation/DocumentAnimations.h" #include "core/animation/DocumentTimeline.h" +#include "core/animation/PendingAnimations.h" #include "core/css/CSSFontSelector.h" #include "core/css/CSSStyleDeclaration.h" #include "core/css/CSSStyleSheet.h" @@ -586,7 +586,7 @@ this, &Document::ElementDataCacheClearTimerFired), timeline_(DocumentTimeline::Create(this)), - compositor_pending_animations_(new CompositorPendingAnimations(*this)), + pending_animations_(new PendingAnimations(*this)), template_document_host_(nullptr), did_associate_form_controls_timer_( TaskRunnerHelper::Get(TaskType::kUnspecedLoading, this), @@ -666,6 +666,20 @@ // If a top document with a cache, verify that it was comprehensively // cleared during detach. DCHECK(!ax_object_cache_); + + // As not all documents are destroyed before the process dies, this might miss + // some long-lived documents or leaked documents. + // TODO(hajimehoshi): Record outlive time of documents that are not destroyed + // before the process dies. + // TODO(hajimehoshi): There are some cases that a document can live after + // shutting down because the document can still be reffed (e.g. a document + // opened via window.open can be reffed by the opener even after shutting + // down). Detect those cases and record them independently. + UMA_HISTOGRAM_EXACT_LINEAR( + "Document.OutliveTimeAfterShutdown.DestroyedBeforeProcessDies", + ThreadState::Current()->GcAge() - gc_age_when_document_detached_ + 1, + 101); + InstanceCounters::DecrementCounter(InstanceCounters::kDocumentCounter); } @@ -1041,14 +1055,18 @@ imports_controller_ = nullptr; } -void Document::CreateImportsController() { - DCHECK(!imports_controller_); - imports_controller_ = HTMLImportsController::Create(*this); +HTMLImportsController* Document::EnsureImportsController() { + if (!imports_controller_) { + DCHECK(frame_); + imports_controller_ = HTMLImportsController::Create(*this); + } + + return imports_controller_; } HTMLImportLoader* Document::ImportLoader() const { if (!imports_controller_) - return 0; + return nullptr; return imports_controller_->LoaderFor(*this); } @@ -2007,24 +2025,6 @@ GetLayoutViewItem().SetStyle(new_style); SetupFontBuilder(*new_style); } - - if (body) { - if (const ComputedStyle* style = body->GetComputedStyle()) { - if (style->Direction() != root_direction || - style->GetWritingMode() != root_writing_mode) - body->SetNeedsStyleRecalc(kSubtreeStyleChange, - StyleChangeReasonForTracing::Create( - StyleChangeReason::kWritingModeChange)); - } - } - - if (const ComputedStyle* style = documentElement()->GetComputedStyle()) { - if (style->Direction() != root_direction || - style->GetWritingMode() != root_writing_mode) - documentElement()->SetNeedsStyleRecalc( - kSubtreeStyleChange, StyleChangeReasonForTracing::Create( - StyleChangeReason::kWritingModeChange)); - } } #if DCHECK_IS_ON() @@ -2740,6 +2740,8 @@ // should be renamed, or this setting of the frame to 0 could be made // explicit in each of the callers of Document::detachLayoutTree(). frame_ = nullptr; + + gc_age_when_document_detached_ = ThreadState::Current()->GcAge(); } void Document::RemoveAllEventListeners() { @@ -6426,16 +6428,12 @@ DocumentLoader* Document::Loader() const { if (!frame_) - return 0; - - DocumentLoader* loader = frame_->Loader().GetDocumentLoader(); - if (!loader) - return 0; + return nullptr; if (frame_->GetDocument() != this) - return 0; + return nullptr; - return loader; + return frame_->Loader().GetDocumentLoader(); } Node* EventTargetNodeForDocument(Document* doc) { @@ -6954,7 +6952,7 @@ visitor->Trace(user_action_elements_); visitor->Trace(svg_extensions_); visitor->Trace(timeline_); - visitor->Trace(compositor_pending_animations_); + visitor->Trace(pending_animations_); visitor->Trace(context_document_); visitor->Trace(canvas_font_cache_); visitor->Trace(intersection_observer_controller_);
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h index 0667c0c..699c0c97 100644 --- a/third_party/WebKit/Source/core/dom/Document.h +++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -85,7 +85,6 @@ class CSSStyleSheet; class CanvasFontCache; class ChromeClient; -class CompositorPendingAnimations; class Comment; class ComputedStyle; class ConsoleMessage; @@ -144,6 +143,7 @@ class NthIndexCache; class OriginAccessEntry; class Page; +class PendingAnimations; class ProcessingInstruction; class PropertyRegistry; class QualifiedName; @@ -1176,7 +1176,7 @@ V0CustomElementMicrotaskRunQueue* CustomElementMicrotaskRunQueue(); void ClearImportsController(); - void CreateImportsController(); + HTMLImportsController* EnsureImportsController(); HTMLImportsController* ImportsController() const { return imports_controller_; } @@ -1207,9 +1207,7 @@ AnimationClock& GetAnimationClock(); DocumentTimeline& Timeline() const { return *timeline_; } - CompositorPendingAnimations& GetCompositorPendingAnimations() { - return *compositor_pending_animations_; - } + PendingAnimations& GetPendingAnimations() { return *pending_animations_; } void AddToTopLayer(Element*, const Element* before = nullptr); void RemoveFromTopLayer(Element*); @@ -1675,7 +1673,7 @@ LocaleIdentifierToLocaleMap locale_cache_; Member<DocumentTimeline> timeline_; - Member<CompositorPendingAnimations> compositor_pending_animations_; + Member<PendingAnimations> pending_animations_; Member<Document> template_document_; Member<Document> template_document_host_; @@ -1722,6 +1720,8 @@ Member<NetworkStateObserver> network_state_observer_; bool has_high_media_engagement_; + + int gc_age_when_document_detached_ = 0; }; extern template class CORE_EXTERN_TEMPLATE_EXPORT Supplement<Document>;
diff --git a/third_party/WebKit/Source/core/dom/DocumentTest.cpp b/third_party/WebKit/Source/core/dom/DocumentTest.cpp index 451a2b3..d0f31e5 100644 --- a/third_party/WebKit/Source/core/dom/DocumentTest.cpp +++ b/third_party/WebKit/Source/core/dom/DocumentTest.cpp
@@ -916,4 +916,24 @@ GetDocument().Lifecycle().GetState()); } +// Tests that the difference in computed style of direction on the html and body +// elements does not trigger a style recalc for viewport style propagation when +// the computed style for another element in the document is recalculated. +TEST_F(DocumentTest, ViewportPropagationNoRecalc) { + SetHtmlInnerHTML( + "<body style='direction:rtl'>" + " <div id=recalc></div>" + "</body>"); + + int old_element_count = GetDocument().GetStyleEngine().StyleForElementCount(); + + Element* div = GetDocument().getElementById("recalc"); + div->setAttribute("style", "color:green"); + GetDocument().UpdateStyleAndLayoutTree(); + + int new_element_count = GetDocument().GetStyleEngine().StyleForElementCount(); + + EXPECT_EQ(1, new_element_count - old_element_count); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/README.md b/third_party/WebKit/Source/core/dom/README.md index 474782e7..c29b1f11 100644 --- a/third_party/WebKit/Source/core/dom/README.md +++ b/third_party/WebKit/Source/core/dom/README.md
@@ -2,13 +2,13 @@ [Rendered](https://chromium.googlesource.com/chromium/src/+/master/third_party/WebKit/Source/core/dom/README.md) -This directory contains the implementation of [DOM]. +The `Source/core/dom` directory contains the implementation of [DOM]. [DOM]: https://dom.spec.whatwg.org/ [DOM Standard]: https://dom.spec.whatwg.org/ Basically, this directory should contain only a file which is related to [DOM Standard]. -However, for historical reasons, `core/dom` directory has been used +However, for historical reasons, `Source/core/dom` directory has been used as if it were *misc* directory. As a result, unfortunately, this directory contains a lot of files which are not directly related to DOM. @@ -22,3 +22,73 @@ if you know more appropriate places for each file. - See [crbug.com/738794](http://crbug.com/738794) for tracking our efforts. + + +# Node and DOM Tree + +In this README, we draw a tree in left-to-right direction. `A` is the root of the tree. + + +``` text +A +├───B +├───C +│ ├───D +│ └───E +└───E +``` + +`Node` is a base class of all kinds of nodes in DOM tree. Each `Node` has following 3 pointers (but not limited to): + +- `parent_or_shadow_host_node_`: Points to the parent (or the shadow host if it is a shadow root; explained later) +- `previous_`: Points to the previous sibling +- `next_`: Points to the next sibling + +`ContainerNode`, from which `Element` extends, has additional pointers for its child: + +- `first_child_`: The meaning is obvious. +- `last_child_`: Nit. + +That means: +- Siblings are stored as a linked list. It takes O(N) to access a parent's n-th child. +- Parent can't tell how many children it has in O(1). + +# Zero-Cost Nodes traversal functions + +TODO(hayato): Explain. + +# Shadow Tree + +TODO(hayato): Explain. + +# TreeScope + +TODO(hayato): Explain. + +# Composed Tree (a tree of DOM trees) + +TODO(hayato): Explain. + +# Layout Tree + +TODO(hayato): Explain. + +# Flat tree and `FlatTreeTraversal` + +TODO(hayato): Explain. + +# Distribution and slots + +TODO(hayato): Explain. + +# DOM mutations + +TODO(hayato): Explain. + +# Related flags + +TODO(hayato): Explain. + +# Event path and Event Retargeting + +TODO(hayato): Explain.
diff --git a/third_party/WebKit/Source/core/editing/BUILD.gn b/third_party/WebKit/Source/core/editing/BUILD.gn index 91bd552e..835d7ab 100644 --- a/third_party/WebKit/Source/core/editing/BUILD.gn +++ b/third_party/WebKit/Source/core/editing/BUILD.gn
@@ -321,6 +321,7 @@ "PositionIteratorTest.cpp", "PositionTest.cpp", "RelocatablePositionTest.cpp", + "RenderedPositionTest.cpp", "SelectionControllerTest.cpp", "SelectionModifierTest.cpp", "SelectionTemplateTest.cpp",
diff --git a/third_party/WebKit/Source/core/editing/Editor.cpp b/third_party/WebKit/Source/core/editing/Editor.cpp index bf7236d..27958091 100644 --- a/third_party/WebKit/Source/core/editing/Editor.cpp +++ b/third_party/WebKit/Source/core/editing/Editor.cpp
@@ -184,11 +184,9 @@ // When an event handler has moved the selection outside of a text control // we should use the target control's selection for this editing operation. -// TODO(yosin): We should make |Editor::selectionForCommand()| to return -// |SelectionInDOMTree| instead of |VisibleSelection|. -VisibleSelection Editor::SelectionForCommand(Event* event) { - const VisibleSelection selection = - GetFrame().Selection().ComputeVisibleSelectionInDOMTree(); +SelectionInDOMTree Editor::SelectionForCommand(Event* event) { + const SelectionInDOMTree selection = + GetFrame().Selection().GetSelectionInDOMTree(); if (!event) return selection; // If the target is a text control, and the current selection is outside of @@ -196,16 +194,16 @@ if (!IsTextControlElement(*event->target()->ToNode())) return selection; TextControlElement* text_control_of_selection_start = - EnclosingTextControl(selection.Start()); + EnclosingTextControl(selection.Base()); TextControlElement* text_control_of_target = ToTextControlElement(event->target()->ToNode()); - if (selection.Start().IsNotNull() && + if (!selection.IsNone() && text_control_of_target == text_control_of_selection_start) return selection; const SelectionInDOMTree& select = text_control_of_target->Selection(); if (select.IsNone()) return selection; - return CreateVisibleSelection(select); + return select; } // Function considers Mac editing behavior a fallback when Page or Settings is @@ -1053,7 +1051,8 @@ bool select_inserted_text, TextEvent* triggering_event, InputEvent::InputType input_type) { - const VisibleSelection& selection = SelectionForCommand(triggering_event); + const VisibleSelection& selection = + CreateVisibleSelection(SelectionForCommand(triggering_event)); if (!selection.IsContentEditable()) return false;
diff --git a/third_party/WebKit/Source/core/editing/Editor.h b/third_party/WebKit/Source/core/editing/Editor.h index b9ef7738..fe561c2 100644 --- a/third_party/WebKit/Source/core/editing/Editor.h +++ b/third_party/WebKit/Source/core/editing/Editor.h
@@ -214,7 +214,7 @@ void Clear(); - VisibleSelection SelectionForCommand(Event*); + SelectionInDOMTree SelectionForCommand(Event*); KillRing& GetKillRing() const { return *kill_ring_; }
diff --git a/third_party/WebKit/Source/core/editing/InputMethodController.cpp b/third_party/WebKit/Source/core/editing/InputMethodController.cpp index 78dc3f0f..853f3d59 100644 --- a/third_party/WebKit/Source/core/editing/InputMethodController.cpp +++ b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
@@ -195,7 +195,7 @@ // TODO(dtapuska): We may wish to restrict this to a yet to be proposed // <contenteditable> or <richtext> element Mozilla discussed at TPAC 2016. - return element->FastGetAttribute(HTMLNames::inputmodeAttr).DeprecatedLower(); + return element->FastGetAttribute(HTMLNames::inputmodeAttr).LowerASCII(); } constexpr int kInvalidDeletionLength = -1;
diff --git a/third_party/WebKit/Source/core/editing/InputMethodController.h b/third_party/WebKit/Source/core/editing/InputMethodController.h index 844222d3..88f1f25 100644 --- a/third_party/WebKit/Source/core/editing/InputMethodController.h +++ b/third_party/WebKit/Source/core/editing/InputMethodController.h
@@ -26,6 +26,7 @@ #ifndef InputMethodController_h #define InputMethodController_h +#include "base/gtest_prod_util.h" #include "core/CoreExport.h" #include "core/dom/SynchronousMutationObserver.h" #include "core/editing/CompositionUnderline.h" @@ -170,6 +171,9 @@ // Returns true if selection offsets were successfully set. bool SetSelectionOffsets(const PlainTextRange&, TypingContinuation); + + FRIEND_TEST_ALL_PREFIXES(InputMethodControllerTest, + InputModeOfFocusedElement); }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp b/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp index 3462e9c..c368cc3 100644 --- a/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp +++ b/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp
@@ -2302,4 +2302,18 @@ EXPECT_STREQ("abcd", input->value().Utf8().data()); } +TEST_F(InputMethodControllerTest, InputModeOfFocusedElement) { + InsertHTMLElement("<input id='a' inputmode='KataKana'>", "a")->focus(); + EXPECT_EQ(kWebTextInputModeKataKana, + Controller().InputModeOfFocusedElement()); + + // U+212A + "atakana" + InsertHTMLElement( + "<input id='b' inputmode='\xE2\x84\xAA" + "atakana'>", + "b") + ->focus(); + EXPECT_EQ(kWebTextInputModeDefault, Controller().InputModeOfFocusedElement()); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/LayoutSelection.cpp b/third_party/WebKit/Source/core/editing/LayoutSelection.cpp index b93ed45c..c0d917e 100644 --- a/third_party/WebKit/Source/core/editing/LayoutSelection.cpp +++ b/third_party/WebKit/Source/core/editing/LayoutSelection.cpp
@@ -441,14 +441,6 @@ InsertLayoutObjectAndAncestorBlocks(&invalidation_set, end_layout_object); } - // TODO(yoichio): If start == end, they should be kStartAndEnd. - // If not, start.SelectionState == kStart and vice versa. - DCHECK(start_layout_object->GetSelectionState() == SelectionState::kStart || - start_layout_object->GetSelectionState() == - SelectionState::kStartAndEnd); - DCHECK(end_layout_object->GetSelectionState() == SelectionState::kEnd || - end_layout_object->GetSelectionState() == - SelectionState::kStartAndEnd); return {start_layout_object, start_editing_offset, end_layout_object, end_pos.ComputeEditingOffset(), std::move(invalidation_set)}; } @@ -472,6 +464,43 @@ DCHECK(!frame_selection_->GetDocument().NeedsLayoutTreeUpdate()); SetShouldInvalidateSelection(new_range, paint_range_); paint_range_ = new_range.ToPaintRange(); + // TODO(yoichio): Remove this if state. + // This SelectionState reassignment is ad-hoc patch for + // prohibiting use-after-free(crbug.com/752715). + // LayoutText::setSelectionState(state) propergates |state| to ancestor + // LayoutObjects, which can accidentally change start/end LayoutObject state + // then LayoutObject::IsSelectionBorder() returns false although we should + // clear selection at LayoutObject::WillBeRemoved(). + // We should make LayoutObject::setSelectionState() trivial and remove + // such propagation or at least do it in LayoutSelection. + if ((paint_range_.StartLayoutObject()->GetSelectionState() != + SelectionState::kStart && + paint_range_.StartLayoutObject()->GetSelectionState() != + SelectionState::kStartAndEnd) || + (paint_range_.EndLayoutObject()->GetSelectionState() != + SelectionState::kEnd && + paint_range_.EndLayoutObject()->GetSelectionState() != + SelectionState::kStartAndEnd)) { + if (paint_range_.StartLayoutObject() == paint_range_.EndLayoutObject()) { + paint_range_.StartLayoutObject()->SetSelectionStateIfNeeded( + SelectionState::kStartAndEnd); + } else { + paint_range_.StartLayoutObject()->SetSelectionStateIfNeeded( + SelectionState::kStart); + paint_range_.EndLayoutObject()->SetSelectionStateIfNeeded( + SelectionState::kEnd); + } + } + // TODO(yoichio): If start == end, they should be kStartAndEnd. + // If not, start.SelectionState == kStart and vice versa. + DCHECK(paint_range_.StartLayoutObject()->GetSelectionState() == + SelectionState::kStart || + paint_range_.StartLayoutObject()->GetSelectionState() == + SelectionState::kStartAndEnd); + DCHECK(paint_range_.EndLayoutObject()->GetSelectionState() == + SelectionState::kEnd || + paint_range_.EndLayoutObject()->GetSelectionState() == + SelectionState::kStartAndEnd); } void LayoutSelection::OnDocumentShutdown() {
diff --git a/third_party/WebKit/Source/core/editing/LayoutSelectionTest.cpp b/third_party/WebKit/Source/core/editing/LayoutSelectionTest.cpp index 4de0dd6..0e24d333 100644 --- a/third_party/WebKit/Source/core/editing/LayoutSelectionTest.cpp +++ b/third_party/WebKit/Source/core/editing/LayoutSelectionTest.cpp
@@ -58,6 +58,7 @@ return true; } LayoutObject* Current() { return current_; } + void Reset() { current_ = nullptr; } #ifndef NDEBUG void PrintLayoutTreeForDebug() { std::stringstream stream; @@ -184,4 +185,48 @@ TEST_NO_NEXT_LAYOUT_OBJECT(); } +// crbug.com/752715 +TEST_F(LayoutSelectionTest, + InvalidationShouldNotChangeRefferedLayoutObjectState) { + SetBodyContent( + "<div id='d1'>div1</div><div id='d2'>foo<span>bar</span>baz</div>"); + Node* span = GetDocument().QuerySelector("span"); + Selection().SetSelection( + SelectionInDOMTree::Builder() + .SetBaseAndExtent(Position(span->firstChild(), 0), + Position(span->firstChild(), 3)) + .Build()); + Selection().CommitAppearanceIfNeeded(); + TEST_NEXT(&LayoutObject::IsLayoutBlock, SelectionState::kStartAndEnd); + TEST_NEXT(&LayoutObject::IsLayoutBlockFlow, SelectionState::kNone); + TEST_NEXT("div1", SelectionState::kNone); + TEST_NEXT(&LayoutObject::IsLayoutBlockFlow, SelectionState::kStartAndEnd); + TEST_NEXT("foo", SelectionState::kNone); + TEST_NEXT(&LayoutObject::IsLayoutInline, SelectionState::kNone); + TEST_NEXT("bar", SelectionState::kStartAndEnd); + TEST_NEXT("baz", SelectionState::kNone); + TEST_NO_NEXT_LAYOUT_OBJECT(); + + Node* d1 = GetDocument().QuerySelector("#d1"); + Node* d2 = GetDocument().QuerySelector("#d2"); + Selection().SetSelection( + SelectionInDOMTree::Builder() + .SetBaseAndExtent(Position(d1, 0), Position(d2, 0)) + .Build()); + // This commit should not crash. + Selection().CommitAppearanceIfNeeded(); + Reset(); + TEST_NEXT(&LayoutObject::IsLayoutBlock, SelectionState::kEnd); + TEST_NEXT(&LayoutObject::IsLayoutBlockFlow, SelectionState::kStart); + TEST_NEXT("div1", SelectionState::kStart); + TEST_NEXT(&LayoutObject::IsLayoutBlockFlow, SelectionState::kEnd); + TEST_NEXT("foo", SelectionState::kNone); + TEST_NEXT(&LayoutObject::IsLayoutInline, SelectionState::kNone); + // TODO(yoichio) : Introduce enum class InvalidateOption and confirm + // "bar" is SelectionState::kNone and ShouldInvalidation. + // TEST_NEXT("bar", SelectionState::kNone); + // TEST_NEXT("baz", SelectionState::kNone); + // TEST_NO_NEXT_LAYOUT_OBJECT(); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/RenderedPosition.cpp b/third_party/WebKit/Source/core/editing/RenderedPosition.cpp index db3e2f2..d84876e 100644 --- a/third_party/WebKit/Source/core/editing/RenderedPosition.cpp +++ b/third_party/WebKit/Source/core/editing/RenderedPosition.cpp
@@ -34,6 +34,7 @@ #include "core/editing/TextAffinity.h" #include "core/editing/VisiblePosition.h" #include "core/editing/VisibleUnits.h" +#include "core/html/TextControlElement.h" #include "core/layout/api/LineLayoutAPIShim.h" #include "core/layout/compositing/CompositedSelectionBound.h" #include "core/paint/PaintLayer.h" @@ -292,6 +293,33 @@ return container_point; } +void RenderedPosition::GetLocalSelectionEndpoints( + bool selection_start, + LayoutPoint& edge_top_in_layer, + LayoutPoint& edge_bottom_in_layer, + bool& is_text_direction_rtl) const { + const LayoutRect rect = layout_object_->LocalCaretRect(inline_box_, offset_); + if (layout_object_->Style()->IsHorizontalWritingMode()) { + edge_top_in_layer = rect.MinXMinYCorner(); + edge_bottom_in_layer = rect.MinXMaxYCorner(); + return; + } + edge_top_in_layer = rect.MinXMinYCorner(); + edge_bottom_in_layer = rect.MaxXMinYCorner(); + + // When text is vertical, it looks better for the start handle baseline to + // be at the starting edge, to enclose the selection fully between the + // handles. + if (selection_start) { + LayoutUnit x_swap = edge_bottom_in_layer.X(); + edge_bottom_in_layer.SetX(edge_top_in_layer.X()); + edge_top_in_layer.SetX(x_swap); + } + + // Flipped blocks writing mode is not only vertical but also right to left. + is_text_direction_rtl = layout_object_->HasFlippedBlocksWritingMode(); +} + void RenderedPosition::PositionInGraphicsLayerBacking( CompositedSelectionBound& bound, bool selection_start) const { @@ -301,30 +329,48 @@ if (IsNull()) return; - LayoutRect rect = layout_object_->LocalCaretRect(inline_box_, offset_); - if (layout_object_->Style()->IsHorizontalWritingMode()) { - bound.edge_top_in_layer = - LocalToInvalidationBackingPoint(rect.MinXMinYCorner(), &bound.layer); - bound.edge_bottom_in_layer = - LocalToInvalidationBackingPoint(rect.MinXMaxYCorner(), nullptr); - } else { - bound.edge_top_in_layer = - LocalToInvalidationBackingPoint(rect.MinXMinYCorner(), &bound.layer); - bound.edge_bottom_in_layer = - LocalToInvalidationBackingPoint(rect.MaxXMinYCorner(), nullptr); + LayoutPoint edge_top_in_layer; + LayoutPoint edge_bottom_in_layer; + GetLocalSelectionEndpoints(selection_start, edge_top_in_layer, + edge_bottom_in_layer, bound.is_text_direction_rtl); - // When text is vertical, it looks better for the start handle baseline to - // be at the starting edge, to enclose the selection fully between the - // handles. - if (selection_start) { - float x_swap = bound.edge_bottom_in_layer.X(); - bound.edge_bottom_in_layer.SetX(bound.edge_top_in_layer.X()); - bound.edge_top_in_layer.SetX(x_swap); - } + bound.edge_top_in_layer = + LocalToInvalidationBackingPoint(edge_top_in_layer, &bound.layer); + bound.edge_bottom_in_layer = + LocalToInvalidationBackingPoint(edge_bottom_in_layer, nullptr); +} - // Flipped blocks writing mode is not only vertical but also right to left. - bound.is_text_direction_rtl = layout_object_->HasFlippedBlocksWritingMode(); - } +bool RenderedPosition::IsVisible(bool selection_start) { + if (IsNull()) + return false; + + Node* node = layout_object_->GetNode(); + if (!node) + return true; + TextControlElement* text_control = EnclosingTextControl(node); + if (!text_control) + return true; + if (!isHTMLInputElement(text_control)) + return true; + + LayoutObject* layout_object = text_control->GetLayoutObject(); + if (!layout_object || !layout_object->IsBox()) + return true; + + LayoutPoint edge_top_in_layer; + LayoutPoint ignored1; + bool ignored2; + GetLocalSelectionEndpoints(selection_start, edge_top_in_layer, ignored1, + ignored2); + + LayoutBox* text_control_object = ToLayoutBox(layout_object); + LayoutPoint position_in_input(layout_object_->LocalToAncestorPoint( + FloatPoint(edge_top_in_layer), text_control_object, + kTraverseDocumentBoundaries)); + if (!text_control_object->BorderBoxRect().Contains(position_in_input)) + return false; + + return true; } bool LayoutObjectContainsPosition(LayoutObject* target,
diff --git a/third_party/WebKit/Source/core/editing/RenderedPosition.h b/third_party/WebKit/Source/core/editing/RenderedPosition.h index f5227b0..909a4da5 100644 --- a/third_party/WebKit/Source/core/editing/RenderedPosition.h +++ b/third_party/WebKit/Source/core/editing/RenderedPosition.h
@@ -44,7 +44,7 @@ class LayoutObject; struct CompositedSelectionBound; -class RenderedPosition { +class CORE_EXPORT RenderedPosition { STACK_ALLOCATED(); public: @@ -70,8 +70,8 @@ bool AtRightBoundaryOfBidiRun() const { return AtRightBoundaryOfBidiRun(kIgnoreBidiLevel, 0); } - // The following two functions return true only if the current position is at - // the end of the bidi run of the specified bidi embedding level. + // The following two functions return true only if the current position is + // at the end of the bidi run of the specified bidi embedding level. bool AtLeftBoundaryOfBidiRun(unsigned char bidi_level_of_run) const { return AtLeftBoundaryOfBidiRun(kMatchBidiLevel, bidi_level_of_run); } @@ -87,6 +87,10 @@ void PositionInGraphicsLayerBacking(CompositedSelectionBound&, bool selection_start) const; + // Returns whether this position is not visible on the screen (because + // clipped out). + bool IsVisible(bool selection_start); + private: bool operator==(const RenderedPosition&) const { return false; } explicit RenderedPosition(LayoutObject*, InlineBox*, int offset); @@ -104,6 +108,11 @@ bool AtRightBoundaryOfBidiRun(ShouldMatchBidiLevel, unsigned char bidi_level_of_run) const; + void GetLocalSelectionEndpoints(bool selection_start, + LayoutPoint& edge_top_in_layer, + LayoutPoint& edge_bottom_in_layer, + bool& is_text_direction_rtl) const; + FloatPoint LocalToInvalidationBackingPoint( const LayoutPoint& local_point, GraphicsLayer** graphics_layer_backing) const;
diff --git a/third_party/WebKit/Source/core/editing/RenderedPositionTest.cpp b/third_party/WebKit/Source/core/editing/RenderedPositionTest.cpp new file mode 100644 index 0000000..960cf2fc --- /dev/null +++ b/third_party/WebKit/Source/core/editing/RenderedPositionTest.cpp
@@ -0,0 +1,43 @@ +// 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 "core/editing/RenderedPosition.h" + +#include "build/build_config.h" +#include "core/css/CSSStyleDeclaration.h" +#include "core/editing/EditingTestBase.h" +#include "core/editing/VisibleUnits.h" + +namespace blink { + +class RenderedPositionTest : public EditingTestBase {}; + +#if defined(OS_ANDROID) +// Failing on WebKit Android (Nexus4): https://crbug.com/752827 +#define MAYBE_IsVisible DISABLED_IsVisible +#else +#define MAYBE_IsVisible IsVisible +#endif +TEST_F(RenderedPositionTest, MAYBE_IsVisible) { + SetBodyContent( + "<input id=target width=100 value='test test test test test tes tes test'" + " style='will-change: transform; font-size:40pt;'/>"); + + Element* target = GetDocument().getElementById("target"); + Position visible_position( + target->GetLayoutObject()->SlowFirstChild()->SlowFirstChild()->GetNode(), + 0); + RenderedPosition rendered_visible_position( + CreateVisiblePosition(visible_position)); + EXPECT_TRUE(rendered_visible_position.IsVisible(true)); + + Position hidden_position( + target->GetLayoutObject()->SlowFirstChild()->SlowFirstChild()->GetNode(), + 32); + RenderedPosition rendered_hidden_position( + CreateVisiblePosition(hidden_position)); + EXPECT_FALSE(rendered_hidden_position.IsVisible(true)); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/SelectionController.cpp b/third_party/WebKit/Source/core/editing/SelectionController.cpp index c0058dc2..5afa6216 100644 --- a/third_party/WebKit/Source/core/editing/SelectionController.cpp +++ b/third_party/WebKit/Source/core/editing/SelectionController.cpp
@@ -485,20 +485,21 @@ !target_node->GetLayoutObject()->IsSelectable()) return false; - // TODO(editing-dev): We should compute visible selection after dispatching - // "selectstart", once we have |SelectionInFlatTree::IsValidFor()|. - const VisibleSelectionInFlatTree& visible_selection = - CreateVisibleSelection(selection); - - if (DispatchSelectStart(target_node) != DispatchEventResult::kNotCanceled) - return false; + { + SelectionInFlatTree::InvalidSelectionResetter resetter(selection); + if (DispatchSelectStart(target_node) != DispatchEventResult::kNotCanceled) + return false; + } // |dispatchSelectStart()| can change document hosted by |m_frame|. if (!this->Selection().IsAvailable()) return false; - if (!visible_selection.IsValidFor(this->Selection().GetDocument())) - return false; + // TODO(editing-dev): Use of updateStyleAndLayoutIgnorePendingStylesheets + // needs to be audited. See http://crbug.com/590369 for more details. + GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets(); + const VisibleSelectionInFlatTree& visible_selection = + CreateVisibleSelection(selection); if (visible_selection.IsRange()) { selection_state_ = SelectionState::kExtendedSelection;
diff --git a/third_party/WebKit/Source/core/editing/SelectionTemplate.cpp b/third_party/WebKit/Source/core/editing/SelectionTemplate.cpp index 97e695b6..51dd4517 100644 --- a/third_party/WebKit/Source/core/editing/SelectionTemplate.cpp +++ b/third_party/WebKit/Source/core/editing/SelectionTemplate.cpp
@@ -85,6 +85,17 @@ } template <typename Strategy> +bool SelectionTemplate<Strategy>::IsValidFor(const Document& document) const { + if (IsNone()) + return true; + if (base_.GetDocument() != document) + return false; + if (extent_.GetDocument() != document) + return false; + return !base_.IsOrphan() && !extent_.IsOrphan(); +} + +template <typename Strategy> bool SelectionTemplate<Strategy>::AssertValidFor( const Document& document) const { if (!AssertValid()) @@ -329,6 +340,37 @@ return *this; } +// --- + +template <typename Strategy> +SelectionTemplate<Strategy>::InvalidSelectionResetter::InvalidSelectionResetter( + const SelectionTemplate<Strategy>& selection) + : document_(selection.GetDocument()), + selection_(const_cast<SelectionTemplate&>(selection)) { + DCHECK(selection_.AssertValid()); +} + +template <typename Strategy> +SelectionTemplate< + Strategy>::InvalidSelectionResetter::~InvalidSelectionResetter() { + if (selection_.IsNone()) + return; + DCHECK(document_); + if (!selection_.IsValidFor(*document_)) { + selection_ = SelectionTemplate<Strategy>(); + return; + } +#if DCHECK_IS_ON() + selection_.dom_tree_version_ = document_->DomTreeVersion(); +#endif + selection_.ResetDirectionCache(); +} + +template <typename Strategy> +DEFINE_TRACE(SelectionTemplate<Strategy>::InvalidSelectionResetter) { + visitor->Trace(document_); +} + template class CORE_TEMPLATE_EXPORT SelectionTemplate<EditingStrategy>; template class CORE_TEMPLATE_EXPORT SelectionTemplate<EditingInFlatTreeStrategy>;
diff --git a/third_party/WebKit/Source/core/editing/SelectionTemplate.h b/third_party/WebKit/Source/core/editing/SelectionTemplate.h index b5288c6..8273120a 100644 --- a/third_party/WebKit/Source/core/editing/SelectionTemplate.h +++ b/third_party/WebKit/Source/core/editing/SelectionTemplate.h
@@ -19,7 +19,8 @@ // SelectionTemplate is used for representing a selection in DOM tree or Flat // tree with template parameter |Strategy|. Instances of |SelectionTemplate| -// are immutable objects, you can't change them once constructed. +// are "virtually" immutable objects, we change |SelectionTemplate| by copying +// in |SelectionEdtior| and |InvalidSelectionResetter|. // // To construct |SelectionTemplate| object, please use |Builder| class. template <typename Strategy> @@ -71,6 +72,24 @@ DISALLOW_COPY_AND_ASSIGN(Builder); }; + // Resets selection at end of life time of the object when base and extent + // are disconnected or moved to another document. + class InvalidSelectionResetter final { + DISALLOW_NEW(); + + public: + explicit InvalidSelectionResetter(const SelectionTemplate&); + ~InvalidSelectionResetter(); + + DECLARE_TRACE(); + + private: + const Member<const Document> document_; + SelectionTemplate& selection_; + + DISALLOW_COPY_AND_ASSIGN(InvalidSelectionResetter); + }; + SelectionTemplate(const SelectionTemplate& other); SelectionTemplate(); @@ -116,6 +135,7 @@ }; Document* GetDocument() const; + bool IsValidFor(const Document&) const; void ResetDirectionCache() const; PositionTemplate<Strategy> base_;
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp index d273e19e..737eee43 100644 --- a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp +++ b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
@@ -1122,62 +1122,9 @@ // TODO(yosin): We should use |associatedLayoutObjectOf()| in "VisibleUnits.cpp" // where it takes |LayoutObject| from |Position|. -// Note about ::first-letter pseudo-element: -// When an element has ::first-letter pseudo-element, first letter characters -// are taken from |Text| node and first letter characters are considered -// as content of <pseudo:first-letter>. -// For following HTML, -// <style>div::first-letter {color: red}</style> -// <div>abc</div> -// we have following layout tree: -// LayoutBlockFlow {DIV} at (0,0) size 784x55 -// LayoutInline {<pseudo:first-letter>} at (0,0) size 22x53 -// LayoutTextFragment (anonymous) at (0,1) size 22x53 -// text run at (0,1) width 22: "a" -// LayoutTextFragment {#text} at (21,30) size 16x17 -// text run at (21,30) width 16: "bc" -// In this case, |Text::layoutObject()| for "abc" returns |LayoutTextFragment| -// containing "bc", and it is called remaining part. -// -// Even if |Text| node contains only first-letter characters, e.g. just "a", -// remaining part of |LayoutTextFragment|, with |fragmentLength()| == 0, is -// appeared in layout tree. -// -// When |Text| node contains only first-letter characters and whitespaces, e.g. -// "B\n", associated |LayoutTextFragment| is first-letter part instead of -// remaining part. -// -// Punctuation characters are considered as first-letter. For "(1)ab", -// "(1)" are first-letter part and "ab" are remaining part. -LayoutObject* AssociatedLayoutObjectOf(const Node& node, int offset_in_node) { - DCHECK_GE(offset_in_node, 0); - LayoutObject* layout_object = node.GetLayoutObject(); - if (!node.IsTextNode() || !layout_object || - !ToLayoutText(layout_object)->IsTextFragment()) - return layout_object; - LayoutTextFragment* layout_text_fragment = - ToLayoutTextFragment(layout_object); - if (!layout_text_fragment->IsRemainingTextLayoutObject()) { - DCHECK_LE( - static_cast<unsigned>(offset_in_node), - layout_text_fragment->Start() + layout_text_fragment->FragmentLength()); - return layout_text_fragment; - } - if (layout_text_fragment->FragmentLength() && - static_cast<unsigned>(offset_in_node) >= layout_text_fragment->Start()) - return layout_object; - LayoutObject* first_letter_layout_object = - layout_text_fragment->GetFirstLetterPseudoElement()->GetLayoutObject(); - // TODO(yosin): We're not sure when |firstLetterLayoutObject| has - // multiple child layout object. - LayoutObject* child = first_letter_layout_object->SlowFirstChild(); - CHECK(child && child->IsText()); - DCHECK_EQ(child, first_letter_layout_object->SlowLastChild()); - return child; -} int CaretMinOffset(const Node* node) { - LayoutObject* layout_object = AssociatedLayoutObjectOf(*node, 0); + const LayoutObject* layout_object = AssociatedLayoutObjectOf(*node, 0); return layout_object ? layout_object->CaretMinOffset() : 0; } @@ -1192,12 +1139,12 @@ return false; const int offset_in_node = position.ComputeEditingOffset(); - LayoutObject* layout_object = + const LayoutObject* layout_object = AssociatedLayoutObjectOf(*anchor_node, offset_in_node); if (!layout_object) return false; - LayoutText* text_layout_object = ToLayoutText(layout_object); + const LayoutText* text_layout_object = ToLayoutText(layout_object); const int text_offset = offset_in_node - text_layout_object->TextStartOffset(); for (InlineTextBox* box : InlineTextBoxesOf(*text_layout_object)) { @@ -1359,7 +1306,7 @@ return last_visible.DeprecatedComputePosition(); // skip position in non-laid out or invisible node - LayoutObject* const layout_object = + const LayoutObject* const layout_object = AssociatedLayoutObjectOf(*current_node, current_pos.OffsetInLeafNode()); if (!layout_object || layout_object->Style()->Visibility() != EVisibility::kVisible) @@ -1393,7 +1340,7 @@ // return current position if it is in laid out text if (!layout_object->IsText()) continue; - LayoutText* const text_layout_object = ToLayoutText(layout_object); + const LayoutText* const text_layout_object = ToLayoutText(layout_object); if (!text_layout_object->FirstTextBox()) continue; const unsigned text_start_offset = text_layout_object->TextStartOffset(); @@ -1568,7 +1515,7 @@ return last_visible.DeprecatedComputePosition(); // skip position in non-laid out or invisible node - LayoutObject* const layout_object = + const LayoutObject* const layout_object = AssociatedLayoutObjectOf(*current_node, current_pos.OffsetInLeafNode()); if (!layout_object || layout_object->Style()->Visibility() != EVisibility::kVisible) @@ -1594,7 +1541,7 @@ // return current position if it is in laid out text if (!layout_object->IsText()) continue; - LayoutText* const text_layout_object = ToLayoutText(layout_object); + const LayoutText* const text_layout_object = ToLayoutText(layout_object); if (!text_layout_object->FirstTextBox()) continue; const unsigned text_start_offset = text_layout_object->TextStartOffset();
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.h b/third_party/WebKit/Source/core/editing/VisibleUnits.h index 15a8099..de97d1d 100644 --- a/third_party/WebKit/Source/core/editing/VisibleUnits.h +++ b/third_party/WebKit/Source/core/editing/VisibleUnits.h
@@ -84,9 +84,6 @@ // "core/editing/VisibleUnitsTest.cpp". std::ostream& operator<<(std::ostream&, const InlineBoxPosition&); -CORE_EXPORT LayoutObject* AssociatedLayoutObjectOf(const Node&, - int offset_in_node); - // offset functions on Node CORE_EXPORT int CaretMinOffset(const Node*); CORE_EXPORT int CaretMaxOffset(const Node*);
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnitsTest.cpp b/third_party/WebKit/Source/core/editing/VisibleUnitsTest.cpp index fb74c91a..5ae44d71 100644 --- a/third_party/WebKit/Source/core/editing/VisibleUnitsTest.cpp +++ b/third_party/WebKit/Source/core/editing/VisibleUnitsTest.cpp
@@ -81,78 +81,6 @@ EXPECT_EQ(bounds_in_dom_tree, bounds_in_flat_tree); } -TEST_F(VisibleUnitsTest, associatedLayoutObjectOfFirstLetterPunctuations) { - const char* body_content = - "<style>p:first-letter {color:red;}</style><p id=sample>(a)bc</p>"; - SetBodyContent(body_content); - - Node* sample = GetDocument().getElementById("sample"); - Node* text = sample->firstChild(); - - LayoutTextFragment* layout_object0 = - ToLayoutTextFragment(AssociatedLayoutObjectOf(*text, 0)); - EXPECT_FALSE(layout_object0->IsRemainingTextLayoutObject()); - - LayoutTextFragment* layout_object1 = - ToLayoutTextFragment(AssociatedLayoutObjectOf(*text, 1)); - EXPECT_EQ(layout_object0, layout_object1) - << "A character 'a' should be part of first letter."; - - LayoutTextFragment* layout_object2 = - ToLayoutTextFragment(AssociatedLayoutObjectOf(*text, 2)); - EXPECT_EQ(layout_object0, layout_object2) - << "close parenthesis should be part of first letter."; - - LayoutTextFragment* layout_object3 = - ToLayoutTextFragment(AssociatedLayoutObjectOf(*text, 3)); - EXPECT_TRUE(layout_object3->IsRemainingTextLayoutObject()); -} - -TEST_F(VisibleUnitsTest, associatedLayoutObjectOfFirstLetterSplit) { - V8TestingScope scope; - - const char* body_content = - "<style>p:first-letter {color:red;}</style><p id=sample>abc</p>"; - SetBodyContent(body_content); - - Node* sample = GetDocument().getElementById("sample"); - Node* first_letter = sample->firstChild(); - // Split "abc" into "a" "bc" - ToText(first_letter)->splitText(1, ASSERT_NO_EXCEPTION); - UpdateAllLifecyclePhases(); - - LayoutTextFragment* layout_object0 = - ToLayoutTextFragment(AssociatedLayoutObjectOf(*first_letter, 0)); - EXPECT_FALSE(layout_object0->IsRemainingTextLayoutObject()); - - LayoutTextFragment* layout_object1 = - ToLayoutTextFragment(AssociatedLayoutObjectOf(*first_letter, 1)); - EXPECT_EQ(layout_object0, layout_object1); -} - -TEST_F(VisibleUnitsTest, - associatedLayoutObjectOfFirstLetterWithTrailingWhitespace) { - const char* body_content = - "<style>div:first-letter {color:red;}</style><div id=sample>a\n " - "<div></div></div>"; - SetBodyContent(body_content); - - Node* sample = GetDocument().getElementById("sample"); - Node* text = sample->firstChild(); - - LayoutTextFragment* layout_object0 = - ToLayoutTextFragment(AssociatedLayoutObjectOf(*text, 0)); - EXPECT_FALSE(layout_object0->IsRemainingTextLayoutObject()); - - LayoutTextFragment* layout_object1 = - ToLayoutTextFragment(AssociatedLayoutObjectOf(*text, 1)); - EXPECT_TRUE(layout_object1->IsRemainingTextLayoutObject()); - - LayoutTextFragment* layout_object2 = - ToLayoutTextFragment(AssociatedLayoutObjectOf(*text, 2)); - EXPECT_EQ(layout_object1, layout_object2); -} - TEST_F(VisibleUnitsTest, caretMinOffset) { const char* body_content = "<p id=one>one</p>"; SetBodyContent(body_content);
diff --git a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp index af59ba9..3bbadee 100644 --- a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
@@ -2083,7 +2083,7 @@ // The term "visible" here includes a caret in editable text or a range in any // text. const VisibleSelection& selection = - frame.GetEditor().SelectionForCommand(event); + CreateVisibleSelection(frame.GetEditor().SelectionForCommand(event)); return (selection.IsCaret() && selection.IsContentEditable()) || selection.IsRange(); } @@ -2098,7 +2098,7 @@ return false; const VisibleSelection& selection = - frame.GetEditor().SelectionForCommand(event); + CreateVisibleSelection(frame.GetEditor().SelectionForCommand(event)); return ((selection.IsCaret() && selection.IsContentEditable()) || selection.IsRange()) && !frame.GetEditor().Mark().IsNone(); @@ -2113,7 +2113,7 @@ !frame.Selection().SelectionHasFocus()) return false; const VisibleSelection& selection = - frame.GetEditor().SelectionForCommand(event); + CreateVisibleSelection(frame.GetEditor().SelectionForCommand(event)); return selection.IsCaret() && selection.IsContentEditable(); } @@ -2142,7 +2142,10 @@ if (source == kCommandFromMenuOrKeyBinding && !frame.Selection().SelectionHasFocus()) return false; - return frame.GetEditor().SelectionForCommand(event).RootEditableElement(); + const SelectionInDOMTree selection = + frame.GetEditor().SelectionForCommand(event); + return RootEditableElementOf( + CreateVisiblePosition(selection.Base()).DeepEquivalent()); } static bool EnabledDelete(LocalFrame& frame, @@ -2228,7 +2231,7 @@ // The term "visible" here includes a caret in editable text or a range in any // text. const VisibleSelection& selection = - frame.GetEditor().SelectionForCommand(event); + CreateVisibleSelection(frame.GetEditor().SelectionForCommand(event)); return (selection.IsCaret() && selection.IsContentEditable()) || selection.IsRange(); }
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertIncrementalTextCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertIncrementalTextCommand.cpp index b3d9c57..408abd7 100644 --- a/third_party/WebKit/Source/core/editing/commands/InsertIncrementalTextCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/InsertIncrementalTextCommand.cpp
@@ -98,20 +98,16 @@ new_text.length() - common_prefix_length - common_suffix_length); } -VisibleSelection ComputeSelectionForInsertion( +SelectionInDOMTree ComputeSelectionForInsertion( const EphemeralRange& selection_range, const int offset, - const int length, - const bool is_directional) { + const int length) { CharacterIterator char_it(selection_range); const EphemeralRange& range_for_insertion = char_it.CalculateCharacterSubrange(offset, length); - const VisibleSelection& selection = - CreateVisibleSelection(SelectionInDOMTree::Builder() - .SetBaseAndExtent(range_for_insertion) - .SetIsDirectional(is_directional) - .Build()); - return selection; + return SelectionInDOMTree::Builder() + .SetBaseAndExtent(range_for_insertion) + .Build(); } } // anonymous namespace @@ -158,9 +154,8 @@ const int offset = static_cast<int>(common_prefix_length); const int length = static_cast<int>(old_text_length - common_prefix_length - common_suffix_length); - const VisibleSelection& selection_for_insertion = - ComputeSelectionForInsertion(selection_range, offset, length, - EndingSelection().IsDirectional()); + const VisibleSelection& selection_for_insertion = CreateVisibleSelection( + ComputeSelectionForInsertion(selection_range, offset, length)); SetEndingSelectionWithoutValidation(selection_for_insertion.Start(), selection_for_insertion.End());
diff --git a/third_party/WebKit/Source/core/events/Event.cpp b/third_party/WebKit/Source/core/events/Event.cpp index 18fc718..88c776a3 100644 --- a/third_party/WebKit/Source/core/events/Event.cpp +++ b/third_party/WebKit/Source/core/events/Event.cpp
@@ -272,8 +272,10 @@ } } -HeapVector<Member<EventTarget>> Event::path(ScriptState* script_state) const { - return PathInternal(script_state, kNonEmptyAfterDispatch); +ScriptValue Event::path(ScriptState* script_state) const { + return ScriptValue( + script_state, + ToV8(PathInternal(script_state, kNonEmptyAfterDispatch), script_state)); } HeapVector<Member<EventTarget>> Event::composedPath(
diff --git a/third_party/WebKit/Source/core/events/Event.h b/third_party/WebKit/Source/core/events/Event.h index 046a341..691b1a4 100644 --- a/third_party/WebKit/Source/core/events/Event.h +++ b/third_party/WebKit/Source/core/events/Event.h
@@ -210,7 +210,7 @@ } void InitEventPath(Node&); - HeapVector<Member<EventTarget>> path(ScriptState*) const; + ScriptValue path(ScriptState*) const; HeapVector<Member<EventTarget>> composedPath(ScriptState*) const; bool IsBeingDispatched() const { return eventPhase(); }
diff --git a/third_party/WebKit/Source/core/events/Event.idl b/third_party/WebKit/Source/core/events/Event.idl index 148b35a..b2115a2 100644 --- a/third_party/WebKit/Source/core/events/Event.idl +++ b/third_party/WebKit/Source/core/events/Event.idl
@@ -55,5 +55,5 @@ [MeasureAs=EventSrcElement] readonly attribute EventTarget srcElement; [MeasureAs=EventReturnValue, CallWith=ScriptState, ImplementedAs=legacyReturnValue] attribute boolean returnValue; [MeasureAs=EventCancelBubble, CallWith=ScriptState] attribute boolean cancelBubble; - [MeasureAs=EventPath, CallWith=ScriptState] readonly attribute EventTarget[] path; + [MeasureAs=EventPath, CallWith=ScriptState] readonly attribute object path; };
diff --git a/third_party/WebKit/Source/core/exported/BUILD.gn b/third_party/WebKit/Source/core/exported/BUILD.gn index a658fd7..fdd95e39 100644 --- a/third_party/WebKit/Source/core/exported/BUILD.gn +++ b/third_party/WebKit/Source/core/exported/BUILD.gn
@@ -89,8 +89,6 @@ "WebTextCheckingResult.cpp", "WebUserGestureIndicator.cpp", "WebUserGestureToken.cpp", - "WebViewBase.cpp", - "WebViewBase.h", "WebViewImpl.cpp", "WebViewImpl.h", "WorkerShadowPage.cpp",
diff --git a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp index d1aad9f..975876e 100644 --- a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp +++ b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp
@@ -46,7 +46,7 @@ #include "core/exported/WebDevToolsFrontendImpl.h" #include "core/exported/WebDocumentLoaderImpl.h" #include "core/exported/WebPluginContainerImpl.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalFrameView.h" #include "core/frame/Settings.h" #include "core/frame/WebLocalFrameImpl.h" @@ -468,7 +468,7 @@ } static bool AllowCreatingBackgroundTabs() { - const WebInputEvent* input_event = WebViewBase::CurrentInputEvent(); + const WebInputEvent* input_event = WebViewImpl::CurrentInputEvent(); if (!input_event || (input_event->GetType() != WebInputEvent::kMouseUp && (input_event->GetType() != WebInputEvent::kRawKeyDown && input_event->GetType() != WebInputEvent::kKeyDown) && @@ -654,7 +654,7 @@ } bool LocalFrameClientImpl::NavigateBackForward(int offset) const { - WebViewBase* webview = web_frame_->ViewImpl(); + WebViewImpl* webview = web_frame_->ViewImpl(); if (!webview->Client()) return false; @@ -963,7 +963,7 @@ } unsigned LocalFrameClientImpl::BackForwardLength() { - WebViewBase* webview = web_frame_->ViewImpl(); + WebViewImpl* webview = web_frame_->ViewImpl(); if (!webview || !webview->Client()) return 0; return webview->Client()->HistoryBackListCount() + 1 +
diff --git a/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp b/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp index 65bb2d05..38068ab0 100644 --- a/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp +++ b/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp
@@ -39,7 +39,7 @@ #include "core/CoreProbeSink.h" #include "core/events/WebInputEventConversion.h" #include "core/exported/WebSettingsImpl.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalFrame.h" #include "core/frame/LocalFrameView.h" #include "core/frame/Settings.h" @@ -162,7 +162,7 @@ // 1. Disable input events. WebFrameWidgetBase::SetIgnoreInputEvents(true); - for (const auto view : WebViewBase::AllInstances()) + for (const auto view : WebViewImpl::AllInstances()) view->GetChromeClient().NotifyPopupOpeningObservers(); // 2. Notify embedder about pausing. @@ -236,7 +236,7 @@ return agent; } - WebViewBase* view = frame->ViewImpl(); + WebViewImpl* view = frame->ViewImpl(); WebDevToolsAgentImpl* agent = new WebDevToolsAgentImpl(frame, client, true); agent->LayerTreeViewChanged(view->LayerTreeView()); return agent;
diff --git a/third_party/WebKit/Source/core/exported/WebFrameTest.cpp b/third_party/WebKit/Source/core/exported/WebFrameTest.cpp index d0dd0658..0e18f8f 100644 --- a/third_party/WebKit/Source/core/exported/WebFrameTest.cpp +++ b/third_party/WebKit/Source/core/exported/WebFrameTest.cpp
@@ -6038,14 +6038,27 @@ .As<v8::Int32>() ->Value(); - const IntPoint hit_point = - IntPoint((start_edge_top_in_layer_x + start_edge_bottom_in_layer_x + - end_edge_top_in_layer_x + end_edge_bottom_in_layer_x) / - 4, - (start_edge_top_in_layer_y + start_edge_bottom_in_layer_y + - end_edge_top_in_layer_y + end_edge_bottom_in_layer_y) / - 4 + - 3); + IntPoint hit_point; + + if (expected_result.Length() >= 17) { + hit_point = IntPoint(expected_result.Get(context, 15) + .ToLocalChecked() + .As<v8::Int32>() + ->Value(), + expected_result.Get(context, 16) + .ToLocalChecked() + .As<v8::Int32>() + ->Value()); + } else { + hit_point = + IntPoint((start_edge_top_in_layer_x + start_edge_bottom_in_layer_x + + end_edge_top_in_layer_x + end_edge_bottom_in_layer_x) / + 4, + (start_edge_top_in_layer_y + start_edge_bottom_in_layer_y + + end_edge_top_in_layer_y + end_edge_bottom_in_layer_y) / + 4 + + 3); + } WebGestureEvent gesture_event(WebInputEvent::kGestureTap, WebInputEvent::kNoModifiers, @@ -6118,11 +6131,26 @@ .As<v8::Int32>() ->Value(); } + int y_bottom_deviation = start_edge_bottom_in_layer_y - select_start->edge_bottom_in_layer.y; EXPECT_GE(y_bottom_epsilon, std::abs(y_bottom_deviation)); EXPECT_EQ(y_bottom_deviation, end_edge_bottom_in_layer_y - select_end->edge_bottom_in_layer.y); + + if (expected_result.Length() >= 15) { + bool start_hidden = expected_result.Get(context, 13) + .ToLocalChecked() + .As<v8::Boolean>() + ->Value(); + bool end_hidden = expected_result.Get(context, 14) + .ToLocalChecked() + .As<v8::Boolean>() + ->Value(); + + EXPECT_EQ(start_hidden, select_start->hidden); + EXPECT_EQ(end_hidden, select_end->hidden); + } } void RunTestWithMultipleFiles(const char* test_file, ...) { @@ -6178,6 +6206,16 @@ TEST_P(CompositedSelectionBoundsTest, EditableDiv) { RunTest("composited_selection_bounds_editable_div.html"); } +#if defined(OS_LINUX) +#if !defined(OS_ANDROID) +TEST_P(CompositedSelectionBoundsTest, Input) { + RunTest("composited_selection_bounds_input.html"); +} +TEST_P(CompositedSelectionBoundsTest, InputScrolled) { + RunTest("composited_selection_bounds_input_scrolled.html"); +} +#endif +#endif class DisambiguationPopupTestWebViewClient : public FrameTestHelpers::TestWebViewClient { @@ -12109,6 +12147,37 @@ EXPECT_EQ(frame.GetMenuData().selected_text, " "); } +TEST_P(ParameterizedWebFrameTest, ContextMenuDataPasswordSelectedText) { + ContextMenuWebFrameClient frame; + FrameTestHelpers::WebViewHelper web_view_helper; + WebViewImpl* web_view = web_view_helper.Initialize(&frame); + const std::string& html = "<input type='password' value='password'>"; + FrameTestHelpers::LoadHTMLString(web_view->MainFrameImpl(), html, + ToKURL("about:blank")); + web_view->Resize(WebSize(500, 300)); + web_view->UpdateAllLifecyclePhases(); + RunPendingTasks(); + web_view->SetInitialFocus(false); + RunPendingTasks(); + + web_view->MainFrameImpl()->ExecuteCommand(WebString::FromUTF8("SelectAll")); + + WebMouseEvent mouse_event(WebInputEvent::kMouseDown, + WebInputEvent::kNoModifiers, + WebInputEvent::kTimeStampForTesting); + + mouse_event.button = WebMouseEvent::Button::kRight; + mouse_event.SetPositionInWidget(8, 8); + mouse_event.click_count = 1; + web_view->HandleInputEvent(WebCoalescedInputEvent(mouse_event)); + + RunPendingTasks(); + web_view_helper.Reset(); + EXPECT_EQ(frame.GetMenuData().input_field_type, + blink::WebContextMenuData::kInputFieldTypePassword); + EXPECT_FALSE(frame.GetMenuData().selected_text.IsEmpty()); +} + TEST_P(ParameterizedWebFrameTest, LocalFrameWithRemoteParentIsTransparent) { FrameTestHelpers::WebViewHelper helper; helper.InitializeRemote();
diff --git a/third_party/WebKit/Source/core/exported/WebPluginContainerImpl.cpp b/third_party/WebKit/Source/core/exported/WebPluginContainerImpl.cpp index c46a77ca..e79abb2 100644 --- a/third_party/WebKit/Source/core/exported/WebPluginContainerImpl.cpp +++ b/third_party/WebKit/Source/core/exported/WebPluginContainerImpl.cpp
@@ -873,6 +873,14 @@ return; } } + // Invoke "PasteAndMatchStyle" using Ctrl + Shift + V to paste as plain + // text. + if (input_modifiers == (kEditingModifier | WebInputEvent::kShiftKey) && + web_event.windows_key_code == VKEY_V && web_plugin_->CanEditText() && + ExecuteEditCommand("PasteAndMatchStyle", "")) { + event->SetDefaultHandled(); + return; + } } // Give the client a chance to issue edit comamnds.
diff --git a/third_party/WebKit/Source/core/exported/WebPluginContainerTest.cpp b/third_party/WebKit/Source/core/exported/WebPluginContainerTest.cpp index 189dce59..1da44c3 100644 --- a/third_party/WebKit/Source/core/exported/WebPluginContainerTest.cpp +++ b/third_party/WebKit/Source/core/exported/WebPluginContainerTest.cpp
@@ -153,7 +153,7 @@ cut_called_ = true; return true; } - if (name == "Paste") { + if (name == "Paste" || name == "PasteAndMatchStyle") { paste_called_ = true; return true; } @@ -565,7 +565,7 @@ // Use TestPluginWithEditableText for testing "Paste". plugin_web_frame_client.SetHasEditableText(true); - WebViewBase* web_view = web_view_helper.InitializeAndLoad( + WebViewImpl* web_view = web_view_helper.InitializeAndLoad( base_url_ + "plugin_container.html", &plugin_web_frame_client); EnablePlugins(web_view, WebSize(300, 300)); @@ -607,6 +607,46 @@ EXPECT_TRUE(test_plugin->IsPasteCalled()); } +// Verifies |Ctrl-Shift-V| keyboard event results in the "PasteAndMatchStyle" +// command being invoked. +TEST_F(WebPluginContainerTest, PasteAndMatchStyleKeyboardEventsTest) { + RegisterMockedURL("plugin_container.html"); + // Must outlive |web_view_helper|. + TestPluginWebFrameClient plugin_web_frame_client; + FrameTestHelpers::WebViewHelper web_view_helper; + + // Use TestPluginWithEditableText for testing "PasteAndMatchStyle". + plugin_web_frame_client.SetHasEditableText(true); + + WebViewImpl* web_view = web_view_helper.InitializeAndLoad( + base_url_ + "plugin_container.html", &plugin_web_frame_client); + EnablePlugins(web_view, WebSize(300, 300)); + + WebElement plugin_container_one_element = + web_view->MainFrameImpl()->GetDocument().GetElementById( + WebString::FromUTF8("translated-plugin")); + + WebPlugin* plugin = + ToWebPluginContainerImpl(plugin_container_one_element.PluginContainer()) + ->Plugin(); + TestPluginWithEditableText* test_plugin = + static_cast<TestPluginWithEditableText*>(plugin); + + WebInputEvent::Modifiers modifier_key = static_cast<WebInputEvent::Modifiers>( + WebInputEvent::kControlKey | WebInputEvent::kShiftKey | + WebInputEvent::kNumLockOn | WebInputEvent::kIsLeft); +#if defined(OS_MACOSX) + modifier_key = static_cast<WebInputEvent::Modifiers>( + WebInputEvent::kMetaKey | WebInputEvent::kShiftKey | + WebInputEvent::kNumLockOn | WebInputEvent::kIsLeft); +#endif + CreateAndHandleKeyboardEvent(&plugin_container_one_element, modifier_key, + VKEY_V); + + // Check that "PasteAndMatchStyle" command is invoked. + EXPECT_TRUE(test_plugin->IsPasteCalled()); +} + // A class to facilitate testing that events are correctly received by plugins. class EventTestPlugin : public FakeWebPlugin { public:
diff --git a/third_party/WebKit/Source/core/exported/WebSelection.cpp b/third_party/WebKit/Source/core/exported/WebSelection.cpp index 1992cd9..26654fe 100644 --- a/third_party/WebKit/Source/core/exported/WebSelection.cpp +++ b/third_party/WebKit/Source/core/exported/WebSelection.cpp
@@ -33,6 +33,7 @@ result.edge_top_in_layer = RoundedIntPoint(bound.edge_top_in_layer); result.edge_bottom_in_layer = RoundedIntPoint(bound.edge_bottom_in_layer); result.is_text_direction_rtl = bound.is_text_direction_rtl; + result.hidden = bound.hidden; return result; }
diff --git a/third_party/WebKit/Source/core/exported/WebViewBase.cpp b/third_party/WebKit/Source/core/exported/WebViewBase.cpp deleted file mode 100644 index 14b1160..0000000 --- a/third_party/WebKit/Source/core/exported/WebViewBase.cpp +++ /dev/null
@@ -1,56 +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 "core/exported/WebViewBase.h" - -#include <memory> - -#include "core/page/ScopedPageSuspender.h" -#include "platform/wtf/HashSet.h" -#include "platform/wtf/StdLibExtras.h" -#include "platform/wtf/Vector.h" - -namespace blink { - -const WebInputEvent* WebViewBase::current_input_event_ = nullptr; - -const WebInputEvent* WebViewBase::CurrentInputEvent() { - return current_input_event_; -} - -// Used to defer all page activity in cases where the embedder wishes to run -// a nested event loop. Using a stack enables nesting of message loop -// invocations. -static Vector<std::unique_ptr<ScopedPageSuspender>>& PageSuspenderStack() { - DEFINE_STATIC_LOCAL(Vector<std::unique_ptr<ScopedPageSuspender>>, - suspender_stack, ()); - return suspender_stack; -} - -void WebView::WillEnterModalLoop() { - PageSuspenderStack().push_back(WTF::MakeUnique<ScopedPageSuspender>()); -} - -void WebView::DidExitModalLoop() { - DCHECK(PageSuspenderStack().size()); - PageSuspenderStack().pop_back(); -} - -// static -HashSet<WebViewBase*>& WebViewBase::AllInstances() { - DEFINE_STATIC_LOCAL(HashSet<WebViewBase*>, all_instances, ()); - return all_instances; -} - -static bool g_should_use_external_popup_menus = false; - -void WebView::SetUseExternalPopupMenus(bool use_external_popup_menus) { - g_should_use_external_popup_menus = use_external_popup_menus; -} - -bool WebViewBase::UseExternalPopupMenus() { - return g_should_use_external_popup_menus; -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/core/exported/WebViewBase.h b/third_party/WebKit/Source/core/exported/WebViewBase.h deleted file mode 100644 index 3477d205..0000000 --- a/third_party/WebKit/Source/core/exported/WebViewBase.h +++ /dev/null
@@ -1,231 +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.#ifndef WebViewBase_h - -#ifndef WebViewBase_h -#define WebViewBase_h - -#include "core/CoreExport.h" -#include "core/page/EventWithHitTestResults.h" -#include "platform/graphics/paint/PaintImage.h" -#include "platform/transforms/TransformationMatrix.h" -#include "platform/wtf/RefCounted.h" -#include "public/platform/WebDisplayMode.h" -#include "public/platform/WebInputEventResult.h" -#include "public/web/WebElement.h" -#include "public/web/WebView.h" - -namespace blink { - -class BrowserControls; -class ChromeClient; -class CompositorAnimationHost; -class CompositorMutatorImpl; -class CompositorAnimationTimeline; -class ContextMenuProvider; -class DevToolsEmulator; -class Frame; -class GraphicsLayer; -class HitTestResult; -class LinkHighlightImpl; -class Page; -class PaintLayerCompositor; -class PagePopup; -class PagePopupClient; -class PageScaleConstraintsSet; -class WebInputEvent; -class WebInputMethodController; -class WebKeyboardEvent; -class WebLayer; -class WebLocalFrameImpl; -class WebLayerTreeView; -class WebPagePopupImpl; -class WebSettingsImpl; -struct WebRect; - -// WebViewBase is a temporary class introduced to decouple the defintion of -// WebViewImpl from the concrete implementation. It was not possible to move the -// defintion of these methods to WebView as we did not want to pollute the -// public API surface area. -// -// Once WebViewImpl is moved from web to core/exported then this class should be -// removed and clients can once again depend on WebViewImpl. -class WebViewBase : public WebView, public RefCounted<WebViewBase> { - public: - virtual ~WebViewBase() {} - - virtual void SetBaseBackgroundColor(WebColor) = 0; - virtual void SetBaseBackgroundColorOverride(WebColor) = 0; - virtual void ClearBaseBackgroundColorOverride() = 0; - virtual void SetBackgroundColorOverride(WebColor) = 0; - virtual void ClearBackgroundColorOverride() = 0; - virtual void SetZoomFactorOverride(float) = 0; - virtual void SetCompositorDeviceScaleFactorOverride(float) = 0; - virtual void SetDeviceEmulationTransform(const TransformationMatrix&) = 0; - virtual void SetShowDebugBorders(bool) = 0; - - virtual Page* GetPage() const = 0; - virtual Frame* FocusedCoreFrame() const = 0; - - CORE_EXPORT static HashSet<WebViewBase*>& AllInstances(); - - // Returns the main frame associated with this view. This may be null when - // the page is shutting down, but will be valid at all other times. - virtual WebLocalFrameImpl* MainFrameImpl() const = 0; - - virtual float DefaultMinimumPageScaleFactor() const = 0; - virtual float DefaultMaximumPageScaleFactor() const = 0; - virtual float MinimumPageScaleFactor() const = 0; - virtual float MaximumPageScaleFactor() const = 0; - virtual float ClampPageScaleFactorToLimits(float) const = 0; - virtual void ResetScaleStateImmediately() = 0; - - virtual WebLayerTreeView* LayerTreeView() const = 0; - virtual WebViewClient* Client() = 0; - - virtual void ZoomToFindInPageRect(const WebRect&) = 0; - - virtual PageScaleConstraintsSet& GetPageScaleConstraintsSet() const = 0; - virtual Color BaseBackgroundColor() const = 0; - virtual bool BackgroundColorOverrideEnabled() const = 0; - virtual WebColor BackgroundColorOverride() const = 0; - - virtual void DidChangeContentsSize() = 0; - virtual void PageScaleFactorChanged() = 0; - virtual void MainFrameScrollOffsetChanged() = 0; - virtual void UpdateMainFrameLayoutSize() = 0; - - virtual DevToolsEmulator* GetDevToolsEmulator() const = 0; - - // Notifies the WebView that a load has been committed. isNewNavigation - // will be true if a new session history item should be created for that - // load. isNavigationWithinPage will be true if the navigation does - // not take the user away from the current page. - virtual void DidCommitLoad(bool is_new_navigation, - bool is_navigation_within_page) = 0; - - virtual void ShowContextMenuAtPoint(float x, - float y, - ContextMenuProvider*) = 0; - virtual void ShowContextMenuForElement(WebElement) = 0; - - virtual IntSize MainFrameSize() = 0; - virtual bool ShouldAutoResize() const = 0; - virtual IntSize MinAutoSize() const = 0; - virtual IntSize MaxAutoSize() const = 0; - virtual WebDisplayMode DisplayMode() const = 0; - - virtual void DidUpdateFullscreenSize() = 0; - virtual void SetLastHiddenPagePopup(WebPagePopupImpl*) = 0; - virtual WebInputEventResult SendContextMenuEvent(const WebKeyboardEvent&) = 0; - - virtual CompositorAnimationTimeline* LinkHighlightsTimeline() const = 0; - - virtual WebSettingsImpl* SettingsImpl() = 0; - - virtual void RequestDecode(const PaintImage&, - WTF::Function<void(bool)> callback) = 0; - - using WebWidget::GetPagePopup; - virtual PagePopup* OpenPagePopup(PagePopupClient*) = 0; - virtual void ClosePagePopup(PagePopup*) = 0; - virtual void CleanupPagePopup() = 0; - virtual LocalDOMWindow* PagePopupWindow() const = 0; - - virtual void InvalidateRect(const IntRect&) = 0; - - // These functions only apply to the main frame. - // - // LayoutUpdated() indicates two things: - // 1) This view may have a new layout now. - // 2) Calling UpdateAllLifecyclePhases() is a now a no-op. - // After calling WebWidget::UpdateAllLifecyclePhases(), expect to get this - // notification unless the view did not need a layout. - virtual void LayoutUpdated() = 0; - virtual void ResizeAfterLayout() = 0; - - virtual void UpdatePageDefinedViewportConstraints( - const ViewportDescription&) = 0; - - virtual void EnterFullscreen(LocalFrame&) = 0; - virtual void ExitFullscreen(LocalFrame&) = 0; - virtual void FullscreenElementChanged(Element* old_element, - Element* new_element) = 0; - - virtual bool HasOpenedPopup() const = 0; - - // Returns true if popup menus should be rendered by the browser, false if - // they should be rendered by WebKit (which is the default). - static bool UseExternalPopupMenus(); - - virtual GraphicsLayer* RootGraphicsLayer() = 0; - virtual void RegisterViewportLayersWithCompositor() = 0; - virtual PaintLayerCompositor* Compositor() const = 0; - - virtual void DidUpdateBrowserControls() = 0; - virtual FloatSize ElasticOverscroll() const = 0; - virtual double LastFrameTimeMonotonic() const = 0; - - CORE_EXPORT static const WebInputEvent* CurrentInputEvent(); - - virtual void SetCompositorVisibility(bool) = 0; - using WebWidget::SetSuppressFrameRequestsWorkaroundFor704763Only; - using WebWidget::RecordWheelAndTouchScrollingCount; - using WebWidget::GetCompositionCharacterBounds; - // Returns the currently active WebInputMethodController which is the one - // corresponding to the focused frame. It will return nullptr if there is no - // focused frame, or if there is one but it belongs to a different local - // root. - virtual WebInputMethodController* GetActiveWebInputMethodController() - const = 0; - virtual void ScheduleAnimationForWidget() = 0; - virtual CompositorMutatorImpl* CompositorMutator() = 0; - virtual void SetRootGraphicsLayer(GraphicsLayer*) = 0; - virtual void SetRootLayer(WebLayer*) = 0; - virtual CompositorAnimationHost* AnimationHost() const = 0; - virtual HitTestResult CoreHitTestResultAt(const WebPoint&) = 0; - - virtual class ChromeClient& GetChromeClient() const = 0; - - // These methods are consumed by test code only. - virtual BrowserControls& GetBrowserControls() = 0; - virtual Element* FocusedElement() const = 0; - virtual void EnableFakePageScaleAnimationForTesting(bool) = 0; - virtual bool FakeDoubleTapAnimationPendingForTesting() const = 0; - virtual void AnimateDoubleTapZoom(const IntPoint&) = 0; - virtual WebRect ComputeBlockBound(const WebPoint&, bool ignore_clipping) = 0; - virtual void ComputeScaleAndScrollForBlockRect( - const WebPoint& hit_point, - const WebRect& block_rect, - float padding, - float default_scale_when_already_legible, - float& scale, - WebPoint& scroll) = 0; - virtual float FakePageScaleAnimationPageScaleForTesting() const = 0; - virtual bool FakePageScaleAnimationUseAnchorForTesting() const = 0; - virtual IntPoint FakePageScaleAnimationTargetPositionForTesting() const = 0; - virtual void ComputeScaleAndScrollForFocusedNode( - Node* focused_node, - bool zoom_in_to_legible_scale, - float& scale, - IntPoint& scroll, - bool& need_animation) = 0; - virtual bool HasHorizontalScrollbar() = 0; - virtual bool HasVerticalScrollbar() = 0; - virtual TransformationMatrix GetDeviceEmulationTransformForTesting() - const = 0; - virtual bool MatchesHeuristicsForGpuRasterizationForTesting() const = 0; - virtual Node* BestTapNode( - const GestureEventWithHitTestResults& targeted_tap_event) = 0; - virtual void EnableTapHighlightAtPoint( - const GestureEventWithHitTestResults& targeted_tap_event) = 0; - virtual LinkHighlightImpl* GetLinkHighlight(int) = 0; - virtual unsigned NumLinkHighlights() = 0; - virtual void EnableTapHighlights(HeapVector<Member<Node>>&) = 0; - - protected: - CORE_EXPORT static const WebInputEvent* current_input_event_; -}; -} - -#endif // WebViewBase_h
diff --git a/third_party/WebKit/Source/core/exported/WebViewImpl.cpp b/third_party/WebKit/Source/core/exported/WebViewImpl.cpp index 6a571cd..e7a9f83 100644 --- a/third_party/WebKit/Source/core/exported/WebViewImpl.cpp +++ b/third_party/WebKit/Source/core/exported/WebViewImpl.cpp
@@ -212,6 +212,46 @@ const double WebView::kMinTextSizeMultiplier = 0.5; const double WebView::kMaxTextSizeMultiplier = 3.0; +const WebInputEvent* WebViewImpl::current_input_event_ = nullptr; + +const WebInputEvent* WebViewImpl::CurrentInputEvent() { + return current_input_event_; +} + +// Used to defer all page activity in cases where the embedder wishes to run +// a nested event loop. Using a stack enables nesting of message loop +// invocations. +static Vector<std::unique_ptr<ScopedPageSuspender>>& PageSuspenderStack() { + DEFINE_STATIC_LOCAL(Vector<std::unique_ptr<ScopedPageSuspender>>, + suspender_stack, ()); + return suspender_stack; +} + +void WebView::WillEnterModalLoop() { + PageSuspenderStack().push_back(WTF::MakeUnique<ScopedPageSuspender>()); +} + +void WebView::DidExitModalLoop() { + DCHECK(PageSuspenderStack().size()); + PageSuspenderStack().pop_back(); +} + +// static +HashSet<WebViewImpl*>& WebViewImpl::AllInstances() { + DEFINE_STATIC_LOCAL(HashSet<WebViewImpl*>, all_instances, ()); + return all_instances; +} + +static bool g_should_use_external_popup_menus = false; + +void WebView::SetUseExternalPopupMenus(bool use_external_popup_menus) { + g_should_use_external_popup_menus = use_external_popup_menus; +} + +bool WebViewImpl::UseExternalPopupMenus() { + return g_should_use_external_popup_menus; +} + namespace { class EmptyEventListener final : public EventListener { @@ -257,7 +297,7 @@ return WebViewImpl::Create(client, visibility_state); } -WebViewBase* WebViewImpl::Create(WebViewClient* client, +WebViewImpl* WebViewImpl::Create(WebViewClient* client, WebPageVisibilityState visibility_state) { // Pass the WebViewImpl's self-reference to the caller. return AdoptRef(new WebViewImpl(client, visibility_state)).LeakRef();
diff --git a/third_party/WebKit/Source/core/exported/WebViewImpl.h b/third_party/WebKit/Source/core/exported/WebViewImpl.h index 1ead0722..e9f8485 100644 --- a/third_party/WebKit/Source/core/exported/WebViewImpl.h +++ b/third_party/WebKit/Source/core/exported/WebViewImpl.h
@@ -37,7 +37,6 @@ #include "core/CoreExport.h" #include "core/editing/spellcheck/SpellCheckerClientImpl.h" #include "core/exported/WebPagePopupImpl.h" -#include "core/exported/WebViewBase.h" #include "core/frame/ResizeViewportAnchor.h" #include "core/page/ChromeClient.h" #include "core/page/ContextMenuClient.h" @@ -45,6 +44,7 @@ #include "core/page/EditorClient.h" #include "core/page/EventWithHitTestResults.h" #include "core/page/PageWidgetDelegate.h" +#include "core/page/ScopedPageSuspender.h" #include "platform/animation/CompositorAnimationTimeline.h" #include "platform/geometry/IntPoint.h" #include "platform/geometry/IntRect.h" @@ -54,6 +54,7 @@ #include "platform/scheduler/child/web_scheduler.h" #include "platform/wtf/Compiler.h" #include "platform/wtf/HashSet.h" +#include "platform/wtf/StdLibExtras.h" #include "platform/wtf/Vector.h" #include "public/platform/WebDisplayMode.h" #include "public/platform/WebFloatSize.h" @@ -69,6 +70,7 @@ #include "public/platform/WebVector.h" #include "public/web/WebNavigationPolicy.h" #include "public/web/WebPageImportanceSignals.h" +#include "public/web/WebView.h" namespace blink { @@ -96,13 +98,19 @@ class WebViewScheduler; class CORE_EXPORT WebViewImpl final - : NON_EXPORTED_BASE(public WebViewBase), + : NON_EXPORTED_BASE(public WebView), + public RefCounted<WebViewImpl>, NON_EXPORTED_BASE(public WebGestureCurveTarget), public PageWidgetEventHandler, public WebScheduler::InterventionReporter, public WebViewScheduler::WebViewSchedulerDelegate { public: - static WebViewBase* Create(WebViewClient*, WebPageVisibilityState); + static WebViewImpl* Create(WebViewClient*, WebPageVisibilityState); + static HashSet<WebViewImpl*>& AllInstances(); + static const WebInputEvent* CurrentInputEvent(); + // Returns true if popup menus should be rendered by the browser, false if + // they should be rendered by WebKit (which is the default). + static bool UseExternalPopupMenus(); // WebWidget methods: void Close() override; @@ -179,7 +187,7 @@ void ClearFocusedElement() override; bool ScrollFocusedEditableElementIntoRect(const WebRect&) override; void SmoothScroll(int target_x, int target_y, long duration_ms) override; - void ZoomToFindInPageRect(const WebRect&) override; + void ZoomToFindInPageRect(const WebRect&); void AdvanceFocus(bool reverse) override; void AdvanceFocusAcrossFrames(WebFocusType, WebRemoteFrame* from, @@ -236,7 +244,7 @@ bool EndActiveFlingAnimation() override; bool IsFlinging() const override { return !!gesture_animation_.get(); } void SetShowPaintRects(bool) override; - void SetShowDebugBorders(bool) override; + void SetShowDebugBorders(bool); void SetShowFPSCounter(bool) override; void SetShowScrollBottleneckRects(bool) override; void AcceptLanguagesChanged() override; @@ -245,58 +253,58 @@ void ReportIntervention(const WebString& message) override; void RequestBeginMainFrameNotExpected(bool new_state) override; - void DidUpdateFullscreenSize() override; + void DidUpdateFullscreenSize(); - float DefaultMinimumPageScaleFactor() const override; - float DefaultMaximumPageScaleFactor() const override; - float MinimumPageScaleFactor() const override; - float MaximumPageScaleFactor() const override; - float ClampPageScaleFactorToLimits(float) const override; - void ResetScaleStateImmediately() override; + float DefaultMinimumPageScaleFactor() const; + float DefaultMaximumPageScaleFactor() const; + float MinimumPageScaleFactor() const; + float MaximumPageScaleFactor() const; + float ClampPageScaleFactorToLimits(float) const; + void ResetScaleStateImmediately(); - HitTestResult CoreHitTestResultAt(const WebPoint&) override; - void InvalidateRect(const IntRect&) override; + HitTestResult CoreHitTestResultAt(const WebPoint&); + void InvalidateRect(const IntRect&); - void SetBaseBackgroundColor(WebColor) override; - void SetBaseBackgroundColorOverride(WebColor) override; - void ClearBaseBackgroundColorOverride() override; - void SetBackgroundColorOverride(WebColor) override; - void ClearBackgroundColorOverride() override; - void SetZoomFactorOverride(float) override; - void SetCompositorDeviceScaleFactorOverride(float) override; - void SetDeviceEmulationTransform(const TransformationMatrix&) override; - TransformationMatrix GetDeviceEmulationTransformForTesting() const override; + void SetBaseBackgroundColor(WebColor); + void SetBaseBackgroundColorOverride(WebColor); + void ClearBaseBackgroundColorOverride(); + void SetBackgroundColorOverride(WebColor); + void ClearBackgroundColorOverride(); + void SetZoomFactorOverride(float); + void SetCompositorDeviceScaleFactorOverride(float); + void SetDeviceEmulationTransform(const TransformationMatrix&); + TransformationMatrix GetDeviceEmulationTransformForTesting() const; - Color BaseBackgroundColor() const override; - bool BackgroundColorOverrideEnabled() const override { + Color BaseBackgroundColor() const; + bool BackgroundColorOverrideEnabled() const { return background_color_override_enabled_; } - WebColor BackgroundColorOverride() const override { + WebColor BackgroundColorOverride() const { return background_color_override_; } - Frame* FocusedCoreFrame() const override; + Frame* FocusedCoreFrame() const; // Returns the currently focused Element or null if no element has focus. - Element* FocusedElement() const override; + Element* FocusedElement() const; - WebViewClient* Client() override { return client_; } + WebViewClient* Client() { return client_; } // Returns the page object associated with this view. This may be null when // the page is shutting down, but will be valid at all other times. - Page* GetPage() const override { return page_.Get(); } + Page* GetPage() const { return page_.Get(); } // Returns a ValidationMessageClient associated to the Page. This is nullable. ValidationMessageClient* GetValidationMessageClient() const; WebDevToolsAgentImpl* MainFrameDevToolsAgentImpl(); - DevToolsEmulator* GetDevToolsEmulator() const override { + DevToolsEmulator* GetDevToolsEmulator() const { return dev_tools_emulator_.Get(); } // Returns the main frame associated with this view. This may be null when // the page is shutting down, but will be valid at all other times. - WebLocalFrameImpl* MainFrameImpl() const override; + WebLocalFrameImpl* MainFrameImpl() const; // Event related methods: void MouseContextMenu(const WebMouseEvent&); @@ -317,57 +325,55 @@ // wParam, LPARAM lParam) in webkit\webkit\win\WebView.cpp. The only // significant change in this function is the code to convert from a // Keyboard event to the Right Mouse button down event. - WebInputEventResult SendContextMenuEvent(const WebKeyboardEvent&) override; + WebInputEventResult SendContextMenuEvent(const WebKeyboardEvent&); - void ShowContextMenuAtPoint(float x, float y, ContextMenuProvider*) override; + void ShowContextMenuAtPoint(float x, float y, ContextMenuProvider*); - void ShowContextMenuForElement(WebElement) override; + void ShowContextMenuForElement(WebElement); // Notifies the WebView that a load has been committed. isNewNavigation // will be true if a new session history item should be created for that // load. isNavigationWithinPage will be true if the navigation does // not take the user away from the current page. - void DidCommitLoad(bool is_new_navigation, - bool is_navigation_within_page) override; + void DidCommitLoad(bool is_new_navigation, bool is_navigation_within_page); // Indicates two things: // 1) This view may have a new layout now. // 2) Calling updateAllLifecyclePhases() is a no-op. // After calling WebWidget::updateAllLifecyclePhases(), expect to get this // notification unless the view did not need a layout. - void LayoutUpdated() override; - void ResizeAfterLayout() override; + void LayoutUpdated(); + void ResizeAfterLayout(); - void DidChangeContentsSize() override; - void PageScaleFactorChanged() override; - void MainFrameScrollOffsetChanged() override; + void DidChangeContentsSize(); + void PageScaleFactorChanged(); + void MainFrameScrollOffsetChanged(); - bool ShouldAutoResize() const override { return should_auto_resize_; } + bool ShouldAutoResize() const { return should_auto_resize_; } - IntSize MinAutoSize() const override { return min_auto_size_; } + IntSize MinAutoSize() const { return min_auto_size_; } - IntSize MaxAutoSize() const override { return max_auto_size_; } + IntSize MaxAutoSize() const { return max_auto_size_; } - void UpdateMainFrameLayoutSize() override; - void UpdatePageDefinedViewportConstraints( - const ViewportDescription&) override; + void UpdateMainFrameLayoutSize(); + void UpdatePageDefinedViewportConstraints(const ViewportDescription&); - PagePopup* OpenPagePopup(PagePopupClient*) override; - void ClosePagePopup(PagePopup*) override; - void CleanupPagePopup() override; - LocalDOMWindow* PagePopupWindow() const override; + PagePopup* OpenPagePopup(PagePopupClient*); + void ClosePagePopup(PagePopup*); + void CleanupPagePopup(); + LocalDOMWindow* PagePopupWindow() const; - GraphicsLayer* RootGraphicsLayer() override; - void RegisterViewportLayersWithCompositor() override; - PaintLayerCompositor* Compositor() const override; - CompositorAnimationTimeline* LinkHighlightsTimeline() const override { + GraphicsLayer* RootGraphicsLayer(); + void RegisterViewportLayersWithCompositor(); + PaintLayerCompositor* Compositor() const; + CompositorAnimationTimeline* LinkHighlightsTimeline() const { return link_highlights_timeline_.get(); } WebViewScheduler* Scheduler() const override; void SetVisibilityState(WebPageVisibilityState, bool) override; - bool HasOpenedPopup() const override { return page_popup_.Get(); } + bool HasOpenedPopup() const { return page_popup_.Get(); } // Called by a full frame plugin inside this view to inform it that its // zoom level has been updated. The plugin should only call this function @@ -381,67 +387,65 @@ float padding, float default_scale_when_already_legible, float& scale, - WebPoint& scroll) override; - Node* BestTapNode( - const GestureEventWithHitTestResults& targeted_tap_event) override; + WebPoint& scroll); + Node* BestTapNode(const GestureEventWithHitTestResults& targeted_tap_event); void EnableTapHighlightAtPoint( - const GestureEventWithHitTestResults& targeted_tap_event) override; - void EnableTapHighlights(HeapVector<Member<Node>>&) override; + const GestureEventWithHitTestResults& targeted_tap_event); + void EnableTapHighlights(HeapVector<Member<Node>>&); void ComputeScaleAndScrollForFocusedNode(Node* focused_node, bool zoom_in_to_legible_scale, float& scale, IntPoint& scroll, - bool& need_animation) override; + bool& need_animation); - void AnimateDoubleTapZoom(const IntPoint&) override; + void AnimateDoubleTapZoom(const IntPoint&); void ResolveTapDisambiguation(double timestamp_seconds, WebPoint tap_viewport_offset, bool is_long_press) override; - void EnableFakePageScaleAnimationForTesting(bool) override; - bool FakeDoubleTapAnimationPendingForTesting() const override { + void EnableFakePageScaleAnimationForTesting(bool); + bool FakeDoubleTapAnimationPendingForTesting() const { return double_tap_zoom_pending_; } - IntPoint FakePageScaleAnimationTargetPositionForTesting() const override { + IntPoint FakePageScaleAnimationTargetPositionForTesting() const { return fake_page_scale_animation_target_position_; } - float FakePageScaleAnimationPageScaleForTesting() const override { + float FakePageScaleAnimationPageScaleForTesting() const { return fake_page_scale_animation_page_scale_factor_; } - bool FakePageScaleAnimationUseAnchorForTesting() const override { + bool FakePageScaleAnimationUseAnchorForTesting() const { return fake_page_scale_animation_use_anchor_; } - void EnterFullscreen(LocalFrame&) override; - void ExitFullscreen(LocalFrame&) override; - void FullscreenElementChanged(Element* old_element, - Element* new_element) override; + void EnterFullscreen(LocalFrame&); + void ExitFullscreen(LocalFrame&); + void FullscreenElementChanged(Element* old_element, Element* new_element); // Exposed for the purpose of overriding device metrics. void SendResizeEventAndRepaint(); // Exposed for testing purposes. - bool HasHorizontalScrollbar() override; - bool HasVerticalScrollbar() override; + bool HasHorizontalScrollbar(); + bool HasVerticalScrollbar(); // Exposed for tests. - unsigned NumLinkHighlights() override { return link_highlights_.size(); } - LinkHighlightImpl* GetLinkHighlight(int i) override { + unsigned NumLinkHighlights() { return link_highlights_.size(); } + LinkHighlightImpl* GetLinkHighlight(int i) { return link_highlights_[i].get(); } - WebSettingsImpl* SettingsImpl() override; + WebSettingsImpl* SettingsImpl(); // Returns the bounding box of the block type node touched by the WebPoint. - WebRect ComputeBlockBound(const WebPoint&, bool ignore_clipping) override; + WebRect ComputeBlockBound(const WebPoint&, bool ignore_clipping); - WebLayerTreeView* LayerTreeView() const override { return layer_tree_view_; } - CompositorAnimationHost* AnimationHost() const override { + WebLayerTreeView* LayerTreeView() const { return layer_tree_view_; } + CompositorAnimationHost* AnimationHost() const { return animation_host_.get(); } - bool MatchesHeuristicsForGpuRasterizationForTesting() const override { + bool MatchesHeuristicsForGpuRasterizationForTesting() const { return matches_heuristics_for_gpu_rasterization_; } @@ -449,26 +453,24 @@ WebBrowserControlsState current, bool animate) override; - BrowserControls& GetBrowserControls() override; + BrowserControls& GetBrowserControls(); // Called anytime browser controls layout height or content offset have // changed. - void DidUpdateBrowserControls() override; + void DidUpdateBrowserControls(); void ForceNextWebGLContextCreationToFail() override; void ForceNextDrawingBufferCreationToFail() override; - IntSize MainFrameSize() override; - WebDisplayMode DisplayMode() const override { return display_mode_; } + IntSize MainFrameSize(); + WebDisplayMode DisplayMode() const { return display_mode_; } - PageScaleConstraintsSet& GetPageScaleConstraintsSet() const override; + PageScaleConstraintsSet& GetPageScaleConstraintsSet() const; - FloatSize ElasticOverscroll() const override { return elastic_overscroll_; } + FloatSize ElasticOverscroll() const { return elastic_overscroll_; } - double LastFrameTimeMonotonic() const override { - return last_frame_time_monotonic_; - } + double LastFrameTimeMonotonic() const { return last_frame_time_monotonic_; } - class ChromeClient& GetChromeClient() const override { + class ChromeClient& GetChromeClient() const { return *chrome_client_.Get(); } @@ -478,12 +480,11 @@ // root. WebInputMethodController* GetActiveWebInputMethodController() const; - void SetLastHiddenPagePopup(WebPagePopupImpl* page_popup) override { + void SetLastHiddenPagePopup(WebPagePopupImpl* page_popup) { last_hidden_page_popup_ = page_popup; } - void RequestDecode(const PaintImage&, - WTF::Function<void(bool)> callback) override; + void RequestDecode(const PaintImage&, WTF::Function<void(bool)> callback); private: void SetPageScaleFactorAndLocation(float, const FloatPoint&); @@ -504,10 +505,10 @@ // Overrides the compositor visibility. See the description of // m_overrideCompositorVisibility for more details. - void SetCompositorVisibility(bool) override; + void SetCompositorVisibility(bool); // TODO(lfg): Remove once WebViewFrameWidget is deleted. - void ScheduleAnimationForWidget() override; + void ScheduleAnimationForWidget(); bool GetCompositionCharacterBounds(WebVector<WebRect>&) override; void UpdateBaseBackgroundColor(); @@ -566,8 +567,8 @@ float DeviceScaleFactor() const; - void SetRootGraphicsLayer(GraphicsLayer*) override; - void SetRootLayer(WebLayer*) override; + void SetRootGraphicsLayer(GraphicsLayer*); + void SetRootLayer(WebLayer*); void AttachCompositorAnimationTimeline(CompositorAnimationTimeline*); void DetachCompositorAnimationTimeline(CompositorAnimationTimeline*); @@ -575,7 +576,7 @@ LocalFrame* FocusedLocalFrameAvailableForIme() const; CompositorMutatorImpl& Mutator(); - CompositorMutatorImpl* CompositorMutator() override; + CompositorMutatorImpl* CompositorMutator(); WebViewClient* client_; // Can be 0 (e.g. unittests, shared workers, etc.) @@ -714,6 +715,8 @@ bool override_compositor_visibility_; Persistent<ResizeViewportAnchor> resize_viewport_anchor_; + + static const WebInputEvent* current_input_event_; }; // We have no ways to check if the specified WebView is an instance of
diff --git a/third_party/WebKit/Source/core/exported/WebViewTest.cpp b/third_party/WebKit/Source/core/exported/WebViewTest.cpp index 087c5d2d..42724c9 100644 --- a/third_party/WebKit/Source/core/exported/WebViewTest.cpp +++ b/third_party/WebKit/Source/core/exported/WebViewTest.cpp
@@ -1642,7 +1642,7 @@ const std::string test_file = "advance_focus_in_form_with_key_event_listeners.html"; RegisterMockedHttpURLLoad(test_file); - WebViewBase* web_view = + WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(base_url_ + test_file); web_view->SetInitialFocus(false); Document* document = web_view->MainFrameImpl()->GetFrame()->GetDocument(); @@ -1868,7 +1868,7 @@ const std::string test_file = "advance_focus_in_form_with_key_event_listeners.html"; RegisterMockedHttpURLLoad(test_file); - WebViewBase* web_view = + WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(base_url_ + test_file); web_view->SetInitialFocus(false); Document* document = web_view->MainFrameImpl()->GetFrame()->GetDocument(); @@ -1967,7 +1967,7 @@ const std::string test_file = "advance_focus_in_form_with_tabindex_elements.html"; RegisterMockedHttpURLLoad(test_file); - WebViewBase* web_view = + WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(base_url_ + test_file); web_view->SetInitialFocus(false); Document* document = web_view->MainFrameImpl()->GetFrame()->GetDocument(); @@ -2066,7 +2066,7 @@ const std::string test_file = "advance_focus_in_form_with_disabled_and_readonly_elements.html"; RegisterMockedHttpURLLoad(test_file); - WebViewBase* web_view = + WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(base_url_ + test_file); web_view->SetInitialFocus(false); Document* document = web_view->MainFrameImpl()->GetFrame()->GetDocument();
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.cpp b/third_party/WebKit/Source/core/frame/Deprecation.cpp index df4a2b36..51709982 100644 --- a/third_party/WebKit/Source/core/frame/Deprecation.cpp +++ b/third_party/WebKit/Source/core/frame/Deprecation.cpp
@@ -489,10 +489,6 @@ "https://www.chromestatus.com/feature/5735596811091968 for more " "details."; - case WebFeature::kV8SVGPathElement_GetPathSegAtLength_Method: - return willBeRemoved("SVGPathElement.getPathSegAtLength", M62, - "5638783282184192"); - case WebFeature::kCredentialManagerCredentialRequestOptionsUnmediated: return replacedWillBeRemoved( "The boolean flag CredentialRequestOptions.unmediated",
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp index c9a0d1d..a55a5a4 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp +++ b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
@@ -2069,12 +2069,14 @@ VisiblePosition visible_start(visible_selection.VisibleStart()); RenderedPosition rendered_start(visible_start); rendered_start.PositionInGraphicsLayerBacking(selection.start, true); + selection.start.hidden = !rendered_start.IsVisible(true); if (!selection.start.layer) return false; VisiblePosition visible_end(visible_selection.VisibleEnd()); RenderedPosition rendered_end(visible_end); rendered_end.PositionInGraphicsLayerBacking(selection.end, false); + selection.end.hidden = !rendered_end.IsVisible(false); if (!selection.end.layer) return false; @@ -2813,6 +2815,16 @@ } } +CompositorElementId LocalFrameView::GetCompositorElementId() const { + if (!RuntimeEnabledFeatures::RootLayerScrollingEnabled()) { + return CompositorElementIdFromDOMNodeId( + DOMNodeIds::IdForNode(&GetLayoutView()->GetDocument()), + CompositorElementIdNamespace::kRootScroll); + } else { + return PaintInvalidationCapableScrollableArea::GetCompositorElementId(); + } +} + bool LocalFrameView::ScrollAnimatorEnabled() const { return frame_->GetSettings() && frame_->GetSettings()->GetScrollAnimatorEnabled(); @@ -3197,6 +3209,7 @@ Optional<CompositorElementIdSet> composited_element_ids = CompositorElementIdSet(); PushPaintArtifactToCompositor(composited_element_ids.value()); + // TODO(wkorman): Add a call to UpdateCompositorScrollAnimations here. DocumentAnimations::UpdateAnimations(GetLayoutView()->GetDocument(), DocumentLifecycle::kPaintClean, composited_element_ids);
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.h b/third_party/WebKit/Source/core/frame/LocalFrameView.h index 940304c..9f5981b5 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrameView.h +++ b/third_party/WebKit/Source/core/frame/LocalFrameView.h
@@ -435,6 +435,7 @@ // ScrollableArea interface void GetTickmarks(Vector<IntRect>&) const override; IntRect ScrollableAreaBoundingBox() const override; + CompositorElementId GetCompositorElementId() const override; bool ScrollAnimatorEnabled() const override; bool UsesCompositedScrolling() const override; bool ShouldScrollOnMainThread() const override;
diff --git a/third_party/WebKit/Source/core/frame/RootFrameViewport.cpp b/third_party/WebKit/Source/core/frame/RootFrameViewport.cpp index a0efbd7..16dbe4ef 100644 --- a/third_party/WebKit/Source/core/frame/RootFrameViewport.cpp +++ b/third_party/WebKit/Source/core/frame/RootFrameViewport.cpp
@@ -444,6 +444,10 @@ return LayoutViewport().ScrollAnimatorEnabled(); } +CompositorElementId RootFrameViewport::GetCompositorElementId() const { + return LayoutViewport().GetCompositorElementId(); +} + PlatformChromeClient* RootFrameViewport::GetChromeClient() const { return LayoutViewport().GetChromeClient(); }
diff --git a/third_party/WebKit/Source/core/frame/RootFrameViewport.h b/third_party/WebKit/Source/core/frame/RootFrameViewport.h index 42634d6..2214a79 100644 --- a/third_party/WebKit/Source/core/frame/RootFrameViewport.h +++ b/third_party/WebKit/Source/core/frame/RootFrameViewport.h
@@ -95,6 +95,7 @@ OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize) const override; ScrollResult UserScroll(ScrollGranularity, const FloatSize&) override; + CompositorElementId GetCompositorElementId() const override; bool ScrollAnimatorEnabled() const override; PlatformChromeClient* GetChromeClient() const override; SmoothScrollSequencer* GetSmoothScrollSequencer() const override;
diff --git a/third_party/WebKit/Source/core/frame/RootFrameViewportTest.cpp b/third_party/WebKit/Source/core/frame/RootFrameViewportTest.cpp index 3ed693a..d686bae7 100644 --- a/third_party/WebKit/Source/core/frame/RootFrameViewportTest.cpp +++ b/third_party/WebKit/Source/core/frame/RootFrameViewportTest.cpp
@@ -79,6 +79,9 @@ viewport_size_(viewport_size), contents_size_(contents_size) {} + CompositorElementId GetCompositorElementId() const override { + return CompositorElementId(); + } void UpdateScrollOffset(const ScrollOffset& offset, ScrollType) override { scroll_offset_ = offset; }
diff --git a/third_party/WebKit/Source/core/frame/VisualViewport.cpp b/third_party/WebKit/Source/core/frame/VisualViewport.cpp index 6b62059f..8e59847 100644 --- a/third_party/WebKit/Source/core/frame/VisualViewport.cpp +++ b/third_party/WebKit/Source/core/frame/VisualViewport.cpp
@@ -502,6 +502,11 @@ return GetPage().GetSettings().GetViewportEnabled(); } +CompositorElementId VisualViewport::GetCompositorElementId() const { + // TODO(chrishtr): Implement http://crbug.com/638473. + return CompositorElementId(); +} + bool VisualViewport::ScrollAnimatorEnabled() const { return GetPage().GetSettings().GetScrollAnimatorEnabled(); }
diff --git a/third_party/WebKit/Source/core/frame/VisualViewport.h b/third_party/WebKit/Source/core/frame/VisualViewport.h index a33c05a..559fbb74 100644 --- a/third_party/WebKit/Source/core/frame/VisualViewport.h +++ b/third_party/WebKit/Source/core/frame/VisualViewport.h
@@ -202,6 +202,7 @@ IntRect ScrollableAreaBoundingBox() const override; bool UserInputScrollable(ScrollbarOrientation) const override; bool ShouldPlaceVerticalScrollbarOnLeft() const override { return false; } + CompositorElementId GetCompositorElementId() const override; bool ScrollAnimatorEnabled() const override; void ScrollControlWasSetNeedsPaintInvalidation() override {} void UpdateScrollOffset(const ScrollOffset&, ScrollType) override;
diff --git a/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.cpp b/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.cpp index 489a9a9..3da0c85 100644 --- a/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.cpp +++ b/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.cpp
@@ -6,7 +6,7 @@ #include "core/dom/UserGestureIndicator.h" #include "core/events/WebInputEventConversion.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalFrameView.h" #include "core/frame/VisualViewport.h" #include "core/frame/WebLocalFrameImpl.h" @@ -225,7 +225,7 @@ return GetPage()->GetVisualViewport().ViewportToRootFrame(point_in_viewport); } -WebViewBase* WebFrameWidgetBase::View() const { +WebViewImpl* WebFrameWidgetBase::View() const { return ToWebLocalFrameImpl(LocalRoot())->ViewImpl(); }
diff --git a/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.h b/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.h index 6d37a2c..e80246a 100644 --- a/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.h +++ b/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.h
@@ -23,7 +23,7 @@ class WebImage; class WebLayer; class WebLayerTreeView; -class WebViewBase; +class WebViewImpl; class HitTestResult; struct WebPoint; @@ -109,7 +109,7 @@ // Helper function to call VisualViewport::viewportToRootFrame(). WebPoint ViewportToRootFrame(const WebPoint& point_in_viewport) const; - WebViewBase* View() const; + WebViewImpl* View() const; // Returns the page object associated with this widget. This may be null when // the page is shutting down, but will be valid at all other times.
diff --git a/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp index 317d3ab..9f19c23 100644 --- a/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp +++ b/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp
@@ -46,7 +46,7 @@ #include "core/exported/WebPagePopupImpl.h" #include "core/exported/WebPluginContainerImpl.h" #include "core/exported/WebRemoteFrameImpl.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalFrameView.h" #include "core/frame/RemoteFrame.h" #include "core/frame/Settings.h" @@ -62,6 +62,7 @@ #include "core/page/ContextMenuController.h" #include "core/page/FocusController.h" #include "core/page/Page.h" +#include "core/page/PagePopup.h" #include "core/page/PointerLockController.h" #include "core/page/ValidationMessageClient.h" #include "platform/KeyboardCodes.h" @@ -780,13 +781,13 @@ void WebFrameWidgetImpl::HandleMouseDown(LocalFrame& main_frame, const WebMouseEvent& event) { - WebViewBase* view_impl = View(); + WebViewImpl* view_impl = View(); // If there is a popup open, close it as the user is clicking on the page // (outside of the popup). We also save it so we can prevent a click on an // element from immediately reopening the same popup. RefPtr<WebPagePopupImpl> page_popup; if (event.button == WebMouseEvent::Button::kLeft) { - page_popup = ToWebPagePopupImpl(view_impl->GetPagePopup()); + page_popup = view_impl->GetPagePopup(); view_impl->HidePopups(); } @@ -816,8 +817,7 @@ } if (view_impl->GetPagePopup() && page_popup && - ToWebPagePopupImpl(view_impl->GetPagePopup()) - ->HasSamePopupClient(page_popup.Get())) { + view_impl->GetPagePopup()->HasSamePopupClient(page_popup.Get())) { // That click triggered a page popup that is the same as the one we just // closed. It needs to be closed. view_impl->HidePopups(); @@ -897,7 +897,7 @@ WebInputEventResult event_result = WebInputEventResult::kNotHandled; bool event_cancelled = false; - WebViewBase* view_impl = View(); + WebViewImpl* view_impl = View(); switch (event.GetType()) { case WebInputEvent::kGestureScrollBegin: case WebInputEvent::kGestureScrollEnd: @@ -911,8 +911,7 @@ // When we close a popup because of a GestureTapDown, we also save it so // we can prevent the following GestureTap from immediately reopening the // same popup. - view_impl->SetLastHiddenPagePopup( - ToWebPagePopupImpl(view_impl->GetPagePopup())); + view_impl->SetLastHiddenPagePopup(view_impl->GetPagePopup()); View()->HidePopups(); case WebInputEvent::kGestureTapCancel: View()->SetLastHiddenPagePopup(nullptr);
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp index 82a1591..7ddba14 100644 --- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp +++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
@@ -131,7 +131,7 @@ #include "core/exported/WebDocumentLoaderImpl.h" #include "core/exported/WebPluginContainerImpl.h" #include "core/exported/WebRemoteFrameImpl.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalDOMWindow.h" #include "core/frame/LocalFrameView.h" #include "core/frame/PageScaleConstraintsSet.h" @@ -1537,7 +1537,7 @@ WebLocalFrameImpl* frame = new WebLocalFrameImpl(WebTreeScopeType::kDocument, client, interface_registry); frame->SetOpener(opener); - Page& page = *static_cast<WebViewBase*>(web_view)->GetPage(); + Page& page = *static_cast<WebViewImpl*>(web_view)->GetPage(); DCHECK(!page.MainFrame()); frame->InitializeCoreFrame(page, nullptr, name); // Can't force sandbox flags until there's a core frame. @@ -1717,7 +1717,7 @@ DCHECK(GetFrame()); // If frame() doesn't exist, we probably didn't init // properly. - WebViewBase* web_view = ViewImpl(); + WebViewImpl* web_view = ViewImpl(); // Check if we're shutting down. if (!web_view->GetPage()) @@ -1766,7 +1766,7 @@ ToLocalFrame(ToHTMLFrameOwnerElement(element)->ContentFrame())); } -WebViewBase* WebLocalFrameImpl::ViewImpl() const { +WebViewImpl* WebLocalFrameImpl::ViewImpl() const { if (!GetFrame()) return nullptr; return GetFrame()->GetPage()->GetChromeClient().GetWebView();
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h index 0df14dd3..9cc9467e 100644 --- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h +++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h
@@ -71,7 +71,7 @@ class WebScriptExecutionCallback; class WebSpellCheckPanelHostClient; class WebView; -class WebViewBase; +class WebViewImpl; enum class WebFrameLoadType; struct WebContentSecurityPolicyViolation; struct WebPrintParams; @@ -359,7 +359,7 @@ static WebLocalFrameImpl* FromFrame(LocalFrame&); static WebLocalFrameImpl* FromFrameOwnerElement(Element*); - WebViewBase* ViewImpl() const; + WebViewImpl* ViewImpl() const; LocalFrameView* GetFrameView() const { return GetFrame() ? GetFrame()->View() : 0;
diff --git a/third_party/WebKit/Source/core/frame/WebViewFrameWidget.cpp b/third_party/WebKit/Source/core/frame/WebViewFrameWidget.cpp index 46c2f406..1dc8e17d 100644 --- a/third_party/WebKit/Source/core/frame/WebViewFrameWidget.cpp +++ b/third_party/WebKit/Source/core/frame/WebViewFrameWidget.cpp
@@ -4,14 +4,14 @@ #include "core/frame/WebViewFrameWidget.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/WebLocalFrameImpl.h" #include "core/layout/HitTestResult.h" namespace blink { WebViewFrameWidget::WebViewFrameWidget(WebWidgetClient& client, - WebViewBase& web_view, + WebViewImpl& web_view, WebLocalFrameImpl& main_frame) : client_(&client), web_view_(&web_view),
diff --git a/third_party/WebKit/Source/core/frame/WebViewFrameWidget.h b/third_party/WebKit/Source/core/frame/WebViewFrameWidget.h index c286f0b9..2d5c740 100644 --- a/third_party/WebKit/Source/core/frame/WebViewFrameWidget.h +++ b/third_party/WebKit/Source/core/frame/WebViewFrameWidget.h
@@ -15,7 +15,7 @@ namespace blink { -class WebViewBase; +class WebViewImpl; class WebWidgetClient; // Shim class to help normalize the widget interfaces in the Blink public API. @@ -29,7 +29,7 @@ // and just forwards almost everything to it. // After the embedder starts using a WebFrameWidget for the main frame, // WebView will be updated to no longer inherit WebWidget. The eventual goal is -// to unfork the widget code duplicated in WebFrameWidgetImpl and WebViewBase +// to unfork the widget code duplicated in WebFrameWidgetImpl and WebViewImpl // into one class. // A more detailed writeup of this transition can be read at // https://goo.gl/7yVrnb. @@ -38,7 +38,7 @@ public: explicit WebViewFrameWidget(WebWidgetClient&, - WebViewBase&, + WebViewImpl&, WebLocalFrameImpl&); virtual ~WebViewFrameWidget(); @@ -110,7 +110,7 @@ private: WebWidgetClient* client_; - RefPtr<WebViewBase> web_view_; + RefPtr<WebViewImpl> web_view_; Member<WebLocalFrameImpl> main_frame_; SelfKeepAlive<WebViewFrameWidget> self_keep_alive_;
diff --git a/third_party/WebKit/Source/core/html/BUILD.gn b/third_party/WebKit/Source/core/html/BUILD.gn index c1bc643..1b68886f 100644 --- a/third_party/WebKit/Source/core/html/BUILD.gn +++ b/third_party/WebKit/Source/core/html/BUILD.gn
@@ -202,6 +202,8 @@ "HTMLTemplateElement.h", "HTMLTextAreaElement.cpp", "HTMLTextAreaElement.h", + "HTMLTimeElement.cpp", + "HTMLTimeElement.h", "HTMLTitleElement.cpp", "HTMLTitleElement.h", "HTMLTrackElement.cpp",
diff --git a/third_party/WebKit/Source/core/html/HTMLInputElement.cpp b/third_party/WebKit/Source/core/html/HTMLInputElement.cpp index f80e3a5..217f6b2 100644 --- a/third_party/WebKit/Source/core/html/HTMLInputElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLInputElement.cpp
@@ -420,6 +420,13 @@ PseudoStateChanged(CSSSelector::kPseudoRequired); PseudoStateChanged(CSSSelector::kPseudoOptional); } + if (input_type_->SupportsReadOnly() != new_type->SupportsReadOnly()) { + PseudoStateChanged(CSSSelector::kPseudoReadOnly); + PseudoStateChanged(CSSSelector::kPseudoReadWrite); + } + + bool placeholder_changed = + input_type_->SupportsPlaceholder() != new_type->SupportsPlaceholder(); input_type_ = new_type; input_type_view_ = input_type_->CreateView(); @@ -427,6 +434,16 @@ SetNeedsWillValidateCheck(); + if (placeholder_changed) { + // We need to update the UA shadow and then the placeholder visibility flag + // here. Otherwise it would happen as part of attaching the layout tree + // which would be too late in order to make style invalidation work for + // the upcoming frame. + UpdatePlaceholderText(); + UpdatePlaceholderVisibility(); + PseudoStateChanged(CSSSelector::kPseudoPlaceholderShown); + } + ValueMode new_value_mode = input_type_->GetValueMode(); // https://html.spec.whatwg.org/multipage/forms.html#input-type-change
diff --git a/third_party/WebKit/Source/core/html/HTMLOptionsCollection.cpp b/third_party/WebKit/Source/core/html/HTMLOptionsCollection.cpp index 6dd6a7b..3e32106 100644 --- a/third_party/WebKit/Source/core/html/HTMLOptionsCollection.cpp +++ b/third_party/WebKit/Source/core/html/HTMLOptionsCollection.cpp
@@ -27,6 +27,7 @@ #include "bindings/core/v8/HTMLOptionElementOrHTMLOptGroupElement.h" #include "bindings/core/v8/NodeListOrElement.h" #include "core/dom/StaticNodeList.h" +#include "core/frame/UseCounter.h" #include "core/html/HTMLOptionElement.h" #include "core/html/HTMLSelectElement.h" @@ -111,6 +112,9 @@ // FIXME: The spec and Firefox do not return a NodeList. They always return // the first matching Element. + UseCounter::Count( + GetDocument(), + WebFeature::kHTMLOptionsCollectionNamedGetterReturnsNodeList); return_value.setNodeList(StaticElementList::Adopt(named_items)); }
diff --git a/third_party/WebKit/Source/core/html/HTMLTagNames.json5 b/third_party/WebKit/Source/core/html/HTMLTagNames.json5 index 913b6b64c..4e70a308 100644 --- a/third_party/WebKit/Source/core/html/HTMLTagNames.json5 +++ b/third_party/WebKit/Source/core/html/HTMLTagNames.json5
@@ -439,6 +439,10 @@ name: "thead", interfaceName: "HTMLTableSectionElement", }, + { + name: "time", + interfaceName: "HTMLTimeElement", + }, "title", { name: "tr",
diff --git a/third_party/WebKit/Source/core/html/HTMLTimeElement.cpp b/third_party/WebKit/Source/core/html/HTMLTimeElement.cpp new file mode 100644 index 0000000..fb0d036 --- /dev/null +++ b/third_party/WebKit/Source/core/html/HTMLTimeElement.cpp
@@ -0,0 +1,20 @@ +// 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 "core/html/HTMLTimeElement.h" + +#include "core/frame/UseCounter.h" + +namespace blink { + +HTMLTimeElement::HTMLTimeElement(Document& document) + : HTMLElement(HTMLNames::timeTag, document) { + UseCounter::Count(document, WebFeature::kTimeElement); +} + +HTMLTimeElement* HTMLTimeElement::Create(Document& document) { + return new HTMLTimeElement(document); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/html/HTMLTimeElement.h b/third_party/WebKit/Source/core/html/HTMLTimeElement.h new file mode 100644 index 0000000..e2f99b5 --- /dev/null +++ b/third_party/WebKit/Source/core/html/HTMLTimeElement.h
@@ -0,0 +1,24 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef HTMLTimeElement_h +#define HTMLTimeElement_h + +#include "core/html/HTMLElement.h" + +namespace blink { + +class CORE_EXPORT HTMLTimeElement final : public HTMLElement { + DEFINE_WRAPPERTYPEINFO(); + + public: + static HTMLTimeElement* Create(Document&); + + private: + HTMLTimeElement(Document&); +}; + +} // namespace blink + +#endif // HTMLTimeElement_h
diff --git a/third_party/WebKit/Source/core/html/HTMLTimeElement.idl b/third_party/WebKit/Source/core/html/HTMLTimeElement.idl new file mode 100644 index 0000000..48677ffe --- /dev/null +++ b/third_party/WebKit/Source/core/html/HTMLTimeElement.idl
@@ -0,0 +1,10 @@ +// 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. + +// https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-time-element + +[HTMLConstructor] +interface HTMLTimeElement : HTMLElement { + [CEReactions, Reflect] attribute DOMString dateTime; +}; \ No newline at end of file
diff --git a/third_party/WebKit/Source/core/html/HTMLTrackElement.cpp b/third_party/WebKit/Source/core/html/HTMLTrackElement.cpp index 78e6c4e..fdb7fab 100644 --- a/third_party/WebKit/Source/core/html/HTMLTrackElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLTrackElement.cpp
@@ -93,7 +93,7 @@ // As the kind, label, and srclang attributes are set, changed, or removed, // the text track must update accordingly... } else if (name == kindAttr) { - AtomicString lower_case_value = params.new_value.DeprecatedLower(); + AtomicString lower_case_value = params.new_value.LowerASCII(); // 'missing value default' ("subtitles") if (lower_case_value.IsNull()) lower_case_value = TextTrack::SubtitlesKeyword();
diff --git a/third_party/WebKit/Source/core/html/HTMLUnknownElement.cpp b/third_party/WebKit/Source/core/html/HTMLUnknownElement.cpp index 9f382783..3875ba6fc 100644 --- a/third_party/WebKit/Source/core/html/HTMLUnknownElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLUnknownElement.cpp
@@ -4,15 +4,11 @@ #include "core/html/HTMLUnknownElement.h" -#include "core/frame/UseCounter.h" - namespace blink { HTMLUnknownElement::HTMLUnknownElement(const QualifiedName& tag_name, Document& document) : HTMLElement(tag_name, document) { - if (tag_name.LocalName() == "time") - UseCounter::Count(document, WebFeature::kTimeElement); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/LinkResource.cpp b/third_party/WebKit/Source/core/html/LinkResource.cpp index d38e76b..1079910 100644 --- a/third_party/WebKit/Source/core/html/LinkResource.cpp +++ b/third_party/WebKit/Source/core/html/LinkResource.cpp
@@ -37,20 +37,20 @@ namespace blink { -LinkResource::LinkResource(HTMLLinkElement* owner) : owner_(owner) {} +LinkResource::LinkResource(HTMLLinkElement* owner) : owner_(owner) { + DCHECK(owner_); +} LinkResource::~LinkResource() {} bool LinkResource::ShouldLoadResource() const { - return owner_->GetDocument().GetFrame() || - owner_->GetDocument().ImportsController(); + return GetDocument().GetFrame() || GetDocument().ImportsController(); } LocalFrame* LinkResource::LoadingFrame() const { - HTMLImportsController* imports_controller = - owner_->GetDocument().ImportsController(); + HTMLImportsController* imports_controller = GetDocument().ImportsController(); if (!imports_controller) - return owner_->GetDocument().GetFrame(); + return GetDocument().GetFrame(); return imports_controller->Master()->GetFrame(); } @@ -58,10 +58,14 @@ return owner_->GetDocument(); } +const Document& LinkResource::GetDocument() const { + return owner_->GetDocument(); +} + WTF::TextEncoding LinkResource::GetCharset() const { AtomicString charset = owner_->getAttribute(HTMLNames::charsetAttr); - if (charset.IsEmpty() && owner_->GetDocument().GetFrame()) - return owner_->GetDocument().Encoding(); + if (charset.IsEmpty() && GetDocument().GetFrame()) + return GetDocument().Encoding(); return WTF::TextEncoding(charset); }
diff --git a/third_party/WebKit/Source/core/html/LinkResource.h b/third_party/WebKit/Source/core/html/LinkResource.h index 91cd321..bc1ef82 100644 --- a/third_party/WebKit/Source/core/html/LinkResource.h +++ b/third_party/WebKit/Source/core/html/LinkResource.h
@@ -66,6 +66,7 @@ void Load(); Document& GetDocument(); + const Document& GetDocument() const; WTF::TextEncoding GetCharset() const; Member<HTMLLinkElement> owner_;
diff --git a/third_party/WebKit/Source/core/html/forms/ExternalPopupMenu.cpp b/third_party/WebKit/Source/core/html/forms/ExternalPopupMenu.cpp index dbc6a4bc..2dc23d5 100644 --- a/third_party/WebKit/Source/core/html/forms/ExternalPopupMenu.cpp +++ b/third_party/WebKit/Source/core/html/forms/ExternalPopupMenu.cpp
@@ -33,7 +33,6 @@ #include "build/build_config.h" #include "core/dom/NodeComputedStyle.h" #include "core/dom/TaskRunnerHelper.h" -#include "core/exported/WebViewBase.h" #include "core/frame/LocalFrame.h" #include "core/frame/LocalFrameView.h" #include "core/frame/WebLocalFrameImpl.h"
diff --git a/third_party/WebKit/Source/core/html/forms/ExternalPopupMenuTest.cpp b/third_party/WebKit/Source/core/html/forms/ExternalPopupMenuTest.cpp index 1d8ba1c..ffcec5ac 100644 --- a/third_party/WebKit/Source/core/html/forms/ExternalPopupMenuTest.cpp +++ b/third_party/WebKit/Source/core/html/forms/ExternalPopupMenuTest.cpp
@@ -122,7 +122,7 @@ WebView()->UpdateAllLifecyclePhases(); } - WebViewBase* WebView() const { return helper_.WebView(); } + WebViewImpl* WebView() const { return helper_.WebView(); } const ExternalPopupMenuWebFrameClient& Client() const { return web_frame_client_; }
diff --git a/third_party/WebKit/Source/core/html/imports/HTMLImport.cpp b/third_party/WebKit/Source/core/html/imports/HTMLImport.cpp index 2dc5eefb..1e298a0c 100644 --- a/third_party/WebKit/Source/core/html/imports/HTMLImport.cpp +++ b/third_party/WebKit/Source/core/html/imports/HTMLImport.cpp
@@ -110,25 +110,4 @@ import->StateDidChange(); } -#if !defined(NDEBUG) -void HTMLImport::Show() { - Root()->ShowTree(this, 0); -} - -void HTMLImport::ShowTree(HTMLImport* highlight, unsigned depth) { - for (unsigned i = 0; i < depth * 4; ++i) - fprintf(stderr, " "); - - fprintf(stderr, "%s", this == highlight ? "*" : " "); - ShowThis(); - fprintf(stderr, "\n"); - for (HTMLImport* child = FirstChild(); child; child = child->Next()) - child->ShowTree(highlight, depth + 1); -} - -void HTMLImport::ShowThis() { - fprintf(stderr, "%p state=%d", this, state_.PeekValueForDebug()); -} -#endif - } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/imports/HTMLImport.h b/third_party/WebKit/Source/core/html/imports/HTMLImport.h index 70f1f8f9..72b4593 100644 --- a/third_party/WebKit/Source/core/html/imports/HTMLImport.h +++ b/third_party/WebKit/Source/core/html/imports/HTMLImport.h
@@ -75,12 +75,6 @@ static void RecalcTreeState(HTMLImport* root); -#if !defined(NDEBUG) - void Show(); - void ShowTree(HTMLImport* highlight, unsigned depth); - virtual void ShowThis(); -#endif - private: HTMLImportState state_; unsigned sync_ : 1;
diff --git a/third_party/WebKit/Source/core/html/imports/HTMLImportChild.cpp b/third_party/WebKit/Source/core/html/imports/HTMLImportChild.cpp index e4e255a..1c3babf 100644 --- a/third_party/WebKit/Source/core/html/imports/HTMLImportChild.cpp +++ b/third_party/WebKit/Source/core/html/imports/HTMLImportChild.cpp
@@ -47,9 +47,11 @@ HTMLImportChild::HTMLImportChild(const KURL& url, HTMLImportLoader* loader, + HTMLImportChildClient* client, SyncMode sync) - : HTMLImport(sync), url_(url), loader_(loader), client_(nullptr) { - DCHECK(loader); + : HTMLImport(sync), url_(url), loader_(loader), client_(client) { + DCHECK(loader_); + DCHECK(client_); } HTMLImportChild::~HTMLImportChild() {} @@ -150,12 +152,6 @@ return loader_; } -void HTMLImportChild::SetClient(HTMLImportChildClient* client) { - DCHECK(client); - DCHECK(!client_); - client_ = client; -} - HTMLLinkElement* HTMLImportChild::Link() const { if (!client_) return nullptr; @@ -163,14 +159,16 @@ } // Ensuring following invariants against the import tree: -// - HTMLImportChild::firstImport() is the "first import" of the DFS order of -// the import tree. -// - The "first import" manages all the children that is loaded by the document. +// - HTMLImportLoader::FirstImport() is the "first import" of the DFS order of +// the import tree loaded by the loader. +// - The "first import" manages all the children that are loaded by the +// document. void HTMLImportChild::Normalize() { - if (!Loader()->IsFirstImport(this) && - this->Precedes(Loader()->FirstImport())) { - HTMLImportChild* old_first = Loader()->FirstImport(); - Loader()->MoveToFirst(this); + DCHECK(loader_); + + if (!loader_->IsFirstImport(this) && this->Precedes(loader_->FirstImport())) { + HTMLImportChild* old_first = loader_->FirstImport(); + loader_->MoveToFirst(this); TakeChildrenFrom(old_first); } @@ -182,16 +180,6 @@ } } -#if !defined(NDEBUG) -void HTMLImportChild::ShowThis() { - bool is_first = Loader() ? Loader()->IsFirstImport(this) : false; - HTMLImport::ShowThis(); - fprintf(stderr, " loader=%p first=%d, step=%p sync=%s url=%s", loader_.Get(), - is_first, custom_element_microtask_step_.Get(), IsSync() ? "Y" : "N", - Url().GetString().Utf8().data()); -} -#endif - DEFINE_TRACE(HTMLImportChild) { visitor->Trace(custom_element_microtask_step_); visitor->Trace(loader_);
diff --git a/third_party/WebKit/Source/core/html/imports/HTMLImportChild.h b/third_party/WebKit/Source/core/html/imports/HTMLImportChild.h index 6793e4c0..ddb73ac 100644 --- a/third_party/WebKit/Source/core/html/imports/HTMLImportChild.h +++ b/third_party/WebKit/Source/core/html/imports/HTMLImportChild.h
@@ -50,7 +50,10 @@ // class HTMLImportChild final : public HTMLImport { public: - HTMLImportChild(const KURL&, HTMLImportLoader*, SyncMode); + HTMLImportChild(const KURL&, + HTMLImportLoader*, + HTMLImportChildClient*, + SyncMode); ~HTMLImportChild() final; void Dispose(); @@ -69,12 +72,6 @@ void StateDidChange() final; DECLARE_VIRTUAL_TRACE(); -#if !defined(NDEBUG) - void ShowThis() final; -#endif - - void SetClient(HTMLImportChildClient*); - void DidFinishLoading(); void DidFinishUpgradingCustomElements(); void Normalize();
diff --git a/third_party/WebKit/Source/core/html/imports/HTMLImportsController.cpp b/third_party/WebKit/Source/core/html/imports/HTMLImportsController.cpp index 8079e2d..c3625ef3 100644 --- a/third_party/WebKit/Source/core/html/imports/HTMLImportsController.cpp +++ b/third_party/WebKit/Source/core/html/imports/HTMLImportsController.cpp
@@ -79,22 +79,26 @@ WebFeature::kHTMLImportsAsyncAttribute); } - HTMLImportChild* child = new HTMLImportChild(url, loader, mode); - child->SetClient(client); + HTMLImportChild* child = new HTMLImportChild(url, loader, client, mode); parent->AppendImport(child); loader->AddImport(child); return root_->Add(child); } -HTMLImportChild* HTMLImportsController::Load(HTMLImport* parent, +HTMLImportChild* HTMLImportsController::Load(const Document& parent_document, HTMLImportChildClient* client, FetchParameters& params) { + DCHECK(client); + + HTMLImportLoader* parent_loader = LoaderFor(parent_document); + HTMLImport* parent = + parent_loader ? static_cast<HTMLImport*>(parent_loader->FirstImport()) + : static_cast<HTMLImport*>(root_); + const KURL& url = params.Url(); DCHECK(!url.IsEmpty()); DCHECK(url.IsValid()); - DCHECK(parent == root_ || ToHTMLImportChild(parent)->Loader()->IsFirstImport( - ToHTMLImportChild(parent))); if (HTMLImportChild* child_to_share_with = root_->Find(url)) { HTMLImportLoader* loader = child_to_share_with->Loader();
diff --git a/third_party/WebKit/Source/core/html/imports/HTMLImportsController.h b/third_party/WebKit/Source/core/html/imports/HTMLImportsController.h index 851af95a..072dc544 100644 --- a/third_party/WebKit/Source/core/html/imports/HTMLImportsController.h +++ b/third_party/WebKit/Source/core/html/imports/HTMLImportsController.h
@@ -58,7 +58,7 @@ HTMLImportTreeRoot* Root() const { return root_; } bool ShouldBlockScriptExecution(const Document&) const; - HTMLImportChild* Load(HTMLImport* parent, + HTMLImportChild* Load(const Document&, HTMLImportChildClient*, FetchParameters&);
diff --git a/third_party/WebKit/Source/core/html/imports/LinkImport.cpp b/third_party/WebKit/Source/core/html/imports/LinkImport.cpp index 253d6ac9..63a8bd850 100644 --- a/third_party/WebKit/Source/core/html/imports/LinkImport.cpp +++ b/third_party/WebKit/Source/core/html/imports/LinkImport.cpp
@@ -72,24 +72,12 @@ if (!ShouldLoadResource()) return; - if (!GetDocument().ImportsController()) { - // The document should be the master. - Document& master = GetDocument(); - DCHECK(master.GetFrame()); - master.CreateImportsController(); - } - const KURL& url = owner_->GetNonEmptyURLAttribute(HTMLNames::hrefAttr); if (url.IsEmpty() || !url.IsValid()) { DidFinish(); return; } - HTMLImportsController* controller = GetDocument().ImportsController(); - HTMLImportLoader* loader = GetDocument().ImportLoader(); - HTMLImport* parent = loader ? static_cast<HTMLImport*>(loader->FirstImport()) - : static_cast<HTMLImport*>(controller->Root()); - ResourceRequest resource_request(GetDocument().CompleteURL(url)); ReferrerPolicy referrer_policy = owner_->GetReferrerPolicy(); if (referrer_policy != kReferrerPolicyDefault) { @@ -104,7 +92,8 @@ params.SetCharset(GetCharset()); params.SetContentSecurityPolicyNonce(owner_->nonce()); - child_ = controller->Load(parent, this, params); + HTMLImportsController* controller = GetDocument().EnsureImportsController(); + child_ = controller->Load(GetDocument(), this, params); if (!child_) { DidFinish(); return;
diff --git a/third_party/WebKit/Source/core/inspector/DevToolsEmulator.cpp b/third_party/WebKit/Source/core/inspector/DevToolsEmulator.cpp index 888aac3..51ca6d3 100644 --- a/third_party/WebKit/Source/core/inspector/DevToolsEmulator.cpp +++ b/third_party/WebKit/Source/core/inspector/DevToolsEmulator.cpp
@@ -5,7 +5,7 @@ #include "core/inspector/DevToolsEmulator.h" #include "core/events/WebInputEventConversion.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalFrameView.h" #include "core/frame/Settings.h" #include "core/frame/VisualViewport.h" @@ -59,7 +59,7 @@ namespace blink { -DevToolsEmulator::DevToolsEmulator(WebViewBase* web_view) +DevToolsEmulator::DevToolsEmulator(WebViewImpl* web_view) : web_view_(web_view), device_metrics_enabled_(false), emulate_mobile_enabled_(false), @@ -102,7 +102,7 @@ DevToolsEmulator::~DevToolsEmulator() {} -DevToolsEmulator* DevToolsEmulator::Create(WebViewBase* web_view_base) { +DevToolsEmulator* DevToolsEmulator::Create(WebViewImpl* web_view_base) { return new DevToolsEmulator(web_view_base); }
diff --git a/third_party/WebKit/Source/core/inspector/DevToolsEmulator.h b/third_party/WebKit/Source/core/inspector/DevToolsEmulator.h index f4bdd471..fbb555c 100644 --- a/third_party/WebKit/Source/core/inspector/DevToolsEmulator.h +++ b/third_party/WebKit/Source/core/inspector/DevToolsEmulator.h
@@ -21,13 +21,13 @@ class IntRect; class TransformationMatrix; class WebInputEvent; -class WebViewBase; +class WebViewImpl; class CORE_EXPORT DevToolsEmulator final : public GarbageCollectedFinalized<DevToolsEmulator> { public: ~DevToolsEmulator(); - static DevToolsEmulator* Create(WebViewBase*); + static DevToolsEmulator* Create(WebViewImpl*); DECLARE_TRACE(); // Settings overrides. @@ -65,7 +65,7 @@ WTF::Optional<IntRect> VisibleContentRectForPainting() const; private: - explicit DevToolsEmulator(WebViewBase*); + explicit DevToolsEmulator(WebViewImpl*); void EnableMobileEmulation(); void DisableMobileEmulation(); @@ -78,7 +78,7 @@ void ApplyViewportOverride(TransformationMatrix*); void UpdateRootLayerTransform(); - WebViewBase* web_view_; + WebViewImpl* web_view_; bool device_metrics_enabled_; bool emulate_mobile_enabled_;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp index 3a54c71..97ba0a3 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
@@ -2228,7 +2228,10 @@ Response InspectorCSSAgent::getBackgroundColors( int node_id, - Maybe<protocol::Array<String>>* result) { + Maybe<protocol::Array<String>>* background_colors, + Maybe<String>* computed_font_size, + Maybe<String>* computed_font_weight, + Maybe<String>* computed_body_font_size) { Element* element = nullptr; Response response = dom_agent_->AssertElement(node_id, element); if (!response.isSuccess()) @@ -2274,9 +2277,28 @@ } } - *result = protocol::Array<String>::create(); - for (auto color : colors) - result->fromJust()->addItem(color.SerializedAsCSSComponentValue()); + *background_colors = protocol::Array<String>::create(); + for (auto color : colors) { + background_colors->fromJust()->addItem( + color.SerializedAsCSSComponentValue()); + } + + CSSComputedStyleDeclaration* computed_style_info = + CSSComputedStyleDeclaration::Create(element, true); + const CSSValue* font_size = + computed_style_info->GetPropertyCSSValue(CSSPropertyFontSize); + *computed_font_size = font_size->CssText(); + const CSSValue* font_weight = + computed_style_info->GetPropertyCSSValue(CSSPropertyFontWeight); + *computed_font_weight = font_weight->CssText(); + + HTMLElement* body = element->GetDocument().body(); + CSSComputedStyleDeclaration* computed_style_body = + CSSComputedStyleDeclaration::Create(body, true); + const CSSValue* body_font_size = + computed_style_body->GetPropertyCSSValue(CSSPropertyFontSize); + *computed_body_font_size = body_font_size->CssText(); + return Response::OK(); }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h index 8639c4e..0f4af8c 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h
@@ -191,7 +191,10 @@ const String& value) override; protocol::Response getBackgroundColors( int node_id, - protocol::Maybe<protocol::Array<String>>* background_colors) override; + protocol::Maybe<protocol::Array<String>>* background_colors, + protocol::Maybe<String>* computed_font_size, + protocol::Maybe<String>* computed_font_weight, + protocol::Maybe<String>* computed_body_font_size) override; protocol::Response startRuleUsageTracking() override; protocol::Response takeCoverageDelta(
diff --git a/third_party/WebKit/Source/core/inspector/InspectorEmulationAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorEmulationAgent.cpp index 69785e0e..218b64a 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorEmulationAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorEmulationAgent.cpp
@@ -4,7 +4,7 @@ #include "core/inspector/InspectorEmulationAgent.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalFrameView.h" #include "core/frame/Settings.h" #include "core/frame/WebLocalFrameImpl.h" @@ -45,7 +45,7 @@ InspectorEmulationAgent::~InspectorEmulationAgent() {} -WebViewBase* InspectorEmulationAgent::GetWebViewBase() { +WebViewImpl* InspectorEmulationAgent::GetWebViewImpl() { return web_local_frame_->ViewImpl(); } @@ -81,18 +81,18 @@ } Response InspectorEmulationAgent::resetPageScaleFactor() { - GetWebViewBase()->ResetScaleStateImmediately(); + GetWebViewImpl()->ResetScaleStateImmediately(); return Response::OK(); } Response InspectorEmulationAgent::setPageScaleFactor(double page_scale_factor) { - GetWebViewBase()->SetPageScaleFactor(static_cast<float>(page_scale_factor)); + GetWebViewImpl()->SetPageScaleFactor(static_cast<float>(page_scale_factor)); return Response::OK(); } Response InspectorEmulationAgent::setScriptExecutionDisabled(bool value) { state_->setBoolean(EmulationAgentState::kScriptExecutionDisabled, value); - GetWebViewBase()->GetDevToolsEmulator()->SetScriptExecutionDisabled(value); + GetWebViewImpl()->GetDevToolsEmulator()->SetScriptExecutionDisabled(value); return Response::OK(); } @@ -100,14 +100,14 @@ bool enabled, Maybe<String> configuration) { state_->setBoolean(EmulationAgentState::kTouchEventEmulationEnabled, enabled); - GetWebViewBase()->GetDevToolsEmulator()->SetTouchEventEmulationEnabled( + GetWebViewImpl()->GetDevToolsEmulator()->SetTouchEventEmulationEnabled( enabled); return Response::OK(); } Response InspectorEmulationAgent::setEmulatedMedia(const String& media) { state_->setString(EmulationAgentState::kEmulatedMedia, media); - GetWebViewBase()->GetPage()->GetSettings().SetMediaTypeOverride(media); + GetWebViewImpl()->GetPage()->GetSettings().SetMediaTypeOverride(media); return Response::OK(); } @@ -152,7 +152,7 @@ Maybe<protocol::DOM::RGBA> color) { if (!color.isJust()) { // Clear the override and state. - GetWebViewBase()->ClearBaseBackgroundColorOverride(); + GetWebViewImpl()->ClearBaseBackgroundColorOverride(); state_->remove(EmulationAgentState::kDefaultBackgroundColorOverrideRGBA); return Response::OK(); } @@ -162,7 +162,7 @@ rgba->toValue()); // Clamping of values is done by Color() constructor. int alpha = lroundf(255.0f * rgba->getA(1.0f)); - GetWebViewBase()->SetBaseBackgroundColorOverride( + GetWebViewImpl()->SetBaseBackgroundColorOverride( Color(rgba->getR(), rgba->getG(), rgba->getB(), alpha).Rgb()); return Response::OK(); }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorEmulationAgent.h b/third_party/WebKit/Source/core/inspector/InspectorEmulationAgent.h index 144f93d..f942dc3 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorEmulationAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorEmulationAgent.h
@@ -12,7 +12,7 @@ namespace blink { class WebLocalFrameImpl; -class WebViewBase; +class WebViewImpl; namespace protocol { namespace DOM { @@ -59,7 +59,7 @@ private: InspectorEmulationAgent(WebLocalFrameImpl*, Client*); - WebViewBase* GetWebViewBase(); + WebViewImpl* GetWebViewImpl(); void VirtualTimeBudgetExpired(); Member<WebLocalFrameImpl> web_local_frame_;
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json index 154fc77d..0e7a54e 100644 --- a/third_party/WebKit/Source/core/inspector/browser_protocol.json +++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -3326,7 +3326,11 @@ { "name": "nodeId", "$ref": "DOM.NodeId", "description": "Id of the node to get background colors for." } ], "returns": [ - { "name": "backgroundColors", "type": "array", "items": { "type": "string" }, "description": "The range of background colors behind this element, if it contains any visible text. If no visible text is present, this will be undefined. In the case of a flat background color, this will consist of simply that color. In the case of a gradient, this will consist of each of the color stops. For anything more complicated, this will be an empty array. Images will be ignored (as if the image had failed to load).", "optional": true } + { "name": "backgroundColors", "type": "array", "items": { "type": "string" }, "description": "The range of background colors behind this element, if it contains any visible text. If no visible text is present, this will be undefined. In the case of a flat background color, this will consist of simply that color. In the case of a gradient, this will consist of each of the color stops. For anything more complicated, this will be an empty array. Images will be ignored (as if the image had failed to load).", "optional": true }, + { "name": "computedFontSize", "type": "string", "description": "The computed font size for this node, as a CSS computed value string (e.g. '12px').", "optional": true }, + { "name": "computedFontWeight", "type": "string", "description": "The computed font weight for this node, as a CSS computed value string (e.g. 'normal' or '100').", "optional": true }, + + { "name": "computedBodyFontSize", "type": "string", "description": "The computed font size for the document body, as a computed CSS value string (e.g. '16px').", "optional": true } ], "experimental": true },
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp index 971422d7..47dfd47c 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -35,13 +35,13 @@ #include "core/css/resolver/StyleResolver.h" #include "core/dom/AXObjectCache.h" #include "core/dom/ElementTraversal.h" +#include "core/dom/FirstLetterPseudoElement.h" #include "core/dom/ShadowRoot.h" #include "core/dom/StyleChangeReason.h" #include "core/dom/StyleEngine.h" #include "core/editing/EditingUtilities.h" #include "core/editing/FrameSelection.h" #include "core/editing/TextAffinity.h" -#include "core/editing/VisibleUnits.h" #include "core/frame/DeprecatedScheduleStyleRecalcDuringLayout.h" #include "core/frame/EventHandlerRegistry.h" #include "core/frame/LocalFrame.h" @@ -69,6 +69,7 @@ #include "core/layout/LayoutTableCell.h" #include "core/layout/LayoutTableCol.h" #include "core/layout/LayoutTableRow.h" +#include "core/layout/LayoutTextFragment.h" #include "core/layout/LayoutTheme.h" #include "core/layout/LayoutView.h" #include "core/layout/api/LayoutAPIShim.h" @@ -3532,6 +3533,61 @@ } } +// Note about ::first-letter pseudo-element: +// When an element has ::first-letter pseudo-element, first letter characters +// are taken from |Text| node and first letter characters are considered +// as content of <pseudo:first-letter>. +// For following HTML, +// <style>div::first-letter {color: red}</style> +// <div>abc</div> +// we have following layout tree: +// LayoutBlockFlow {DIV} at (0,0) size 784x55 +// LayoutInline {<pseudo:first-letter>} at (0,0) size 22x53 +// LayoutTextFragment (anonymous) at (0,1) size 22x53 +// text run at (0,1) width 22: "a" +// LayoutTextFragment {#text} at (21,30) size 16x17 +// text run at (21,30) width 16: "bc" +// In this case, |Text::layoutObject()| for "abc" returns |LayoutTextFragment| +// containing "bc", and it is called remaining part. +// +// Even if |Text| node contains only first-letter characters, e.g. just "a", +// remaining part of |LayoutTextFragment|, with |fragmentLength()| == 0, is +// appeared in layout tree. +// +// When |Text| node contains only first-letter characters and whitespaces, e.g. +// "B\n", associated |LayoutTextFragment| is first-letter part instead of +// remaining part. +// +// Punctuation characters are considered as first-letter. For "(1)ab", +// "(1)" are first-letter part and "ab" are remaining part. +const LayoutObject* AssociatedLayoutObjectOf(const Node& node, + int offset_in_node) { + DCHECK_GE(offset_in_node, 0); + LayoutObject* layout_object = node.GetLayoutObject(); + if (!node.IsTextNode() || !layout_object || + !ToLayoutText(layout_object)->IsTextFragment()) + return layout_object; + LayoutTextFragment* layout_text_fragment = + ToLayoutTextFragment(layout_object); + if (!layout_text_fragment->IsRemainingTextLayoutObject()) { + DCHECK_LE( + static_cast<unsigned>(offset_in_node), + layout_text_fragment->Start() + layout_text_fragment->FragmentLength()); + return layout_text_fragment; + } + if (layout_text_fragment->FragmentLength() && + static_cast<unsigned>(offset_in_node) >= layout_text_fragment->Start()) + return layout_object; + LayoutObject* first_letter_layout_object = + layout_text_fragment->GetFirstLetterPseudoElement()->GetLayoutObject(); + // TODO(yosin): We're not sure when |firstLetterLayoutObject| has + // multiple child layout object. + LayoutObject* child = first_letter_layout_object->SlowFirstChild(); + CHECK(child && child->IsText()); + DCHECK_EQ(child, first_letter_layout_object->SlowLastChild()); + return child; +} + } // namespace blink #ifndef NDEBUG
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.h b/third_party/WebKit/Source/core/layout/LayoutObject.h index 65887ed1..5780261c 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObject.h +++ b/third_party/WebKit/Source/core/layout/LayoutObject.h
@@ -2749,6 +2749,9 @@ return AdjustScrollForAbsoluteZoom(value, layout_object.StyleRef()); } +CORE_EXPORT const LayoutObject* AssociatedLayoutObjectOf(const Node&, + int offset_in_node); + #define DEFINE_LAYOUT_OBJECT_TYPE_CASTS(thisType, predicate) \ DEFINE_TYPE_CASTS(thisType, LayoutObject, object, object->predicate, \ object.predicate)
diff --git a/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp b/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp index b809285..ab72d056 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp
@@ -4,8 +4,10 @@ #include "core/layout/LayoutObject.h" +#include "bindings/core/v8/V8BindingForTesting.h" #include "core/frame/LocalFrameView.h" #include "core/layout/LayoutTestHelper.h" +#include "core/layout/LayoutTextFragment.h" #include "core/layout/LayoutView.h" #include "platform/json/JSONValues.h" #include "platform/testing/RuntimeEnabledFeaturesTestHelpers.h" @@ -288,4 +290,76 @@ EXPECT_FALSE(parent->NeedsPaintOffsetAndVisualRectUpdate()); } +TEST_F(LayoutObjectTest, AssociatedLayoutObjectOfFirstLetterPunctuations) { + const char* body_content = + "<style>p:first-letter {color:red;}</style><p id=sample>(a)bc</p>"; + SetBodyInnerHTML(body_content); + + Node* sample = GetDocument().getElementById("sample"); + Node* text = sample->firstChild(); + + const LayoutTextFragment* layout_object0 = + ToLayoutTextFragment(AssociatedLayoutObjectOf(*text, 0)); + EXPECT_FALSE(layout_object0->IsRemainingTextLayoutObject()); + + const LayoutTextFragment* layout_object1 = + ToLayoutTextFragment(AssociatedLayoutObjectOf(*text, 1)); + EXPECT_EQ(layout_object0, layout_object1) + << "A character 'a' should be part of first letter."; + + const LayoutTextFragment* layout_object2 = + ToLayoutTextFragment(AssociatedLayoutObjectOf(*text, 2)); + EXPECT_EQ(layout_object0, layout_object2) + << "close parenthesis should be part of first letter."; + + const LayoutTextFragment* layout_object3 = + ToLayoutTextFragment(AssociatedLayoutObjectOf(*text, 3)); + EXPECT_TRUE(layout_object3->IsRemainingTextLayoutObject()); +} + +TEST_F(LayoutObjectTest, AssociatedLayoutObjectOfFirstLetterSplit) { + V8TestingScope scope; + + const char* body_content = + "<style>p:first-letter {color:red;}</style><p id=sample>abc</p>"; + SetBodyInnerHTML(body_content); + + Node* sample = GetDocument().getElementById("sample"); + Node* first_letter = sample->firstChild(); + // Split "abc" into "a" "bc" + ToText(first_letter)->splitText(1, ASSERT_NO_EXCEPTION); + GetDocument().View()->UpdateAllLifecyclePhases(); + + const LayoutTextFragment* layout_object0 = + ToLayoutTextFragment(AssociatedLayoutObjectOf(*first_letter, 0)); + EXPECT_FALSE(layout_object0->IsRemainingTextLayoutObject()); + + const LayoutTextFragment* layout_object1 = + ToLayoutTextFragment(AssociatedLayoutObjectOf(*first_letter, 1)); + EXPECT_EQ(layout_object0, layout_object1); +} + +TEST_F(LayoutObjectTest, + AssociatedLayoutObjectOfFirstLetterWithTrailingWhitespace) { + const char* body_content = + "<style>div:first-letter {color:red;}</style><div id=sample>a\n " + "<div></div></div>"; + SetBodyInnerHTML(body_content); + + Node* sample = GetDocument().getElementById("sample"); + Node* text = sample->firstChild(); + + const LayoutTextFragment* layout_object0 = + ToLayoutTextFragment(AssociatedLayoutObjectOf(*text, 0)); + EXPECT_FALSE(layout_object0->IsRemainingTextLayoutObject()); + + const LayoutTextFragment* layout_object1 = + ToLayoutTextFragment(AssociatedLayoutObjectOf(*text, 1)); + EXPECT_TRUE(layout_object1->IsRemainingTextLayoutObject()); + + const LayoutTextFragment* layout_object2 = + ToLayoutTextFragment(AssociatedLayoutObjectOf(*text, 2)); + EXPECT_EQ(layout_object1, layout_object2); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedSelectionBound.h b/third_party/WebKit/Source/core/layout/compositing/CompositedSelectionBound.h index 168215b4..f15797b 100644 --- a/third_party/WebKit/Source/core/layout/compositing/CompositedSelectionBound.h +++ b/third_party/WebKit/Source/core/layout/compositing/CompositedSelectionBound.h
@@ -39,7 +39,8 @@ struct CompositedSelectionBound { STACK_ALLOCATED(); - CompositedSelectionBound() : layer(nullptr), is_text_direction_rtl(false) {} + CompositedSelectionBound() + : layer(nullptr), is_text_direction_rtl(false), hidden(false) {} // The structure describes the position of a caret in space of the // GraphicsLayer the caret resides in. Where edgeTopInLayer is the top point @@ -50,6 +51,9 @@ FloatPoint edge_bottom_in_layer; bool is_text_direction_rtl; + + // Whether this bound is hidden (clipped out/occluded). + bool hidden; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp b/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp index b1699d83..e603361 100644 --- a/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp +++ b/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp
@@ -1177,9 +1177,8 @@ // In RLS mode, LayoutView scrolling contents layer gets this element ID (in // CompositedLayerMapping::updateElementIdAndCompositorMutableProperties). if (!RuntimeEnabledFeatures::RootLayerScrollingEnabled()) { - scroll_layer_->SetElementId(CompositorElementIdFromDOMNodeId( - DOMNodeIds::IdForNode(&layout_view_.GetDocument()), - CompositorElementIdNamespace::kRootScroll)); + scroll_layer_->SetElementId( + layout_view_.GetFrameView()->GetCompositorElementId()); } // Hook them up
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc index b96f806e..e466afe 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc
@@ -216,10 +216,8 @@ // Reaches here if the LayoutTextFragment is due to a LayoutQuote. return layout_text.GetText(); } - unsigned first_letter_length = node->GetLayoutObject()->TextStartOffset(); - if (text_fragment.IsRemainingTextLayoutObject()) - return node->data().Substring(first_letter_length); - return node->data().Substring(0, first_letter_length); + return node->data().Substring(text_fragment.Start(), + text_fragment.FragmentLength()); } Node* node = layout_text.GetNode(); @@ -733,8 +731,7 @@ // static Optional<NGInlineNode> GetNGInlineNodeFor(const Node& node, unsigned offset) { - // TODO(xiaochengh): Move/Reimplement AssociatedLayoutObjectOf in core/layout. - LayoutObject* layout_object = AssociatedLayoutObjectOf(node, offset); + const LayoutObject* layout_object = AssociatedLayoutObjectOf(node, offset); if (!layout_object || !layout_object->IsInline()) return WTF::nullopt; LayoutBox* box = layout_object->EnclosingBox(); @@ -748,8 +745,7 @@ const NGOffsetMappingUnit* NGInlineNode::GetMappingUnitForDOMOffset( const Node& node, unsigned offset) { - // TODO(xiaochengh): Move/Reimplement AssociatedLayoutObjectOf in core/layout. - LayoutObject* layout_object = AssociatedLayoutObjectOf(node, offset); + const LayoutObject* layout_object = AssociatedLayoutObjectOf(node, offset); if (!layout_object || !layout_object->IsText()) return nullptr;
diff --git a/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc b/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc index de176c4..0c67f7f 100644 --- a/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc +++ b/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc
@@ -88,6 +88,25 @@ for (NGOutOfFlowPositionedDescendant descendant : result->OutOfFlowPositionedDescendants()) descendant.node.UseOldOutOfFlowPositioning(); + + NGPhysicalBoxFragment* fragment = + ToNGPhysicalBoxFragment(result->PhysicalFragment().Get()); + + // This object has already been positioned in legacy layout by our containing + // block. Copy the position and place the fragment. + const LayoutBlock* containing_block = ContainingBlock(); + NGPhysicalOffset physical_offset; + if (containing_block) { + NGPhysicalSize containing_block_size(containing_block->Size().Width(), + containing_block->Size().Height()); + NGLogicalOffset logical_offset(LogicalLeft(), LogicalTop()); + physical_offset = logical_offset.ConvertToPhysical( + constraint_space->WritingMode(), constraint_space->Direction(), + containing_block_size, fragment->Size()); + } + fragment->SetOffset(physical_offset); + + physical_root_fragment_for_testing_ = fragment; } void LayoutNGBlockFlow::UpdateMargins(
diff --git a/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.h b/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.h index d9df556..6d729115 100644 --- a/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.h +++ b/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.h
@@ -15,6 +15,7 @@ class NGBreakToken; class NGConstraintSpace; class NGLayoutResult; +class NGPhysicalBoxFragment; // This overrides the default layout block algorithm to use Layout NG. class CORE_EXPORT LayoutNGBlockFlow final : public LayoutBlockFlow { @@ -43,6 +44,10 @@ NGBreakToken*, RefPtr<NGLayoutResult>); + RefPtr<NGPhysicalBoxFragment> GetFragmentForTesting() const { + return physical_root_fragment_for_testing_; + } + private: bool IsOfType(LayoutObjectType) const override; @@ -52,6 +57,7 @@ RefPtr<NGLayoutResult> cached_result_; RefPtr<NGConstraintSpace> cached_constraint_space_; + RefPtr<NGPhysicalBoxFragment> physical_root_fragment_for_testing_; }; DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutNGBlockFlow, IsLayoutNGBlockFlow());
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc index d0ad859..df8b1f22 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc
@@ -2771,5 +2771,26 @@ EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(-10)), child->Offset()); } +// This test assumes that tables are not yet implemented in LayoutNG. +TEST_F(NGBlockLayoutAlgorithmTest, RootFragmentOffsetInsideLegacy) { + SetBodyInnerHTML(R"HTML( + <!DOCTYPE html> + <div style="display:table-cell;"> + <div id="innerNGRoot" style="margin-top:10px; margin-left:20px;"></div> + </div> + )HTML"); + + GetDocument().View()->UpdateAllLifecyclePhases(); + const LayoutObject* innerNGRoot = GetLayoutObjectByElementId("innerNGRoot"); + + ASSERT_TRUE(innerNGRoot->IsLayoutNGBlockFlow()); + RefPtr<NGPhysicalBoxFragment> fragment = + ToLayoutNGBlockFlow(innerNGRoot)->GetFragmentForTesting(); + + ASSERT_TRUE(fragment.Get()); + EXPECT_EQ(NGPhysicalOffset(LayoutUnit(20), LayoutUnit(10)), + fragment->Offset()); +} + } // namespace } // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/CookieJar.cpp b/third_party/WebKit/Source/core/loader/CookieJar.cpp index 2c697070..14e9b2b0 100644 --- a/third_party/WebKit/Source/core/loader/CookieJar.cpp +++ b/third_party/WebKit/Source/core/loader/CookieJar.cpp
@@ -33,6 +33,7 @@ #include "core/dom/Document.h" #include "core/frame/LocalFrame.h" #include "core/frame/LocalFrameClient.h" +#include "platform/Histogram.h" #include "public/platform/Platform.h" #include "public/platform/WebCookieJar.h" #include "public/platform/WebURL.h" @@ -49,6 +50,8 @@ WebCookieJar* cookie_jar = ToCookieJar(document); if (!cookie_jar) return String(); + + SCOPED_BLINK_UMA_HISTOGRAM_TIMER("Blink.CookieJar.SyncCookiesTime"); return cookie_jar->Cookies(url, document->FirstPartyForCookies()); }
diff --git a/third_party/WebKit/Source/core/loader/EmptyClients.h b/third_party/WebKit/Source/core/loader/EmptyClients.h index ce4f49c..dce0445 100644 --- a/third_party/WebKit/Source/core/loader/EmptyClients.h +++ b/third_party/WebKit/Source/core/loader/EmptyClients.h
@@ -85,7 +85,7 @@ ~EmptyChromeClient() override {} void ChromeDestroyed() override {} - WebViewBase* GetWebView() const override { return nullptr; } + WebViewImpl* GetWebView() const override { return nullptr; } void SetWindowRect(const IntRect&, LocalFrame&) override {} IntRect RootWindowRect() override { return IntRect(); }
diff --git a/third_party/WebKit/Source/core/page/ChromeClient.h b/third_party/WebKit/Source/core/page/ChromeClient.h index 1eec0354..70095ff6 100644 --- a/third_party/WebKit/Source/core/page/ChromeClient.h +++ b/third_party/WebKit/Source/core/page/ChromeClient.h
@@ -79,7 +79,7 @@ class WebImage; class WebLayer; class WebLayerTreeView; -class WebViewBase; +class WebViewImpl; struct CompositedSelection; struct DateTimeChooserParameters; @@ -167,7 +167,7 @@ String& result); virtual bool TabsToLinks() = 0; - virtual WebViewBase* GetWebView() const = 0; + virtual WebViewImpl* GetWebView() const = 0; // Methods used by PlatformChromeClient. virtual WebScreenInfo GetScreenInfo() const = 0; @@ -235,13 +235,13 @@ // Pass nullptr as the GraphicsLayer to detach the root layer. // This sets the graphics layer for the LocalFrame's WebWidget, if it has - // one. Otherwise it sets it for the WebViewBase. + // one. Otherwise it sets it for the WebViewImpl. virtual void AttachRootGraphicsLayer(GraphicsLayer*, LocalFrame* local_root) = 0; // Pass nullptr as the WebLayer to detach the root layer. // This sets the WebLayer for the LocalFrame's WebWidget, if it has - // one. Otherwise it sets it for the WebViewBase. + // one. Otherwise it sets it for the WebViewImpl. virtual void AttachRootLayer(WebLayer*, LocalFrame* local_root) = 0; virtual void AttachCompositorAnimationTimeline(CompositorAnimationTimeline*,
diff --git a/third_party/WebKit/Source/core/page/ChromeClientImpl.cpp b/third_party/WebKit/Source/core/page/ChromeClientImpl.cpp index 6ef3985..dfb29b89 100644 --- a/third_party/WebKit/Source/core/page/ChromeClientImpl.cpp +++ b/third_party/WebKit/Source/core/page/ChromeClientImpl.cpp
@@ -44,7 +44,7 @@ #include "core/exported/WebPluginContainerImpl.h" #include "core/exported/WebRemoteFrameImpl.h" #include "core/exported/WebSettingsImpl.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalFrameView.h" #include "core/frame/Settings.h" #include "core/frame/UseCounter.h" @@ -156,23 +156,23 @@ class CompositorAnimationTimeline; -ChromeClientImpl::ChromeClientImpl(WebViewBase* web_view) +ChromeClientImpl::ChromeClientImpl(WebViewImpl* web_view) : web_view_(web_view), cursor_overridden_(false), did_request_non_empty_tool_tip_(false) {} ChromeClientImpl::~ChromeClientImpl() {} -ChromeClientImpl* ChromeClientImpl::Create(WebViewBase* web_view) { +ChromeClientImpl* ChromeClientImpl::Create(WebViewImpl* web_view) { return new ChromeClientImpl(web_view); } -WebViewBase* ChromeClientImpl::GetWebView() const { +WebViewImpl* ChromeClientImpl::GetWebView() const { return web_view_; } void ChromeClientImpl::ChromeDestroyed() { - // Our lifetime is bound to the WebViewBase. + // Our lifetime is bound to the WebViewImpl. } void ChromeClientImpl::SetWindowRect(const IntRect& r, LocalFrame& frame) { @@ -272,8 +272,8 @@ const AtomicString& frame_name = !EqualIgnoringASCIICase(r.FrameName(), "_blank") ? r.FrameName() : g_empty_atom; - WebViewBase* new_view = - static_cast<WebViewBase*>(web_view_->Client()->CreateView( + WebViewImpl* new_view = + static_cast<WebViewImpl*>(web_view_->Client()->CreateView( WebLocalFrameImpl::FromFrame(frame), WrappedResourceRequest(r.GetResourceRequest()), features, frame_name, static_cast<WebNavigationPolicy>(navigation_policy), @@ -783,7 +783,7 @@ return nullptr; NotifyPopupOpeningObservers(); - if (WebViewBase::UseExternalPopupMenus()) + if (WebViewImpl::UseExternalPopupMenus()) return new ExternalPopupMenu(frame, select, *web_view_); DCHECK(RuntimeEnabledFeatures::PagePopupEnabled()); @@ -959,7 +959,7 @@ } const WebInputEvent* ChromeClientImpl::GetCurrentInputEvent() const { - return WebViewBase::CurrentInputEvent(); + return WebViewImpl::CurrentInputEvent(); } bool ChromeClientImpl::RequestPointerLock(LocalFrame* frame) {
diff --git a/third_party/WebKit/Source/core/page/ChromeClientImpl.h b/third_party/WebKit/Source/core/page/ChromeClientImpl.h index 8d59fe4..2ad89172 100644 --- a/third_party/WebKit/Source/core/page/ChromeClientImpl.h +++ b/third_party/WebKit/Source/core/page/ChromeClientImpl.h
@@ -44,16 +44,16 @@ class PagePopup; class PagePopupClient; class WebAutofillClient; -class WebViewBase; +class WebViewImpl; struct WebCursorInfo; // Handles window-level notifications from core on behalf of a WebView. class CORE_EXPORT ChromeClientImpl final : public ChromeClient { public: - static ChromeClientImpl* Create(WebViewBase*); + static ChromeClientImpl* Create(WebViewImpl*); ~ChromeClientImpl() override; - WebViewBase* GetWebView() const override; + WebViewImpl* GetWebView() const override; // ChromeClient methods: void ChromeDestroyed() override; @@ -235,7 +235,7 @@ WTF::Function<void(bool)> callback) override; private: - explicit ChromeClientImpl(WebViewBase*); + explicit ChromeClientImpl(WebViewImpl*); bool IsChromeClientImpl() const override { return true; } @@ -245,7 +245,7 @@ // returns nullable. WebAutofillClient* AutofillClientFromFrame(LocalFrame*); - WebViewBase* web_view_; // Weak pointer. + WebViewImpl* web_view_; // Weak pointer. Vector<PopupOpeningObserver*> popup_opening_observers_; Cursor last_set_mouse_cursor_for_testing_; bool cursor_overridden_;
diff --git a/third_party/WebKit/Source/core/page/ContextMenuClient.cpp b/third_party/WebKit/Source/core/page/ContextMenuClient.cpp index 52e7fbe..36e6717 100644 --- a/third_party/WebKit/Source/core/page/ContextMenuClient.cpp +++ b/third_party/WebKit/Source/core/page/ContextMenuClient.cpp
@@ -348,12 +348,8 @@ } // HitTestResult::isSelected() ensures clean layout by performing a hit test. - if (r.IsSelected()) { - if (!isHTMLInputElement(*r.InnerNode()) || - toHTMLInputElement(r.InnerNode())->type() != InputTypeNames::password) { - data.selected_text = selected_frame->SelectedText(); - } - } + if (r.IsSelected()) + data.selected_text = selected_frame->SelectedText(); if (r.IsContentEditable()) { data.is_editable = true;
diff --git a/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.cpp b/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.cpp index 4421a702..3e80b9ab 100644 --- a/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.cpp +++ b/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.cpp
@@ -94,12 +94,12 @@ return; provisional_first_meaningful_paint_ = MonotonicallyIncreasingTime(); - had_user_input_before_provisional_first_meaningful_paint_ = had_user_input_; next_paint_is_meaningful_ = false; if (network2_quiet_reached_) return; + had_user_input_before_provisional_first_meaningful_paint_ = had_user_input_; provisional_first_meaningful_paint_swap_ = 0.0; RegisterNotifySwapTime(PaintEvent::kProvisionalFirstMeaningfulPaint); @@ -190,15 +190,29 @@ first_meaningful_paint2_quiet_ = paint_timing_->FirstContentfulPaint(); first_meaningful_paint2_quiet_swap_ = paint_timing_->FirstContentfulPaintSwap(); + // It's possible that this timer fires between when the first contentful + // paint is set and its SwapPromise is fulfilled. If this happens, defer + // until NotifyFirstContentfulPaint() is called. + if (first_meaningful_paint2_quiet_swap_ == 0.0) + defer_first_meaningful_paint_ = kDeferFirstContentfulPaintNotSet; } else { first_meaningful_paint2_quiet_ = provisional_first_meaningful_paint_; first_meaningful_paint2_quiet_swap_ = provisional_first_meaningful_paint_swap_; + // We might still be waiting for one or more swap promises, in which case + // we want to defer reporting first meaningful paint until they complete. + // Otherwise, we would either report the wrong swap timestamp or none at + // all. + if (outstanding_swap_promise_count_ > 0) + defer_first_meaningful_paint_ = kDeferOutstandingSwapPromises; } - // Report FirstMeaningfulPaint when the page reached network 2-quiet. - paint_timing_->SetFirstMeaningfulPaint( - first_meaningful_paint2_quiet_, first_meaningful_paint2_quiet_swap_, - had_user_input_before_provisional_first_meaningful_paint_); + if (defer_first_meaningful_paint_ == kDoNotDefer) { + // Report FirstMeaningfulPaint when the page reached network 2-quiet if + // we aren't waiting for a swap timestamp. + paint_timing_->SetFirstMeaningfulPaint( + first_meaningful_paint2_quiet_, first_meaningful_paint2_quiet_swap_, + had_user_input_before_provisional_first_meaningful_paint_); + } } ReportHistograms(); } @@ -247,6 +261,7 @@ } void FirstMeaningfulPaintDetector::RegisterNotifySwapTime(PaintEvent event) { + ++outstanding_swap_promise_count_; paint_timing_->RegisterNotifySwapTime( event, WTF::Bind(&FirstMeaningfulPaintDetector::ReportSwapTime, WrapCrossThreadWeakPersistent(this), event)); @@ -255,24 +270,39 @@ void FirstMeaningfulPaintDetector::ReportSwapTime(PaintEvent event, bool did_swap, double timestamp) { - // TODO(shaseley): Add UMAs here to see how often either of the following - // happen. In the first case, the FMP will be 0.0 if this is the provisional - // timestamp we end up using. In the second case, a swap timestamp of 0.0 is - // reported to PaintTiming because the |network2_quiet_timer_| already fired. + DCHECK(event == PaintEvent::kProvisionalFirstMeaningfulPaint); + DCHECK_GT(outstanding_swap_promise_count_, 0U); + --outstanding_swap_promise_count_; + + // TODO(shaseley): Add UMAs here to see how often swaps fail. If this happens, + // the FMP will be 0.0 if this is the provisional timestamp we end up using. if (!did_swap) return; - if (network2_quiet_reached_) - return; - switch (event) { - case PaintEvent::kProvisionalFirstMeaningfulPaint: - provisional_first_meaningful_paint_swap_ = timestamp; - return; - default: - NOTREACHED(); + provisional_first_meaningful_paint_swap_ = timestamp; + + if (defer_first_meaningful_paint_ == kDeferOutstandingSwapPromises && + outstanding_swap_promise_count_ == 0) { + DCHECK_GT(first_meaningful_paint2_quiet_, 0.0); + first_meaningful_paint2_quiet_swap_ = + provisional_first_meaningful_paint_swap_; + paint_timing_->SetFirstMeaningfulPaint( + first_meaningful_paint2_quiet_, first_meaningful_paint2_quiet_swap_, + had_user_input_before_provisional_first_meaningful_paint_); } } +void FirstMeaningfulPaintDetector::NotifyFirstContentfulPaint( + double swap_stamp) { + if (defer_first_meaningful_paint_ != kDeferFirstContentfulPaintNotSet) + return; + DCHECK_EQ(first_meaningful_paint2_quiet_swap_, 0.0); + first_meaningful_paint2_quiet_swap_ = swap_stamp; + paint_timing_->SetFirstMeaningfulPaint( + first_meaningful_paint2_quiet_, first_meaningful_paint2_quiet_swap_, + had_user_input_before_provisional_first_meaningful_paint_); +} + DEFINE_TRACE(FirstMeaningfulPaintDetector) { visitor->Trace(paint_timing_); }
diff --git a/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.h b/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.h index 0f98bb23..1bd25b66 100644 --- a/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.h +++ b/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.h
@@ -50,6 +50,7 @@ void NotifyPaint(); void CheckNetworkStable(); void ReportSwapTime(PaintEvent, bool did_swap, double timestamp); + void NotifyFirstContentfulPaint(double swap_stamp); DECLARE_TRACE(); @@ -58,6 +59,12 @@ private: friend class FirstMeaningfulPaintDetectorTest; + enum DeferFirstMeaningfulPaint { + kDoNotDefer, + kDeferOutstandingSwapPromises, + kDeferFirstContentfulPaintNotSet + }; + // The page is n-quiet if there are no more than n active network requests for // this duration of time. static constexpr double kNetwork2QuietWindowSeconds = 0.5; @@ -88,6 +95,8 @@ double first_meaningful_paint0_quiet_ = 0.0; double first_meaningful_paint2_quiet_ = 0.0; double first_meaningful_paint2_quiet_swap_ = 0.0; + unsigned outstanding_swap_promise_count_ = 0; + DeferFirstMeaningfulPaint defer_first_meaningful_paint_ = kDoNotDefer; TaskRunnerTimer<FirstMeaningfulPaintDetector> network0_quiet_timer_; TaskRunnerTimer<FirstMeaningfulPaintDetector> network2_quiet_timer_; };
diff --git a/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetectorTest.cpp b/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetectorTest.cpp index 72bb641..34663ed 100644 --- a/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetectorTest.cpp +++ b/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetectorTest.cpp
@@ -4,6 +4,7 @@ #include "core/paint/FirstMeaningfulPaintDetector.h" +#include "core/paint/PaintEvent.h" #include "core/paint/PaintTiming.h" #include "core/testing/DummyPageHolder.h" #include "platform/testing/TestingPlatformSupport.h" @@ -73,6 +74,38 @@ bool HadNetwork0Quiet() { return Detector().network0_quiet_reached_; } bool HadNetwork2Quiet() { return Detector().network2_quiet_reached_; } + void ClearFirstPaintSwapPromise() { + platform_->AdvanceClockSeconds(0.001); + GetPaintTiming().ReportSwapTime(PaintEvent::kFirstPaint, true, + MonotonicallyIncreasingTime()); + } + + void ClearFirstContentfulPaintSwapPromise() { + platform_->AdvanceClockSeconds(0.001); + GetPaintTiming().ReportSwapTime(PaintEvent::kFirstContentfulPaint, true, + MonotonicallyIncreasingTime()); + } + + void ClearProvisionalFirstMeaningfulPaintSwapPromise() { + platform_->AdvanceClockSeconds(0.001); + Detector().ReportSwapTime(PaintEvent::kProvisionalFirstMeaningfulPaint, + true, MonotonicallyIncreasingTime()); + } + + unsigned OutstandingDetectorSwapPromiseCount() { + return Detector().outstanding_swap_promise_count_; + } + + void MarkFirstContentfulPaintAndClearSwapPromise() { + GetPaintTiming().MarkFirstContentfulPaint(); + ClearFirstContentfulPaintSwapPromise(); + } + + void MarkFirstPaintAndClearSwapPromise() { + GetPaintTiming().MarkFirstPaint(); + ClearFirstPaintSwapPromise(); + } + protected: ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler> platform_; @@ -88,45 +121,67 @@ TEST_F(FirstMeaningfulPaintDetectorTest, NoFirstPaint) { SimulateLayoutAndPaint(1); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 0U); SimulateNetworkStable(); EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaint(), 0.0); + EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaintSwap(), 0.0); } TEST_F(FirstMeaningfulPaintDetectorTest, OneLayout) { - GetPaintTiming().MarkFirstContentfulPaint(); + MarkFirstContentfulPaintAndClearSwapPromise(); SimulateLayoutAndPaint(1); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U); + ClearProvisionalFirstMeaningfulPaintSwapPromise(); double after_paint = AdvanceClockAndGetTime(); EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaint(), 0.0); + EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaintSwap(), 0.0); SimulateNetworkStable(); EXPECT_GT(GetPaintTiming().FirstMeaningfulPaint(), GetPaintTiming().FirstPaint()); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), + GetPaintTiming().FirstMeaningfulPaint()); EXPECT_LT(GetPaintTiming().FirstMeaningfulPaint(), after_paint); + EXPECT_LT(GetPaintTiming().FirstMeaningfulPaintSwap(), after_paint); } TEST_F(FirstMeaningfulPaintDetectorTest, TwoLayoutsSignificantSecond) { - GetPaintTiming().MarkFirstContentfulPaint(); + MarkFirstContentfulPaintAndClearSwapPromise(); SimulateLayoutAndPaint(1); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U); + ClearProvisionalFirstMeaningfulPaintSwapPromise(); double after_layout1 = AdvanceClockAndGetTime(); SimulateLayoutAndPaint(10); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U); + ClearProvisionalFirstMeaningfulPaintSwapPromise(); double after_layout2 = AdvanceClockAndGetTime(); SimulateNetworkStable(); EXPECT_GT(GetPaintTiming().FirstMeaningfulPaint(), after_layout1); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), after_layout1); EXPECT_LT(GetPaintTiming().FirstMeaningfulPaint(), after_layout2); + EXPECT_LT(GetPaintTiming().FirstMeaningfulPaintSwap(), after_layout2); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), + GetPaintTiming().FirstMeaningfulPaint()); } TEST_F(FirstMeaningfulPaintDetectorTest, TwoLayoutsSignificantFirst) { - GetPaintTiming().MarkFirstContentfulPaint(); + MarkFirstContentfulPaintAndClearSwapPromise(); SimulateLayoutAndPaint(10); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U); + ClearProvisionalFirstMeaningfulPaintSwapPromise(); double after_layout1 = AdvanceClockAndGetTime(); SimulateLayoutAndPaint(1); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 0U); SimulateNetworkStable(); EXPECT_GT(GetPaintTiming().FirstMeaningfulPaint(), GetPaintTiming().FirstPaint()); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), + GetPaintTiming().FirstPaint()); EXPECT_LT(GetPaintTiming().FirstMeaningfulPaint(), after_layout1); + EXPECT_LT(GetPaintTiming().FirstMeaningfulPaintSwap(), after_layout1); } TEST_F(FirstMeaningfulPaintDetectorTest, FirstMeaningfulPaintCandidate) { - GetPaintTiming().MarkFirstContentfulPaint(); + MarkFirstContentfulPaintAndClearSwapPromise(); EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaintCandidate(), 0.0); SimulateLayoutAndPaint(1); double after_paint = AdvanceClockAndGetTime(); @@ -143,7 +198,7 @@ TEST_F(FirstMeaningfulPaintDetectorTest, OnlyOneFirstMeaningfulPaintCandidateBeforeNetworkStable) { - GetPaintTiming().MarkFirstContentfulPaint(); + MarkFirstContentfulPaintAndClearSwapPromise(); EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaintCandidate(), 0.0); double before_paint = AdvanceClockAndGetTime(); SimulateLayoutAndPaint(1); @@ -160,58 +215,91 @@ TEST_F(FirstMeaningfulPaintDetectorTest, NetworkStableBeforeFirstContentfulPaint) { - GetPaintTiming().MarkFirstPaint(); + MarkFirstPaintAndClearSwapPromise(); SimulateLayoutAndPaint(1); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U); + ClearProvisionalFirstMeaningfulPaintSwapPromise(); SimulateNetworkStable(); EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaint(), 0.0); - GetPaintTiming().MarkFirstContentfulPaint(); + EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaintSwap(), 0.0); + MarkFirstContentfulPaintAndClearSwapPromise(); SimulateNetworkStable(); EXPECT_NE(GetPaintTiming().FirstMeaningfulPaint(), 0.0); + EXPECT_NE(GetPaintTiming().FirstMeaningfulPaintSwap(), 0.0); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), + GetPaintTiming().FirstMeaningfulPaint()); } TEST_F(FirstMeaningfulPaintDetectorTest, FirstMeaningfulPaintShouldNotBeBeforeFirstContentfulPaint) { - GetPaintTiming().MarkFirstPaint(); + MarkFirstPaintAndClearSwapPromise(); SimulateLayoutAndPaint(10); - GetPaintTiming().MarkFirstContentfulPaint(); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U); + ClearProvisionalFirstMeaningfulPaintSwapPromise(); + platform_->AdvanceClockSeconds(0.001); + MarkFirstContentfulPaintAndClearSwapPromise(); SimulateNetworkStable(); EXPECT_GE(GetPaintTiming().FirstMeaningfulPaint(), GetPaintTiming().FirstContentfulPaint()); + EXPECT_GE(GetPaintTiming().FirstMeaningfulPaintSwap(), + GetPaintTiming().FirstContentfulPaintSwap()); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), + GetPaintTiming().FirstMeaningfulPaint()); } TEST_F(FirstMeaningfulPaintDetectorTest, Network2QuietThen0Quiet) { - GetPaintTiming().MarkFirstContentfulPaint(); + MarkFirstContentfulPaintAndClearSwapPromise(); SimulateLayoutAndPaint(1); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U); double after_first_paint = AdvanceClockAndGetTime(); + ClearProvisionalFirstMeaningfulPaintSwapPromise(); + double after_first_paint_swap = AdvanceClockAndGetTime(); SimulateNetwork2Quiet(); SimulateLayoutAndPaint(10); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 0U); SimulateNetwork0Quiet(); // The first paint is FirstMeaningfulPaint. EXPECT_GT(GetPaintTiming().FirstMeaningfulPaint(), 0.0); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), 0.0); EXPECT_LT(GetPaintTiming().FirstMeaningfulPaint(), after_first_paint); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), after_first_paint); + EXPECT_LT(GetPaintTiming().FirstMeaningfulPaintSwap(), + after_first_paint_swap); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), + GetPaintTiming().FirstMeaningfulPaint()); } TEST_F(FirstMeaningfulPaintDetectorTest, Network0QuietThen2Quiet) { - GetPaintTiming().MarkFirstContentfulPaint(); + MarkFirstContentfulPaintAndClearSwapPromise(); SimulateLayoutAndPaint(1); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U); + ClearProvisionalFirstMeaningfulPaintSwapPromise(); double after_first_paint = AdvanceClockAndGetTime(); SimulateNetwork0Quiet(); SimulateLayoutAndPaint(10); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U); + ClearProvisionalFirstMeaningfulPaintSwapPromise(); double after_second_paint = AdvanceClockAndGetTime(); SimulateNetwork2Quiet(); // The second paint is FirstMeaningfulPaint. EXPECT_GT(GetPaintTiming().FirstMeaningfulPaint(), after_first_paint); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), after_first_paint); EXPECT_LT(GetPaintTiming().FirstMeaningfulPaint(), after_second_paint); + EXPECT_LT(GetPaintTiming().FirstMeaningfulPaintSwap(), after_second_paint); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), + GetPaintTiming().FirstMeaningfulPaint()); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), + GetPaintTiming().FirstMeaningfulPaint()); } TEST_F(FirstMeaningfulPaintDetectorTest, Network0QuietTimer) { - GetPaintTiming().MarkFirstContentfulPaint(); + MarkFirstContentfulPaintAndClearSwapPromise(); SetActiveConnections(1); EXPECT_FALSE(IsNetwork0QuietTimerActive()); @@ -231,7 +319,7 @@ } TEST_F(FirstMeaningfulPaintDetectorTest, Network2QuietTimer) { - GetPaintTiming().MarkFirstContentfulPaint(); + MarkFirstContentfulPaintAndClearSwapPromise(); SetActiveConnections(3); EXPECT_FALSE(IsNetwork2QuietTimerActive()); @@ -253,19 +341,97 @@ TEST_F(FirstMeaningfulPaintDetectorTest, FirstMeaningfulPaintAfterUserInteraction) { - GetPaintTiming().MarkFirstContentfulPaint(); + MarkFirstContentfulPaintAndClearSwapPromise(); SimulateUserInput(); SimulateLayoutAndPaint(10); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U); + ClearProvisionalFirstMeaningfulPaintSwapPromise(); SimulateNetworkStable(); EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaint(), 0.0); + EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaintSwap(), 0.0); } TEST_F(FirstMeaningfulPaintDetectorTest, UserInteractionBeforeFirstPaint) { SimulateUserInput(); - GetPaintTiming().MarkFirstContentfulPaint(); + MarkFirstContentfulPaintAndClearSwapPromise(); SimulateLayoutAndPaint(10); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U); + ClearProvisionalFirstMeaningfulPaintSwapPromise(); SimulateNetworkStable(); EXPECT_NE(GetPaintTiming().FirstMeaningfulPaint(), 0.0); + EXPECT_NE(GetPaintTiming().FirstMeaningfulPaintSwap(), 0.0); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), + GetPaintTiming().FirstMeaningfulPaint()); +} + +TEST_F(FirstMeaningfulPaintDetectorTest, + WaitForSingleOutstandingSwapPromiseAfterNetworkStable) { + MarkFirstContentfulPaintAndClearSwapPromise(); + SimulateLayoutAndPaint(10); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U); + SimulateNetworkStable(); + EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaint(), 0.0); + EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaintSwap(), 0.0); + ClearProvisionalFirstMeaningfulPaintSwapPromise(); + EXPECT_NE(GetPaintTiming().FirstMeaningfulPaint(), 0.0); + EXPECT_NE(GetPaintTiming().FirstMeaningfulPaintSwap(), 0.0); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), + GetPaintTiming().FirstMeaningfulPaint()); +} + +TEST_F(FirstMeaningfulPaintDetectorTest, + WaitForMultipleOutstandingSwapPromisesAfterNetworkStable) { + MarkFirstContentfulPaintAndClearSwapPromise(); + SimulateLayoutAndPaint(1); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U); + platform_->AdvanceClockSeconds(0.001); + SimulateLayoutAndPaint(10); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 2U); + // Having outstanding swap promises should defer setting FMP. + SimulateNetworkStable(); + EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaint(), 0.0); + EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaintSwap(), 0.0); + // Clearing the first swap promise should have no effect on FMP. + ClearProvisionalFirstMeaningfulPaintSwapPromise(); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U); + EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaint(), 0.0); + EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaintSwap(), 0.0); + double after_first_swap = AdvanceClockAndGetTime(); + // Clearing the last outstanding swap promise should set FMP. + ClearProvisionalFirstMeaningfulPaintSwapPromise(); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 0U); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaint(), 0.0); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), 0.0); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), after_first_swap); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), + GetPaintTiming().FirstMeaningfulPaint()); +} + +TEST_F(FirstMeaningfulPaintDetectorTest, + WaitForFirstContentfulPaintSwapAfterNetworkStable) { + MarkFirstPaintAndClearSwapPromise(); + SimulateLayoutAndPaint(10); + EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U); + ClearProvisionalFirstMeaningfulPaintSwapPromise(); + double after_first_meaningful_paint_candidate = AdvanceClockAndGetTime(); + platform_->AdvanceClockSeconds(0.001); + GetPaintTiming().MarkFirstContentfulPaint(); + // FCP > FMP candidate, but still waiting for FCP swap. + SimulateNetworkStable(); + EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaint(), 0.0); + EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaintSwap(), 0.0); + // Trigger notifying the detector about the FCP swap. + ClearFirstContentfulPaintSwapPromise(); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaint(), 0.0); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), 0.0); + EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaint(), + GetPaintTiming().FirstContentfulPaint()); + EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaintSwap(), + GetPaintTiming().FirstContentfulPaintSwap()); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaint(), + after_first_meaningful_paint_candidate); + EXPECT_GT(GetPaintTiming().FirstMeaningfulPaintSwap(), + GetPaintTiming().FirstMeaningfulPaint()); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp index 69f1eef..38da685 100644 --- a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp +++ b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp
@@ -272,4 +272,13 @@ UseCounter::Count(GetLayoutBox()->GetDocument(), scrollbar_use_uma); } +CompositorElementId +PaintInvalidationCapableScrollableArea::GetCompositorElementId() const { + return GetLayoutBox() + ->FirstFragment() + ->PaintProperties() + ->ScrollTranslation() + ->GetCompositorElementId(); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.h b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.h index 73a2f92..af24832 100644 --- a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.h +++ b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.h
@@ -37,6 +37,7 @@ } void DidScrollWithScrollbar(ScrollbarPart, ScrollbarOrientation) override; + CompositorElementId GetCompositorElementId() const override; private: virtual LayoutScrollbarPart* ScrollCorner() const = 0;
diff --git a/third_party/WebKit/Source/core/paint/PaintTiming.cpp b/third_party/WebKit/Source/core/paint/PaintTiming.cpp index 4991dd6b..1934f5cf 100644 --- a/third_party/WebKit/Source/core/paint/PaintTiming.cpp +++ b/third_party/WebKit/Source/core/paint/PaintTiming.cpp
@@ -218,6 +218,7 @@ first_contentful_paint_swap_ = timestamp; if (performance) performance->AddFirstContentfulPaintTiming(first_contentful_paint_); + fmp_detector_->NotifyFirstContentfulPaint(timestamp); return; default: NOTREACHED();
diff --git a/third_party/WebKit/Source/core/paint/PaintTiming.h b/third_party/WebKit/Source/core/paint/PaintTiming.h index 577baeca70..db3f9fd7 100644 --- a/third_party/WebKit/Source/core/paint/PaintTiming.h +++ b/third_party/WebKit/Source/core/paint/PaintTiming.h
@@ -79,6 +79,9 @@ // firstMeaningfulPaint returns the first time that page's primary content // was painted. double FirstMeaningfulPaint() const { return first_meaningful_paint_; } + double FirstMeaningfulPaintSwap() const { + return first_meaningful_paint_swap_; + } // firstMeaningfulPaintCandidate indicates the first time we considered a // paint to qualify as the potentially first meaningful paint. Unlike
diff --git a/third_party/WebKit/Source/core/paint/TableSectionPainter.cpp b/third_party/WebKit/Source/core/paint/TableSectionPainter.cpp index 40c3186..d451b26 100644 --- a/third_party/WebKit/Source/core/paint/TableSectionPainter.cpp +++ b/third_party/WebKit/Source/core/paint/TableSectionPainter.cpp
@@ -108,8 +108,12 @@ header_group_offset += strut_on_first_row; LayoutUnit total_height_of_rows = sections_rect.Height() + IntMod(header_group_offset, page_height); - total_height_of_rows -= (layout_table_section_.LogicalHeight() - - layout_table_section_.FirstRow()->PaginationStrut()); + LayoutUnit first_row_strut = + layout_table_section_.FirstRow() + ? layout_table_section_.FirstRow()->PaginationStrut() + : LayoutUnit(); + total_height_of_rows -= + layout_table_section_.LogicalHeight() - first_row_strut; // Move the offset to the top of the page the table starts on. LayoutPoint pagination_offset = paint_offset;
diff --git a/third_party/WebKit/Source/core/svg/SVGPathElement.cpp b/third_party/WebKit/Source/core/svg/SVGPathElement.cpp index 1ed87f83..5ae88fe 100644 --- a/third_party/WebKit/Source/core/svg/SVGPathElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGPathElement.cpp
@@ -75,11 +75,6 @@ return SVGPointTearOff::CreateDetached(point); } -unsigned SVGPathElement::getPathSegAtLength(float length) { - GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets(); - return SVGPathQuery(PathByteStream()).GetPathSegIndexAtLength(length); -} - void SVGPathElement::SvgAttributeChanged(const QualifiedName& attr_name) { if (attr_name == SVGNames::dAttr) { SVGElement::InvalidationGuard invalidation_guard(this);
diff --git a/third_party/WebKit/Source/core/svg/SVGPathElement.h b/third_party/WebKit/Source/core/svg/SVGPathElement.h index 070f0aaa..fc7f3b1 100644 --- a/third_party/WebKit/Source/core/svg/SVGPathElement.h +++ b/third_party/WebKit/Source/core/svg/SVGPathElement.h
@@ -41,7 +41,6 @@ float getTotalLength() override; SVGPointTearOff* getPointAtLength(float distance) override; - unsigned getPathSegAtLength(float distance); SVGAnimatedPath* GetPath() const { return path_.Get(); } float ComputePathLength() const override;
diff --git a/third_party/WebKit/Source/core/svg/SVGPathElement.idl b/third_party/WebKit/Source/core/svg/SVGPathElement.idl index ce21df9..748f418 100644 --- a/third_party/WebKit/Source/core/svg/SVGPathElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGPathElement.idl
@@ -27,5 +27,4 @@ // https://svgwg.org/svg2-draft/paths.html#InterfaceSVGPathElement interface SVGPathElement : SVGGeometryElement { - [DeprecateAs=V8SVGPathElement_GetPathSegAtLength_Method] unsigned long getPathSegAtLength(float distance); };
diff --git a/third_party/WebKit/Source/core/svg/SVGPathQuery.cpp b/third_party/WebKit/Source/core/svg/SVGPathQuery.cpp index 9544609d..547de447 100644 --- a/third_party/WebKit/Source/core/svg/SVGPathQuery.cpp +++ b/third_party/WebKit/Source/core/svg/SVGPathQuery.cpp
@@ -107,13 +107,6 @@ SVGPathQuery::SVGPathQuery(const SVGPathByteStream& path_byte_stream) : path_byte_stream_(path_byte_stream) {} -unsigned SVGPathQuery::GetPathSegIndexAtLength(float length) const { - SVGPathTraversalState traversal_state( - PathTraversalState::kTraversalSegmentAtLength, length); - ExecuteQuery(path_byte_stream_, traversal_state); - return traversal_state.SegmentIndex(); -} - float SVGPathQuery::GetTotalLength() const { SVGPathTraversalState traversal_state( PathTraversalState::kTraversalTotalLength);
diff --git a/third_party/WebKit/Source/core/svg/SVGPathQuery.h b/third_party/WebKit/Source/core/svg/SVGPathQuery.h index 7ac4cdf..d5caa44 100644 --- a/third_party/WebKit/Source/core/svg/SVGPathQuery.h +++ b/third_party/WebKit/Source/core/svg/SVGPathQuery.h
@@ -32,7 +32,6 @@ float GetTotalLength() const; FloatPoint GetPointAtLength(float length) const; - unsigned GetPathSegIndexAtLength(float length) const; private: const SVGPathByteStream& path_byte_stream_;
diff --git a/third_party/WebKit/Source/core/testing/data/composited_selection_bounds_input.html b/third_party/WebKit/Source/core/testing/data/composited_selection_bounds_input.html new file mode 100644 index 0000000..6e05739 --- /dev/null +++ b/third_party/WebKit/Source/core/testing/data/composited_selection_bounds_input.html
@@ -0,0 +1,27 @@ +<style> + @font-face { + font-family: ahem; + src: url(Ahem.ttf); + } + * { + font-family: ahem; + margin: 0; + padding: 0; + } + #text { + background-color: transparent; /* Prevent scrolling layer promotion to it's own layer */ + } +</style> +<input id=target width=20 value='test test test test test tes tes test' style='width: 100px; height: 20px;'> +</input> +<script> + target.select(); + + var expectEditable = false; + var expectEmptyTextFormControl = false; + var yBottomEpsilon = 2; + var startHidden = false; + var endHidden = true; + window.expectedResult = [document, 2, 3, 2, 17, document, 482, 3, 482, 17, expectEditable, + expectEmptyTextFormControl, yBottomEpsilon, startHidden, endHidden, 50, 10]; +</script>
diff --git a/third_party/WebKit/Source/core/testing/data/composited_selection_bounds_input_scrolled.html b/third_party/WebKit/Source/core/testing/data/composited_selection_bounds_input_scrolled.html new file mode 100644 index 0000000..27a001ff --- /dev/null +++ b/third_party/WebKit/Source/core/testing/data/composited_selection_bounds_input_scrolled.html
@@ -0,0 +1,27 @@ +<style> + @font-face { + font-family: ahem; + src: url(Ahem.ttf); + } + * { + font-family: ahem; + margin: 0; + padding: 0; + } + #text { + background-color: transparent; /* Prevent scrolling layer promotion to it's own layer */ + } +</style> +<input id=target width=20 value='test test test test test tes tes test' style='width: 100px; height: 20px;'> +</input> +<script> + target.select(); + target.scrollLeft = 100; + + var expectEditable = false; + var expectEmptyTextFormControl = false; + var yBottomEpsilon = 2; + var startHidden = true; + var endHidden = true; + window.expectedResult = [document, -98, 3, -98, 17, document, 382, 3, 382, 17, expectEditable, expectEmptyTextFormControl, yBottomEpsilon, startHidden, endHidden, 50, 10]; +</script>
diff --git a/third_party/WebKit/Source/core/timing/PerformanceBase.cpp b/third_party/WebKit/Source/core/timing/PerformanceBase.cpp index 2fd642a5..6513758 100644 --- a/third_party/WebKit/Source/core/timing/PerformanceBase.cpp +++ b/third_party/WebKit/Source/core/timing/PerformanceBase.cpp
@@ -452,12 +452,6 @@ void PerformanceBase::UnregisterPerformanceObserver( PerformanceObserver& old_observer) { - // Deliver any pending observations on this observer before unregistering. - if (active_observers_.Contains(&old_observer) && - !old_observer.ShouldBeSuspended()) { - old_observer.Deliver(); - active_observers_.erase(&old_observer); - } observers_.erase(&old_observer); UpdatePerformanceObserverFilterOptions(); UpdateLongTaskInstrumentation();
diff --git a/third_party/WebKit/Source/core/timing/PerformanceBaseTest.cpp b/third_party/WebKit/Source/core/timing/PerformanceBaseTest.cpp index bb66152..54debdd 100644 --- a/third_party/WebKit/Source/core/timing/PerformanceBaseTest.cpp +++ b/third_party/WebKit/Source/core/timing/PerformanceBaseTest.cpp
@@ -111,7 +111,7 @@ base_->UnregisterPerformanceObserver(*observer_.Get()); EXPECT_EQ(0, base_->NumObservers()); - EXPECT_EQ(0, base_->NumActiveObservers()); + EXPECT_EQ(1, base_->NumActiveObservers()); } TEST_F(PerformanceBaseTest, AddLongTaskTiming) {
diff --git a/third_party/WebKit/Source/core/timing/PerformanceObserver.cpp b/third_party/WebKit/Source/core/timing/PerformanceObserver.cpp index 2f51f1a..7efae8a 100644 --- a/third_party/WebKit/Source/core/timing/PerformanceObserver.cpp +++ b/third_party/WebKit/Source/core/timing/PerformanceObserver.cpp
@@ -86,9 +86,9 @@ } void PerformanceObserver::disconnect() { + performance_entries_.clear(); if (performance_) performance_->UnregisterPerformanceObserver(*this); - performance_entries_.clear(); is_registered_ = false; }
diff --git a/third_party/WebKit/Source/core/workers/InstalledScriptsManager.h b/third_party/WebKit/Source/core/workers/InstalledScriptsManager.h index 01fb3bd..6212fd39 100644 --- a/third_party/WebKit/Source/core/workers/InstalledScriptsManager.h +++ b/third_party/WebKit/Source/core/workers/InstalledScriptsManager.h
@@ -22,10 +22,13 @@ class CORE_EXPORT ScriptData { public: + ScriptData() = default; ScriptData(const KURL& script_url, String source_text, std::unique_ptr<Vector<char>> meta_data, std::unique_ptr<CrossThreadHTTPHeaderMapData>); + ScriptData(ScriptData&& other) = default; + ScriptData& operator=(ScriptData&& other) = default; String TakeSourceText() { return std::move(source_text_); } std::unique_ptr<Vector<char>> TakeMetaData() { @@ -38,23 +41,35 @@ std::unique_ptr<Vector<String>> CreateOriginTrialTokens(); private: - const KURL script_url_; + KURL script_url_; String source_text_; std::unique_ptr<Vector<char>> meta_data_; HTTPHeaderMap headers_; + + DISALLOW_COPY_AND_ASSIGN(ScriptData); }; // Used on the main or worker thread. Returns true if the script has been // installed. virtual bool IsScriptInstalled(const KURL& script_url) const = 0; - // Used on the worker thread. This is possible to return WTF::nullopt when the - // script has already been served from this manager (i.e. the same script is - // read more than once) or when receiving the script from the browser has - // failed. This can be blocked if the script is not streamed yet. - virtual Optional<ScriptData> GetScriptData(const KURL& script_url) = 0; + enum class ScriptStatus { kSuccess, kTaken, kFailed }; + // Used on the worker thread. GetScriptData() can provide a script for the + // |script_url| only once. When GetScriptData returns + // - ScriptStatus::kSuccess: the script has been received correctly. Sets the + // script to |out_script_data|. + // - ScriptStatus::kTaken: the script has been served from this manager + // (i.e. the same script is read more than once). + // |out_script_data| is left as is. + // - ScriptStatus::kFailed: an error happened while receiving the script from + // the browser process. + // |out_script_data| is left as is. + // This can block if the script has not been received from the browser process + // yet. + virtual ScriptStatus GetScriptData(const KURL& script_url, + ScriptData* out_script_data) = 0; }; } // namespace blink -#endif // WorkerInstalledScriptsManager_h +#endif // InstalledScriptsManager_h
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp index 90350bb..c524206 100644 --- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
@@ -44,6 +44,7 @@ #include "core/inspector/WorkerThreadDebugger.h" #include "core/loader/WorkerThreadableLoader.h" #include "core/probe/CoreProbes.h" +#include "core/workers/InstalledScriptsManager.h" #include "core/workers/WorkerLocation.h" #include "core/workers/WorkerNavigator.h" #include "core/workers/WorkerReportingProxy.h" @@ -51,6 +52,7 @@ #include "core/workers/WorkerThread.h" #include "platform/CrossThreadFunctional.h" #include "platform/InstanceCounters.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/loader/fetch/MemoryCache.h" #include "platform/network/ContentSecurityPolicyParsers.h" #include "platform/scheduler/child/web_scheduler.h" @@ -171,7 +173,6 @@ DCHECK(GetExecutionContext()); ExecutionContext& execution_context = *this->GetExecutionContext(); - Vector<KURL> completed_urls; for (const String& url_string : urls) { const KURL& url = execution_context.CompleteURL(url_string); @@ -191,35 +192,35 @@ } for (const KURL& complete_url : completed_urls) { - RefPtr<WorkerScriptLoader> script_loader(WorkerScriptLoader::Create()); - script_loader->LoadSynchronously( - execution_context, complete_url, WebURLRequest::kRequestContextScript, - execution_context.GetSecurityContext().AddressSpace()); + KURL response_url; + String source_code; + std::unique_ptr<Vector<char>> cached_meta_data; + LoadResult result = LoadResult::kNotHandled; + if (RuntimeEnabledFeatures::ServiceWorkerScriptStreamingEnabled()) { + result = LoadingScriptFromInstalledScriptsManager( + complete_url, &response_url, &source_code, &cached_meta_data); + } - // If the fetching attempt failed, throw a NetworkError exception and - // abort all these steps. - if (script_loader->Failed()) { + // If the script wasn't provided by the InstalledScriptsManager, load from + // ResourceLoader. + if (result == LoadResult::kNotHandled) { + result = LoadingScriptFromWorkerScriptLoader( + complete_url, &response_url, &source_code, &cached_meta_data); + } + + if (result != LoadResult::kSuccess) { exception_state.ThrowDOMException( kNetworkError, "The script at '" + complete_url.ElidedString() + "' failed to load."); return; } - probe::scriptImported(&execution_context, script_loader->Identifier(), - script_loader->SourceText()); - ErrorEvent* error_event = nullptr; - std::unique_ptr<Vector<char>> cached_meta_data( - script_loader->ReleaseCachedMetadata()); CachedMetadataHandler* handler(CreateWorkerScriptCachedMetadataHandler( complete_url, cached_meta_data.get())); GetThread()->GetWorkerReportingProxy().WillEvaluateImportedScript( - script_loader->SourceText().length(), - script_loader->CachedMetadata() - ? script_loader->CachedMetadata()->size() - : 0); - ScriptController()->Evaluate(ScriptSourceCode(script_loader->SourceText(), - script_loader->ResponseURL()), + source_code.length(), cached_meta_data ? cached_meta_data->size() : 0); + ScriptController()->Evaluate(ScriptSourceCode(source_code, response_url), &error_event, handler, v8_cache_options_); if (error_event) { ScriptController()->RethrowExceptionFromImportedScript(error_event, @@ -229,6 +230,63 @@ } } +WorkerGlobalScope::LoadResult +WorkerGlobalScope::LoadingScriptFromInstalledScriptsManager( + const KURL& script_url, + KURL* out_response_url, + String* out_source_code, + std::unique_ptr<Vector<char>>* out_cached_meta_data) { + if (!GetThread()->GetInstalledScriptsManager() || + !GetThread()->GetInstalledScriptsManager()->IsScriptInstalled( + script_url)) { + return LoadResult::kNotHandled; + } + InstalledScriptsManager::ScriptData script_data; + InstalledScriptsManager::ScriptStatus status = + GetThread()->GetInstalledScriptsManager()->GetScriptData(script_url, + &script_data); + switch (status) { + case InstalledScriptsManager::ScriptStatus::kTaken: + return LoadResult::kNotHandled; + case InstalledScriptsManager::ScriptStatus::kFailed: + return LoadResult::kFailed; + case InstalledScriptsManager::ScriptStatus::kSuccess: + *out_response_url = script_url; + *out_source_code = script_data.TakeSourceText(); + *out_cached_meta_data = script_data.TakeMetaData(); + // TODO(shimazu): Add appropriate probes for inspector. + return LoadResult::kSuccess; + } + + NOTREACHED(); + return LoadResult::kFailed; +} + +WorkerGlobalScope::LoadResult +WorkerGlobalScope::LoadingScriptFromWorkerScriptLoader( + const KURL& script_url, + KURL* out_response_url, + String* out_source_code, + std::unique_ptr<Vector<char>>* out_cached_meta_data) { + ExecutionContext* execution_context = GetExecutionContext(); + RefPtr<WorkerScriptLoader> script_loader(WorkerScriptLoader::Create()); + script_loader->LoadSynchronously( + *execution_context, script_url, WebURLRequest::kRequestContextScript, + execution_context->GetSecurityContext().AddressSpace()); + + // If the fetching attempt failed, throw a NetworkError exception and + // abort all these steps. + if (script_loader->Failed()) + return LoadResult::kFailed; + + *out_response_url = script_loader->ResponseURL(); + *out_source_code = script_loader->SourceText(); + *out_cached_meta_data = script_loader->ReleaseCachedMetadata(); + probe::scriptImported(execution_context, script_loader->Identifier(), + script_loader->SourceText()); + return LoadResult::kSuccess; +} + v8::Local<v8::Object> WorkerGlobalScope::Wrap( v8::Isolate*, v8::Local<v8::Object> creation_context) { @@ -347,6 +405,7 @@ void WorkerGlobalScope::SetWorkerSettings( std::unique_ptr<WorkerSettings> worker_settings) { worker_settings_ = std::move(worker_settings); + worker_settings_->MakeGenericFontFamilySettingsAtomic(); } void WorkerGlobalScope::ExceptionThrown(ErrorEvent* event) {
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h index 73da94c..9fdd4397 100644 --- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h +++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h
@@ -167,6 +167,33 @@ void RemoveURLFromMemoryCache(const KURL&) final; private: + // |kNotHandled| is used when the script was not in + // InstalledScriptsManager, which means either it was not an installed script + // or it was already taken. + enum class LoadResult { kSuccess, kFailed, kNotHandled }; + + // Tries to load the script synchronously from the + // InstalledScriptsManager, which holds scripts that are sent from the browser + // upon starting an installed worker. This blocks until the script is + // received. If the script load could not be handled by the + // InstalledScriptsManager, e.g. when the script was not an installed script, + // returns LoadResult::kNotHandled. + // TODO(crbug.com/753350): Factor out LoadingScriptFrom* into a new class + // which provides the worker's scripts. + LoadResult LoadingScriptFromInstalledScriptsManager( + const KURL& script_url, + KURL* out_response_url, + String* out_source_code, + std::unique_ptr<Vector<char>>* out_cached_meta_data); + // Tries to load the script synchronously from the WorkerScriptLoader, which + // requests the script from the browser. This + // blocks until the script is received. + LoadResult LoadingScriptFromWorkerScriptLoader( + const KURL& script_url, + KURL* out_response_url, + String* out_source_code, + std::unique_ptr<Vector<char>>* out_cached_meta_data); + // ExecutionContext EventTarget* ErrorEventTarget() final { return this; } const KURL& VirtualURL() const final { return url_; }
diff --git a/third_party/WebKit/Source/core/workers/WorkerSettings.cpp b/third_party/WebKit/Source/core/workers/WorkerSettings.cpp index c1ffb5a2..efe1fda 100644 --- a/third_party/WebKit/Source/core/workers/WorkerSettings.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerSettings.cpp
@@ -18,6 +18,8 @@ settings->GetAllowRunningOfInsecureContent(); strictly_block_blockable_mixed_content_ = settings->GetStrictlyBlockBlockableMixedContent(); + settings->GetGenericFontFamilySettings().IsolatedCopyTo( + generic_font_family_settings_); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/WorkerSettings.h b/third_party/WebKit/Source/core/workers/WorkerSettings.h index 1a169ca..6e7eab2 100644 --- a/third_party/WebKit/Source/core/workers/WorkerSettings.h +++ b/third_party/WebKit/Source/core/workers/WorkerSettings.h
@@ -7,6 +7,7 @@ #include "core/CoreExport.h" #include "core/frame/Settings.h" +#include "platform/fonts/GenericFontFamilySettings.h" namespace blink { @@ -25,6 +26,14 @@ return strictly_block_blockable_mixed_content_; } + const GenericFontFamilySettings& GetGenericFontFamilySettings() const { + return generic_font_family_settings_; + } + + void MakeGenericFontFamilySettingsAtomic() { + generic_font_family_settings_.MakeAtomic(); + } + private: void CopyFlagValuesFromSettings(Settings*); @@ -36,6 +45,8 @@ bool strict_mixed_content_checking_ = false; bool allow_running_of_insecure_content_ = false; bool strictly_block_blockable_mixed_content_ = false; + + GenericFontFamilySettings generic_font_family_settings_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.cpp b/third_party/WebKit/Source/core/workers/WorkerThread.cpp index 02a4cebf..6d90b7d 100644 --- a/third_party/WebKit/Source/core/workers/WorkerThread.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
@@ -416,33 +416,42 @@ GetInstalledScriptsManager() && GetInstalledScriptsManager()->IsScriptInstalled(script_url)) { // GetScriptData blocks until the script is received from the browser. - auto script_data = GetInstalledScriptsManager()->GetScriptData(script_url); + InstalledScriptsManager::ScriptData script_data; + InstalledScriptsManager::ScriptStatus status = + GetInstalledScriptsManager()->GetScriptData(script_url, &script_data); - // |script_data| could be null if an error occurred in the browser process - // while trying to read the installed script. In that case, the worker - // thread will terminate after initialization of the global scope since - // PrepareForShutdownOnWorkerThread() assumes the global scope has already - // been initialized. - if (!script_data) { - should_terminate = true; - } else { - DCHECK(source_code.IsEmpty()); - DCHECK(!cached_meta_data); - source_code = script_data->TakeSourceText(); - cached_meta_data = script_data->TakeMetaData(); + // If an error occurred in the browser process while trying to read the + // installed script, the worker thread will terminate after initialization + // of the global scope since PrepareForShutdownOnWorkerThread() assumes the + // global scope has already been initialized. + switch (status) { + case InstalledScriptsManager::ScriptStatus::kTaken: + // InstalledScriptsManager::ScriptStatus::kTaken should not be returned + // since requesting the main script should be the first and no script + // has been taken until here. + NOTREACHED(); + case InstalledScriptsManager::ScriptStatus::kFailed: + should_terminate = true; + break; + case InstalledScriptsManager::ScriptStatus::kSuccess: + DCHECK(source_code.IsEmpty()); + DCHECK(!cached_meta_data); + source_code = script_data.TakeSourceText(); + cached_meta_data = script_data.TakeMetaData(); - global_scope_creation_params->content_security_policy_raw_headers = - script_data->GetContentSecurityPolicyResponseHeaders(); - global_scope_creation_params->referrer_policy = - script_data->GetReferrerPolicy(); - global_scope_creation_params->origin_trial_tokens = - script_data->CreateOriginTrialTokens(); - // This may block until CSP and referrer policy are set on the main - // thread. - worker_reporting_proxy_.DidLoadInstalledScript( - global_scope_creation_params->content_security_policy_raw_headers - .value(), - global_scope_creation_params->referrer_policy); + global_scope_creation_params->content_security_policy_raw_headers = + script_data.GetContentSecurityPolicyResponseHeaders(); + global_scope_creation_params->referrer_policy = + script_data.GetReferrerPolicy(); + global_scope_creation_params->origin_trial_tokens = + script_data.CreateOriginTrialTokens(); + // This may block until CSP and referrer policy are set on the main + // thread. + worker_reporting_proxy_.DidLoadInstalledScript( + global_scope_creation_params->content_security_policy_raw_headers + .value(), + global_scope_creation_params->referrer_policy); + break; } } else { source_code = std::move(global_scope_creation_params->source_code);
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn index 67f6f69..0ffc52c 100644 --- a/third_party/WebKit/Source/devtools/BUILD.gn +++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -104,6 +104,7 @@ "front_end/cm_web_modes/htmlmixed.js", "front_end/cm_web_modes/javascript.js", "front_end/cm_web_modes/xml.js", + "front_end/color_picker/Contrast.js", "front_end/color_picker/module.json", "front_end/color_picker/spectrum.css", "front_end/color_picker/Spectrum.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/mediumIcons.png b/third_party/WebKit/Source/devtools/front_end/Images/mediumIcons.png index dce7e5ce..5cd9f460 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/mediumIcons.png +++ b/third_party/WebKit/Source/devtools/front_end/Images/mediumIcons.png Binary files differ
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/mediumIcons_2x.png b/third_party/WebKit/Source/devtools/front_end/Images/mediumIcons_2x.png index b39d28ba4..730c3ea 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/mediumIcons_2x.png +++ b/third_party/WebKit/Source/devtools/front_end/Images/mediumIcons_2x.png Binary files differ
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/smallIcons.png b/third_party/WebKit/Source/devtools/front_end/Images/smallIcons.png index 04e7680..c13b06d 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/smallIcons.png +++ b/third_party/WebKit/Source/devtools/front_end/Images/smallIcons.png Binary files differ
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/smallIcons_2x.png b/third_party/WebKit/Source/devtools/front_end/Images/smallIcons_2x.png index 731ba43d..7cf24d7b 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/smallIcons_2x.png +++ b/third_party/WebKit/Source/devtools/front_end/Images/smallIcons_2x.png Binary files differ
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/src/mediumIcons.svg b/third_party/WebKit/Source/devtools/front_end/Images/src/mediumIcons.svg index 92237b9..682d2145 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/src/mediumIcons.svg +++ b/third_party/WebKit/Source/devtools/front_end/Images/src/mediumIcons.svg
@@ -1,91 +1,440 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="64" height="64" id="svg4775" version="1.1" inkscape:version="0.48.4 r9939" sodipodi:docname="mediumIcons.svg"> - <metadata id="metadata4917"> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="64" + height="64" + id="svg4775" + version="1.1" + inkscape:version="0.48.4 r9939" + sodipodi:docname="mediumIcons.svg"> + <metadata + id="metadata4917"> <rdf:RDF> - <cc:Work rdf:about=""> + <cc:Work + rdf:about=""> <dc:format>image/svg+xml</dc:format> - <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> </cc:Work> </rdf:RDF> </metadata> - <defs id="defs4915"/> - <sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="1278" inkscape:window-height="746" id="namedview4913" showgrid="true" inkscape:zoom="2.6074563" inkscape:cx="-16.363967" inkscape:cy="36.722264" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="0" inkscape:current-layer="svg4775"> - <inkscape:grid type="xygrid" id="grid4919" empspacing="5" visible="true" enabled="true" snapvisiblegridlinesonly="true" spacingx="16px" spacingy="16px"/> + <defs + id="defs4915" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1278" + inkscape:window-height="746" + id="namedview4913" + showgrid="true" + inkscape:zoom="2.6074563" + inkscape:cx="-16.363967" + inkscape:cy="36.722264" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="0" + inkscape:current-layer="svg4775"> + <inkscape:grid + type="xygrid" + id="grid4919" + empspacing="5" + visible="true" + enabled="true" + snapvisiblegridlinesonly="true" + spacingx="16px" + spacingy="16px" /> </sodipodi:namedview> - <g id="g4777"> - <path d="m 3,4 h 10 v 9.008 C 13,14.1082 12.11257,15 11.0004,15 H 4.9996 C 3.8952,15 3,14.09982 3,13.008 V 4 z M 2,2 H 14 V 3 H 2 V 2 z M 5,1 h 6 V 2 H 5 V 1 z" id="path4781" inkscape:connector-curvature="0" style="fill:#212121"/> + <g + id="g4777"> + <path + d="m 3,4 h 10 v 9.008 C 13,14.1082 12.11257,15 11.0004,15 H 4.9996 C 3.8952,15 3,14.09982 3,13.008 V 4 z M 2,2 H 14 V 3 H 2 V 2 z M 5,1 h 6 V 2 H 5 V 1 z" + id="path4781" + inkscape:connector-curvature="0" + style="fill:#212121" /> </g> - <g transform="translate(16,0)" id="g4783"> - <path d="M 13.526,6.25 H 12.0523 V 5.5 c 0,-0.414 -0.33011,-0.75 -0.73684,-0.75 H 9.84176 V 4 c 0,-0.414 -0.33011,-0.75 -0.73684,-0.75 H 8.36808 V 1.75 C 8.36808,1.423 8.16029,1.153 7.87366,1.0495 7.81987,1.021 7.74913,1 7.63124,1 c -3.6628,0 -6.6316,3.0218 -6.6316,6.75 0,3.7275 2.9687,6.75 6.6316,6.75 3.6629,0 6.6316,-3.0225 6.6316,-6.75 V 7 c 0,-0.414 -0.3301,-0.75 -0.73684,-0.75 z M 3.5786,8.5 C 2.96784,8.5 2.4733,7.99667 2.4733,7.375 2.4733,6.75333 2.9678,6.25 3.5786,6.25 4.1894,6.25 4.6839,6.75333 4.6839,7.375 4.6839,7.99667 4.1894,8.5 3.5786,8.5 z M 4.6839,4.375 c 0,-0.62175 0.49516,-1.125 1.1053,-1.125 0.61084,0 1.1053,0.50325 1.1053,1.125 C 6.8945,4.996 6.40008,5.5 5.7892,5.5 5.17909,5.5 4.6839,4.996 4.6839,4.375 z M 6.8944,13 c -0.61059,0 -1.1053,-0.50334 -1.1053,-1.1246 0,-0.62129 0.49467,-1.1254 1.1053,-1.1254 0.61063,0 1.1053,0.50409 1.1053,1.1254 C 7.9997,12.49668 7.50503,13 6.8944,13 z M 7.26282,9.25 C 6.65271,9.25 6.15752,8.746 6.15752,8.125 6.15752,7.504 6.65268,7 7.26282,7 c 0.61014,0 1.1053,0.504 1.1053,1.125 0,0.621 -0.49516,1.125 -1.1053,1.125 z m 3.6842,1.5 c -0.6101,0 -1.1053,-0.504 -1.1053,-1.125 0,-0.621 0.49516,-1.125 1.1053,-1.125 0.61011,0 1.1053,0.504 1.1053,1.125 0,0.621 -0.49516,1.125 -1.1053,1.125 z" id="path4787" inkscape:connector-curvature="0" style="fill:#212121"/> + <g + transform="translate(16,0)" + id="g4783"> + <path + d="M 13.526,6.25 H 12.0523 V 5.5 c 0,-0.414 -0.33011,-0.75 -0.73684,-0.75 H 9.84176 V 4 c 0,-0.414 -0.33011,-0.75 -0.73684,-0.75 H 8.36808 V 1.75 C 8.36808,1.423 8.16029,1.153 7.87366,1.0495 7.81987,1.021 7.74913,1 7.63124,1 c -3.6628,0 -6.6316,3.0218 -6.6316,6.75 0,3.7275 2.9687,6.75 6.6316,6.75 3.6629,0 6.6316,-3.0225 6.6316,-6.75 V 7 c 0,-0.414 -0.3301,-0.75 -0.73684,-0.75 z M 3.5786,8.5 C 2.96784,8.5 2.4733,7.99667 2.4733,7.375 2.4733,6.75333 2.9678,6.25 3.5786,6.25 4.1894,6.25 4.6839,6.75333 4.6839,7.375 4.6839,7.99667 4.1894,8.5 3.5786,8.5 z M 4.6839,4.375 c 0,-0.62175 0.49516,-1.125 1.1053,-1.125 0.61084,0 1.1053,0.50325 1.1053,1.125 C 6.8945,4.996 6.40008,5.5 5.7892,5.5 5.17909,5.5 4.6839,4.996 4.6839,4.375 z M 6.8944,13 c -0.61059,0 -1.1053,-0.50334 -1.1053,-1.1246 0,-0.62129 0.49467,-1.1254 1.1053,-1.1254 0.61063,0 1.1053,0.50409 1.1053,1.1254 C 7.9997,12.49668 7.50503,13 6.8944,13 z M 7.26282,9.25 C 6.65271,9.25 6.15752,8.746 6.15752,8.125 6.15752,7.504 6.65268,7 7.26282,7 c 0.61014,0 1.1053,0.504 1.1053,1.125 0,0.621 -0.49516,1.125 -1.1053,1.125 z m 3.6842,1.5 c -0.6101,0 -1.1053,-0.504 -1.1053,-1.125 0,-0.621 0.49516,-1.125 1.1053,-1.125 0.61011,0 1.1053,0.504 1.1053,1.125 0,0.621 -0.49516,1.125 -1.1053,1.125 z" + id="path4787" + inkscape:connector-curvature="0" + style="fill:#212121" /> </g> - <g transform="translate(32,0)" id="g4789"> - <path d="M 8,6 C 11.3137,6 14,5.10457 14,4 14,2.89543 11.3137,2 8,2 4.6863,2 2,2.89543 2,4 2,5.10457 4.6863,6 8,6 z m -6,7 c 0,1.1046 2.6863,2 6,2 3.3137,0 6,-0.89543 6,-2 v -2 c 0,1.1046 -2.6863,2 -6,2 -3.3137,0 -6,-0.89543 -6,-2 v 2 z m 0,-3 c 0,1.1046 2.6863,2 6,2 3.3137,0 6,-0.89543 6,-2 V 8 C 14,9.1046 11.3137,10 8,10 4.6863,10 2,9.10457 2,8 v 2 z M 2,7 c 0,1.1046 2.6863,2 6,2 3.3137,0 6,-0.89543 6,-2 V 5 C 14,6.1046 11.3137,7 8,7 4.6863,7 2,6.10457 2,5 v 2 z" id="path4793" inkscape:connector-curvature="0"/> + <g + transform="translate(32,0)" + id="g4789"> + <path + d="M 8,6 C 11.3137,6 14,5.10457 14,4 14,2.89543 11.3137,2 8,2 4.6863,2 2,2.89543 2,4 2,5.10457 4.6863,6 8,6 z m -6,7 c 0,1.1046 2.6863,2 6,2 3.3137,0 6,-0.89543 6,-2 v -2 c 0,1.1046 -2.6863,2 -6,2 -3.3137,0 -6,-0.89543 -6,-2 v 2 z m 0,-3 c 0,1.1046 2.6863,2 6,2 3.3137,0 6,-0.89543 6,-2 V 8 C 14,9.1046 11.3137,10 8,10 4.6863,10 2,9.10457 2,8 v 2 z M 2,7 c 0,1.1046 2.6863,2 6,2 3.3137,0 6,-0.89543 6,-2 V 5 C 14,6.1046 11.3137,7 8,7 4.6863,7 2,6.10457 2,5 v 2 z" + id="path4793" + inkscape:connector-curvature="0" /> </g> - <g transform="translate(48,0)" id="g4795"> - <g id="g4799"> - <g id="g4801" style="fill:none"> - <path d="M 0,0 H 16 V 16 H 0 z" id="path4803" inkscape:connector-curvature="0"/> - <path transform="translate(3,1)" d="M 6,0 H 0.9954 C 0.45567,0 0,0.45078 0,1.0068 v 11.986 c 0,0.5569 0.44565,1.0068 0.9954,1.0068 H 9.0046 C 9.54433,13.9996 10,13.54882 10,12.9928 V 3.9996 l -4,-4 z M 9.29,4 H 6 V 0.71 L 9.29,4 z" id="path4805" inkscape:connector-curvature="0" style="fill:#000000"/> - </g> + <g + transform="translate(48,0)" + id="g4795"> + <g + id="g4799"> + <g + id="g4801" + style="fill:none"> + <path + d="M 0,0 H 16 V 16 H 0 z" + id="path4803" + inkscape:connector-curvature="0" /> + <path + transform="translate(3,1)" + d="M 6,0 H 0.9954 C 0.45567,0 0,0.45078 0,1.0068 v 11.986 c 0,0.5569 0.44565,1.0068 0.9954,1.0068 H 9.0046 C 9.54433,13.9996 10,13.54882 10,12.9928 V 3.9996 l -4,-4 z M 9.29,4 H 6 V 0.71 L 9.29,4 z" + id="path4805" + inkscape:connector-curvature="0" + style="fill:#000000" /> </g> + </g> </g> - <g transform="translate(0,16)" id="g4807"> - <path d="M 6.5,3.2289 V 1 h 3 v 2.2289 c 0.70763,0.22225 1.3475,0.59759 1.8807,1.0872 l 1.9315,-1.1151 1.5,2.5981 -1.9305,1.1146 c 0.07749,0.34976 0.11835,0.71329 0.11835,1.0864 0,0.37311 -0.04086,0.73661 -0.11835,1.0864 l 1.9305,1.1146 -1.5,2.5981 -1.9315,-1.1151 C 10.84746,12.17371 10.2076,12.54904 9.5,12.7713 v 2.2289 h -3 V 12.7713 C 5.79237,12.54905 5.1525,12.17371 4.6193,11.6841 l -1.9315,1.1151 -1.5,-2.5981 1.9305,-1.1146 C 3.04081,8.73674 2.99995,8.37321 2.99995,8.0001 2.99995,7.62699 3.04081,7.26349 3.1183,6.9137 L 1.1878,5.7991 2.6878,3.201 4.6193,4.3161 C 5.15253,3.82649 5.7924,3.45116 6.5,3.2289 z M 8,10.5 C 9.3807,10.5 10.5,9.3807 10.5,8 10.5,6.6193 9.3807,5.5 8,5.5 6.6193,5.5 5.5,6.6193 5.5,8 c 0,1.3807 1.1193,2.5 2.5,2.5 z" id="path4811" inkscape:connector-curvature="0" style="fill:#212121"/> + <g + transform="translate(0,16)" + id="g4807"> + <path + d="M 6.5,3.2289 V 1 h 3 v 2.2289 c 0.70763,0.22225 1.3475,0.59759 1.8807,1.0872 l 1.9315,-1.1151 1.5,2.5981 -1.9305,1.1146 c 0.07749,0.34976 0.11835,0.71329 0.11835,1.0864 0,0.37311 -0.04086,0.73661 -0.11835,1.0864 l 1.9305,1.1146 -1.5,2.5981 -1.9315,-1.1151 C 10.84746,12.17371 10.2076,12.54904 9.5,12.7713 v 2.2289 h -3 V 12.7713 C 5.79237,12.54905 5.1525,12.17371 4.6193,11.6841 l -1.9315,1.1151 -1.5,-2.5981 1.9305,-1.1146 C 3.04081,8.73674 2.99995,8.37321 2.99995,8.0001 2.99995,7.62699 3.04081,7.26349 3.1183,6.9137 L 1.1878,5.7991 2.6878,3.201 4.6193,4.3161 C 5.15253,3.82649 5.7924,3.45116 6.5,3.2289 z M 8,10.5 C 9.3807,10.5 10.5,9.3807 10.5,8 10.5,6.6193 9.3807,5.5 8,5.5 6.6193,5.5 5.5,6.6193 5.5,8 c 0,1.3807 1.1193,2.5 2.5,2.5 z" + id="path4811" + inkscape:connector-curvature="0" + style="fill:#212121" /> </g> - <g transform="translate(16,16)" id="g4813"> - <path d="M 2,3.999 C 2,3.44729 2.45098,3.00004 2.99078,3.00004 h 5.0092 v 3 h -6 v -2.001 z M 2,11 h 6 v 3 H 2.9908 C 2.44361,14 2.00002,13.55734 2.00002,13.00104 v -2.001 z M 2,7 h 6 v 3 H 2 V 7 z M 9,3 h 5.0092 c 0.54719,0 0.99078,0.44266 0.99078,0.99896 v 2.001 h -6 v -3 z m 0,8 h 6 v 2.001 c 0,0.55171 -0.45098,0.99896 -0.99078,0.99896 h -5.0092 v -3 z M 9,7 h 6 v 3 H 9 V 7 z" id="path4817" inkscape:connector-curvature="0" style="fill:#212121"/> + <g + transform="translate(16,16)" + id="g4813"> + <path + d="M 2,3.999 C 2,3.44729 2.45098,3.00004 2.99078,3.00004 h 5.0092 v 3 h -6 v -2.001 z M 2,11 h 6 v 3 H 2.9908 C 2.44361,14 2.00002,13.55734 2.00002,13.00104 v -2.001 z M 2,7 h 6 v 3 H 2 V 7 z M 9,3 h 5.0092 c 0.54719,0 0.99078,0.44266 0.99078,0.99896 v 2.001 h -6 v -3 z m 0,8 h 6 v 2.001 c 0,0.55171 -0.45098,0.99896 -0.99078,0.99896 h -5.0092 v -3 z M 9,7 h 6 v 3 H 9 V 7 z" + id="path4817" + inkscape:connector-curvature="0" + style="fill:#212121" /> </g> - <g transform="translate(34,18)" id="g4819"> - <path transform="matrix(1.1,0,0,1.1,-3.3,-3.3)" d="m 8,13 c 2.7614,0 5,-2.2386 5,-5 C 13,5.2386 10.7614,3 8,3 5.2386,3 3,5.2386 3,8 c 0,2.7614 2.2386,5 5,5 z M 8,11 V 9 H 5 V 7 H 8 V 5 l 3,3 -3,3 z" id="path4823" inkscape:connector-curvature="0"/> + <g + transform="translate(34,18)" + id="g4819"> + <path + transform="matrix(1.1,0,0,1.1,-3.3,-3.3)" + d="m 8,13 c 2.7614,0 5,-2.2386 5,-5 C 13,5.2386 10.7614,3 8,3 5.2386,3 3,5.2386 3,8 c 0,2.7614 2.2386,5 5,5 z M 8,11 V 9 H 5 V 7 H 8 V 5 l 3,3 -3,3 z" + id="path4823" + inkscape:connector-curvature="0" /> </g> - <g transform="translate(50,17)" id="g4825"> - <g transform="translate(-76,-24)" id="g4829"> - <circle transform="matrix(1.2,0,0,1.2,72.4,21.2)" cx="10.5" cy="11.5" r="2.5" id="circle4831" d="M 13,11.5 C 13,12.880712 11.880712,14 10.5,14 9.1192881,14 8,12.880712 8,11.5 8,10.119288 9.1192881,9 10.5,9 11.880712,9 13,10.119288 13,11.5 z" sodipodi:cx="10.5" sodipodi:cy="11.5" sodipodi:rx="2.5" sodipodi:ry="2.5" style="fill:#009802"/> - <path d="m 78,25 c -0.54399,0 -1,0.45026 -1,1 v 8 c 0,0.53973 0.44936,1 1,1 h 3.0312 c -0.02335,-0.1633 -0.03125,-0.33024 -0.03125,-0.5 0,-0.16976 0.0079,-0.3367 0.03125,-0.5 H 78 v -8 h 3 v 3 h 3 v 1.5 c 0.1633,-0.02335 0.33024,0 0.5,0 0.16976,0 0.3367,-0.02335 0.5,0 V 28 l -3,-3 z m 4,1 2,2 h -2 z" id="path4833" inkscape:connector-curvature="0"/> - </g> + <g + transform="translate(50,17)" + id="g4825"> + <g + transform="translate(-76,-24)" + id="g4829"> + <circle + transform="matrix(1.2,0,0,1.2,72.4,21.2)" + cx="10.5" + cy="11.5" + r="2.5" + id="circle4831" + d="M 13,11.5 C 13,12.880712 11.880712,14 10.5,14 9.1192881,14 8,12.880712 8,11.5 8,10.119288 9.1192881,9 10.5,9 11.880712,9 13,10.119288 13,11.5 z" + sodipodi:cx="10.5" + sodipodi:cy="11.5" + sodipodi:rx="2.5" + sodipodi:ry="2.5" + style="fill:#009802" /> + <path + d="m 78,25 c -0.54399,0 -1,0.45026 -1,1 v 8 c 0,0.53973 0.44936,1 1,1 h 3.0312 c -0.02335,-0.1633 -0.03125,-0.33024 -0.03125,-0.5 0,-0.16976 0.0079,-0.3367 0.03125,-0.5 H 78 v -8 h 3 v 3 h 3 v 1.5 c 0.1633,-0.02335 0.33024,0 0.5,0 0.16976,0 0.3367,-0.02335 0.5,0 V 28 l -3,-3 z m 4,1 2,2 h -2 z" + id="path4833" + inkscape:connector-curvature="0" /> + </g> </g> - <g transform="translate(2,33)" id="g4835"> - <path transform="translate(-65.625,-24.5)" d="m 71.625,25.5 h -4.003 c -0.54399,0 -0.99703,0.44566 -0.99703,0.9954 v 8.0092 c 0,0.53973 0.44639,0.9954 0.99703,0.9954 h 6.0059 c 0.54399,0 0.99703,-0.44566 0.99703,-0.9954 V 28.5 l -3,-3 z m 0,1 2,2 h -2 v -2 z m -4,0 h 3 v 3 h 3 v 5 h -6 v -8 z" id="path4839" inkscape:connector-curvature="0"/> + <g + transform="translate(2,33)" + id="g4835"> + <path + transform="translate(-65.625,-24.5)" + d="m 71.625,25.5 h -4.003 c -0.54399,0 -0.99703,0.44566 -0.99703,0.9954 v 8.0092 c 0,0.53973 0.44639,0.9954 0.99703,0.9954 h 6.0059 c 0.54399,0 0.99703,-0.44566 0.99703,-0.9954 V 28.5 l -3,-3 z m 0,1 2,2 h -2 v -2 z m -4,0 h 3 v 3 h 3 v 5 h -6 v -8 z" + id="path4839" + inkscape:connector-curvature="0" /> </g> - <g transform="translate(17,33)" id="g4841"> - <path transform="translate(-160,-96)" d="m 160,102.5 c 0,3.59 2.91,6.5 6.5,6.5 3.59,0 6.5,-2.91 6.5,-6.5 0,-3.59 -2.91,-6.5 -6.5,-6.5 -3.59,0 -6.5,2.91 -6.5,6.5" id="path4845" inkscape:connector-curvature="0" style="fill:#9f9f9f"/><path transform="translate(-160,-96)" d="m 170,100.43 -0.93,-0.93 -2.57,2.57 -2.57,-2.57 -0.93,0.93 2.57,2.57 -2.57,2.57 0.93,0.93 2.57,-2.57 2.57,2.57 0.93,-0.93 -2.57,-2.57 2.57,-2.57 z" id="path4847" inkscape:connector-curvature="0" style="fill-opacity:0.36000001"/><path transform="translate(-160,-96)" d="M 170,99.93 169.07,99 166.5,101.57 163.93,99 163,99.93 l 2.57,2.57 -2.57,2.57 0.93,0.93 2.57,-2.57 2.57,2.57 0.93,-0.93 -2.57,-2.57 2.57,-2.57 z" id="path4849" inkscape:connector-curvature="0" style="fill:#ffffff"/> + <g + transform="translate(17,33)" + id="g4841"> + <path + transform="translate(-160,-96)" + d="m 160,102.5 c 0,3.59 2.91,6.5 6.5,6.5 3.59,0 6.5,-2.91 6.5,-6.5 0,-3.59 -2.91,-6.5 -6.5,-6.5 -3.59,0 -6.5,2.91 -6.5,6.5" + id="path4845" + inkscape:connector-curvature="0" + style="fill:#9f9f9f" /> + <path + transform="translate(-160,-96)" + d="m 170,100.43 -0.93,-0.93 -2.57,2.57 -2.57,-2.57 -0.93,0.93 2.57,2.57 -2.57,2.57 0.93,0.93 2.57,-2.57 2.57,2.57 0.93,-0.93 -2.57,-2.57 2.57,-2.57 z" + id="path4847" + inkscape:connector-curvature="0" + style="fill-opacity:0.36000001" /> + <path + transform="translate(-160,-96)" + d="M 170,99.93 169.07,99 166.5,101.57 163.93,99 163,99.93 l 2.57,2.57 -2.57,2.57 0.93,0.93 2.57,-2.57 2.57,2.57 0.93,-0.93 -2.57,-2.57 2.57,-2.57 z" + id="path4849" + inkscape:connector-curvature="0" + style="fill:#ffffff" /> </g> - <g transform="translate(33,33)" id="g4851"> - <path transform="translate(-143,-96)" d="m 143,102.5 c 0,3.59 2.91,6.5 6.5,6.5 3.59,0 6.5,-2.91 6.5,-6.5 0,-3.59 -2.91,-6.5 -6.5,-6.5 -3.59,0 -6.5,2.91 -6.5,6.5" id="path4855" inkscape:connector-curvature="0" style="fill:#bebebe"/><path transform="translate(-143,-96)" d="m 153,100.43 -0.93,-0.93 -2.57,2.57 -2.57,-2.57 -0.93,0.93 2.57,2.57 -2.57,2.57 0.93,0.93 2.57,-2.57 2.57,2.57 0.93,-0.93 -2.57,-2.57 2.57,-2.57 z" id="path4857" inkscape:connector-curvature="0" style="fill-opacity:0.37000002"/><path transform="translate(-143,-96)" d="M 153,99.93 152.07,99 149.5,101.57 146.93,99 146,99.93 l 2.57,2.57 -2.57,2.57 0.93,0.93 2.57,-2.57 2.57,2.57 0.93,-0.93 -2.57,-2.57 2.57,-2.57 z" id="path4859" inkscape:connector-curvature="0" style="fill:#ffffff"/> + <g + transform="translate(33,33)" + id="g4851"> + <path + transform="translate(-143,-96)" + d="m 143,102.5 c 0,3.59 2.91,6.5 6.5,6.5 3.59,0 6.5,-2.91 6.5,-6.5 0,-3.59 -2.91,-6.5 -6.5,-6.5 -3.59,0 -6.5,2.91 -6.5,6.5" + id="path4855" + inkscape:connector-curvature="0" + style="fill:#bebebe" /> + <path + transform="translate(-143,-96)" + d="m 153,100.43 -0.93,-0.93 -2.57,2.57 -2.57,-2.57 -0.93,0.93 2.57,2.57 -2.57,2.57 0.93,0.93 2.57,-2.57 2.57,2.57 0.93,-0.93 -2.57,-2.57 2.57,-2.57 z" + id="path4857" + inkscape:connector-curvature="0" + style="fill-opacity:0.37000002" /> + <path + transform="translate(-143,-96)" + d="M 153,99.93 152.07,99 149.5,101.57 146.93,99 146,99.93 l 2.57,2.57 -2.57,2.57 0.93,0.93 2.57,-2.57 2.57,2.57 0.93,-0.93 -2.57,-2.57 2.57,-2.57 z" + id="path4859" + inkscape:connector-curvature="0" + style="fill:#ffffff" /> </g> - <g transform="translate(49,33)" id="g4861"> - <path transform="translate(-111,-96)" d="m 118,96 c -3.87,0 -7,3.13 -7,7 0,3.87 3.13,7 7,7 3.87,0 7,-3.13 7,-7 0,-3.87 -3.13,-7 -7,-7" id="path4865" inkscape:connector-curvature="0" style="fill:url(#sprite12_a)"/><path transform="translate(-111,-96)" d="m 111.5,103 c 0,3.59 2.91,6.5 6.5,6.5 3.59,0 6.5,-2.91 6.5,-6.5 0,-3.59 -2.91,-6.5 -6.5,-6.5 -3.59,0 -6.5,2.91 -6.5,6.5" id="path4867" inkscape:connector-curvature="0" style="fill:#f27d82"/><path transform="translate(-111,-96)" d="m 121.5,100.93 -0.93,-0.93 -2.57,2.57 -2.57,-2.57 -0.93,0.93 2.57,2.57 -2.57,2.57 0.93,0.93 2.57,-2.57 2.57,2.57 0.93,-0.93 -2.57,-2.57 2.57,-2.57 z" id="path4869" inkscape:connector-curvature="0" style="fill-opacity:0.36000001"/><path transform="translate(-111,-96)" d="m 121.5,100.43 -0.93,-0.93 -2.57,2.57 -2.57,-2.57 -0.93,0.93 2.57,2.57 -2.57,2.57 0.93,0.93 2.57,-2.57 2.57,2.57 0.93,-0.93 -2.57,-2.57 2.57,-2.57 z" id="path4871" inkscape:connector-curvature="0" style="fill:#ffffff"/><defs id="defs4873"> - <linearGradient id="sprite12_r"> - <stop stop-color="#d7687d" offset="0" id="stop4876"/> - <stop stop-color="#b21402" offset="1" id="stop4878"/> - </linearGradient> - <linearGradient id="sprite12_a" x2="24" gradientTransform="matrix(0,-0.58333,-0.58333,0,118,110)" gradientUnits="userSpaceOnUse" xlink:href="#sprite12_r"/> - </defs> + <g + transform="translate(49,33)" + id="g4861"> + <path + transform="translate(-111,-96)" + d="m 118,96 c -3.87,0 -7,3.13 -7,7 0,3.87 3.13,7 7,7 3.87,0 7,-3.13 7,-7 0,-3.87 -3.13,-7 -7,-7" + id="path4865" + inkscape:connector-curvature="0" + style="fill:url(#sprite12_a)" /> + <path + transform="translate(-111,-96)" + d="m 111.5,103 c 0,3.59 2.91,6.5 6.5,6.5 3.59,0 6.5,-2.91 6.5,-6.5 0,-3.59 -2.91,-6.5 -6.5,-6.5 -3.59,0 -6.5,2.91 -6.5,6.5" + id="path4867" + inkscape:connector-curvature="0" + style="fill:#f27d82" /> + <path + transform="translate(-111,-96)" + d="m 121.5,100.93 -0.93,-0.93 -2.57,2.57 -2.57,-2.57 -0.93,0.93 2.57,2.57 -2.57,2.57 0.93,0.93 2.57,-2.57 2.57,2.57 0.93,-0.93 -2.57,-2.57 2.57,-2.57 z" + id="path4869" + inkscape:connector-curvature="0" + style="fill-opacity:0.36000001" /> + <path + transform="translate(-111,-96)" + d="m 121.5,100.43 -0.93,-0.93 -2.57,2.57 -2.57,-2.57 -0.93,0.93 2.57,2.57 -2.57,2.57 0.93,0.93 2.57,-2.57 2.57,2.57 0.93,-0.93 -2.57,-2.57 2.57,-2.57 z" + id="path4871" + inkscape:connector-curvature="0" + style="fill:#ffffff" /> + <defs + id="defs4873"> + <linearGradient + id="sprite12_r"> + <stop + stop-color="#d7687d" + offset="0" + id="stop4876" /> + <stop + stop-color="#b21402" + offset="1" + id="stop4878" /> + </linearGradient> + <linearGradient + id="sprite12_a" + x2="24" + gradientTransform="matrix(0,-0.58333,-0.58333,0,118,110)" + gradientUnits="userSpaceOnUse" + xlink:href="#sprite12_r" /> + </defs> </g> - <g transform="translate(1,49)" id="g4881"> - <path transform="translate(-96,-96)" d="m 103,110 c 3.87,0 7,-3.13 7,-7 0,-3.87 -3.13,-7 -7,-7 -3.87,0 -7,3.13 -7,7 0,3.87 3.13,7 7,7" id="path4885" inkscape:connector-curvature="0" style="fill:url(#sprite13_a)"/><path transform="translate(-96,-96)" d="m 103,96.5 c -3.59,0 -6.5,2.91 -6.5,6.5 0,3.59 2.91,6.5 6.5,6.5 3.59,0 6.5,-2.91 6.5,-6.5 0,-3.59 -2.91,-6.5 -6.5,-6.5" id="path4887" inkscape:connector-curvature="0" style="fill:url(#sprite13_b)"/><path transform="translate(-96,-96)" d="m 106.5,100.93 -0.93,-0.93 -2.57,2.57 -2.57,-2.57 -0.93,0.93 2.57,2.57 -2.57,2.57 0.93,0.93 2.57,-2.57 2.57,2.57 0.93,-0.93 -2.57,-2.57 2.57,-2.57 z" id="path4889" inkscape:connector-curvature="0" style="fill:#993c35"/><path transform="translate(-96,-96)" d="m 106.5,100.43 -0.93,-0.93 -2.57,2.57 -2.57,-2.57 -0.93,0.93 2.57,2.57 -2.57,2.57 0.93,0.93 2.57,-2.57 2.57,2.57 0.93,-0.93 -2.57,-2.57 2.57,-2.57 z" id="path4891" inkscape:connector-curvature="0" style="fill:#ffffff"/><defs id="defs4893"> - <linearGradient id="sprite13_b" x1="96.5" x2="109.5" y1="103" y2="103" gradientTransform="matrix(0,1,-1,0,206,0)" gradientUnits="userSpaceOnUse" xlink:href="#sprite13_q"/> - <linearGradient id="sprite13_q"> - <stop stop-color="#e59290" offset="0" id="stop4897"/> - <stop stop-color="#e99890" offset="1" id="stop4899"/> - </linearGradient> - <linearGradient id="sprite13_a" x1="113" x2="127" y1="104" y2="104" gradientTransform="matrix(0,1,-1,0,207,-17)" gradientUnits="userSpaceOnUse" xlink:href="#sprite13_r"/> - <linearGradient id="sprite13_r"> - <stop stop-color="#c0544f" offset="0" id="stop4903"/> - <stop stop-color="#d08481" offset="1" id="stop4905"/> - </linearGradient> - </defs> + <g + transform="translate(1,49)" + id="g4881"> + <path + transform="translate(-96,-96)" + d="m 103,110 c 3.87,0 7,-3.13 7,-7 0,-3.87 -3.13,-7 -7,-7 -3.87,0 -7,3.13 -7,7 0,3.87 3.13,7 7,7" + id="path4885" + inkscape:connector-curvature="0" + style="fill:url(#sprite13_a)" /> + <path + transform="translate(-96,-96)" + d="m 103,96.5 c -3.59,0 -6.5,2.91 -6.5,6.5 0,3.59 2.91,6.5 6.5,6.5 3.59,0 6.5,-2.91 6.5,-6.5 0,-3.59 -2.91,-6.5 -6.5,-6.5" + id="path4887" + inkscape:connector-curvature="0" + style="fill:url(#sprite13_b)" /> + <path + transform="translate(-96,-96)" + d="m 106.5,100.93 -0.93,-0.93 -2.57,2.57 -2.57,-2.57 -0.93,0.93 2.57,2.57 -2.57,2.57 0.93,0.93 2.57,-2.57 2.57,2.57 0.93,-0.93 -2.57,-2.57 2.57,-2.57 z" + id="path4889" + inkscape:connector-curvature="0" + style="fill:#993c35" /> + <path + transform="translate(-96,-96)" + d="m 106.5,100.43 -0.93,-0.93 -2.57,2.57 -2.57,-2.57 -0.93,0.93 2.57,2.57 -2.57,2.57 0.93,0.93 2.57,-2.57 2.57,2.57 0.93,-0.93 -2.57,-2.57 2.57,-2.57 z" + id="path4891" + inkscape:connector-curvature="0" + style="fill:#ffffff" /> + <defs + id="defs4893"> + <linearGradient + id="sprite13_b" + x1="96.5" + x2="109.5" + y1="103" + y2="103" + gradientTransform="matrix(0,1,-1,0,206,0)" + gradientUnits="userSpaceOnUse" + xlink:href="#sprite13_q" /> + <linearGradient + id="sprite13_q"> + <stop + stop-color="#e59290" + offset="0" + id="stop4897" /> + <stop + stop-color="#e99890" + offset="1" + id="stop4899" /> + </linearGradient> + <linearGradient + id="sprite13_a" + x1="113" + x2="127" + y1="104" + y2="104" + gradientTransform="matrix(0,1,-1,0,207,-17)" + gradientUnits="userSpaceOnUse" + xlink:href="#sprite13_r" /> + <linearGradient + id="sprite13_r"> + <stop + stop-color="#c0544f" + offset="0" + id="stop4903" /> + <stop + stop-color="#d08481" + offset="1" + id="stop4905" /> + </linearGradient> + </defs> </g> - <g transform="translate(18,50)" id="g4907"> - <path transform="translate(-234,-30)" d="m 242.27,38.92 c -0.75073,0.56132 -1.6826,0.89372 -2.6921,0.89372 -2.4853,0 -4.5,-2.0147 -4.5,-4.5 0,-2.4853 2.0147,-4.5 4.5,-4.5 2.4853,0 4.5,2.0147 4.5,4.5 0,1.1154 -0.40579,2.136 -1.0778,2.9222 l 2.3456,2.3456 -0.70711,0.70711 z m -2.6921,-0.10628 c 1.933,0 3.5,-1.567 3.5,-3.5 0,-1.933 -1.567,-3.5 -3.5,-3.5 -1.933,0 -3.5,1.567 -3.5,3.5 0,1.933 1.567,3.5 3.5,3.5 z" id="path4911" inkscape:connector-curvature="0" style="fill:#5b5b5b"/> + <g + transform="translate(18,50)" + id="g4907"> + <path + transform="translate(-234,-30)" + d="m 242.27,38.92 c -0.75073,0.56132 -1.6826,0.89372 -2.6921,0.89372 -2.4853,0 -4.5,-2.0147 -4.5,-4.5 0,-2.4853 2.0147,-4.5 4.5,-4.5 2.4853,0 4.5,2.0147 4.5,4.5 0,1.1154 -0.40579,2.136 -1.0778,2.9222 l 2.3456,2.3456 -0.70711,0.70711 z m -2.6921,-0.10628 c 1.933,0 3.5,-1.567 3.5,-3.5 0,-1.933 -1.567,-3.5 -3.5,-3.5 -1.933,0 -3.5,1.567 -3.5,3.5 0,1.933 1.567,3.5 3.5,3.5 z" + id="path4911" + inkscape:connector-curvature="0" + style="fill:#5b5b5b" /> </g> - <text xml:space="preserve" style="font-size:10px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Sans" x="-11.403088" y="59.207676" id="text4355" sodipodi:linespacing="125%"><tspan sodipodi:role="line" id="tspan4357" x="-11.403088" y="59.207676">1</tspan></text> - <text xml:space="preserve" style="font-size:10px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Sans" x="-11.144299" y="43.675297" id="text4355-8" sodipodi:linespacing="125%"><tspan sodipodi:role="line" id="tspan4357-8" x="-11.144299" y="43.675297">2</tspan></text> - <text xml:space="preserve" style="font-size:10px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Sans" x="-11.066174" y="28.142918" id="text4355-4" sodipodi:linespacing="125%"><tspan sodipodi:role="line" id="tspan4357-3" x="-11.066174" y="28.142918">3</tspan></text> - <text xml:space="preserve" style="font-size:10px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Sans" x="-11.266369" y="12.610539" id="text4355-1" sodipodi:linespacing="125%"><tspan sodipodi:role="line" id="tspan4357-4" x="-11.266369" y="12.610539">4</tspan></text> - <text xml:space="preserve" style="font-size:10px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Sans" x="5.9353299" y="76.082359" id="text4355-9" sodipodi:linespacing="125%"><tspan sodipodi:role="line" id="tspan4357-2" x="5.9353299" y="76.082359">a</tspan></text> - <text xml:space="preserve" style="font-size:10px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Sans" x="21.659466" y="76.082359" id="text4355-0" sodipodi:linespacing="125%"><tspan sodipodi:role="line" id="tspan4357-6" x="21.659466" y="76.082359">b</tspan></text> - <text xml:space="preserve" style="font-size:10px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Sans" x="37.383606" y="76.082359" id="text4355-89" sodipodi:linespacing="125%"><tspan sodipodi:role="line" id="tspan4357-26" x="37.383606" y="76.082359">c</tspan></text> - <text xml:space="preserve" style="font-size:10px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Sans" x="53.107742" y="76.082359" id="text4355-6" sodipodi:linespacing="125%"><tspan sodipodi:role="line" id="tspan4357-49" x="53.107742" y="76.082359">d</tspan></text> + <text + xml:space="preserve" + style="font-size:10px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Sans" + x="-11.403088" + y="59.207676" + id="text4355" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4357" + x="-11.403088" + y="59.207676">1</tspan></text> + <text + xml:space="preserve" + style="font-size:10px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Sans" + x="-11.144299" + y="43.675297" + id="text4355-8" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4357-8" + x="-11.144299" + y="43.675297">2</tspan></text> + <text + xml:space="preserve" + style="font-size:10px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Sans" + x="-11.066174" + y="28.142918" + id="text4355-4" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4357-3" + x="-11.066174" + y="28.142918">3</tspan></text> + <text + xml:space="preserve" + style="font-size:10px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Sans" + x="-11.266369" + y="12.610539" + id="text4355-1" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4357-4" + x="-11.266369" + y="12.610539">4</tspan></text> + <text + xml:space="preserve" + style="font-size:10px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Sans" + x="5.9353299" + y="76.082359" + id="text4355-9" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4357-2" + x="5.9353299" + y="76.082359">a</tspan></text> + <text + xml:space="preserve" + style="font-size:10px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Sans" + x="21.659466" + y="76.082359" + id="text4355-0" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4357-6" + x="21.659466" + y="76.082359">b</tspan></text> + <text + xml:space="preserve" + style="font-size:10px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Sans" + x="37.383606" + y="76.082359" + id="text4355-89" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4357-26" + x="37.383606" + y="76.082359">c</tspan></text> + <text + xml:space="preserve" + style="font-size:10px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Sans" + x="53.107742" + y="76.082359" + id="text4355-6" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4357-49" + x="53.107742" + y="76.082359">d</tspan></text> + <g + style="fill:none;stroke:none" + id="g6346" + transform="translate(32,48)"> + <polygon + points="16,16 0,16 0,0 16,0 " + id="polygon6348" /> + <path + style="fill:#000000" + inkscape:connector-curvature="0" + id="path6350" + d="M 8,1 C 4.136,1 1,4.136 1,8 c 0,3.864 3.136,7 7,7 3.864,0 7,-3.136 7,-7 C 15,4.136 11.864,1 8,1 L 8,1 z M 2.5,8 C 2.5,4.968125 4.968125,2.5 8,2.5 c 3.031875,0 5.5,2.468125 5.5,5.5 0,3.031875 -2.468125,5.5 -5.5,5.5 C 4.968125,13.5 2.5,11.031875 2.5,8 z M 9,12 9,7 7,7 7,12 9,12 z M 7,6 9,6 9,4 7,4 7,6 7,6 z" /> + </g> </svg> -
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes b/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes index c91f6e8..656c2c3 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes +++ b/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes
@@ -4,8 +4,8 @@ "breakpointConditional.svg": "4cf90210b2af2ed84db2f60b07bcde28", "checkboxCheckmark.svg": "f039bf85cee42ad5c30ca3bfdce7912a", "errorWave.svg": "e183fa242a22ed4784a92f6becbc2c45", - "smallIcons.svg": "a0d37d8680ac0f0fbfa6ab053de90b04", - "mediumIcons.svg": "e63ac6385b0a6efb783d9838517e5e44", + "smallIcons.svg": "911ffe3e3692229022105c5a51d20bb9", + "mediumIcons.svg": "84090b8a5c439d6d3022f5fbc4dd8221", "breakpoint.svg": "69cd92d807259c022791112809b97799", "treeoutlineTriangles.svg": "017d2f89437df0afc6b9cd5ff43735d9", "chevrons.svg": "79b4b527771e30b6388ce664077b3409"
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/src/smallIcons.svg b/third_party/WebKit/Source/devtools/front_end/Images/src/smallIcons.svg index dabd05a..b784b81 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/src/smallIcons.svg +++ b/third_party/WebKit/Source/devtools/front_end/Images/src/smallIcons.svg
@@ -36,17 +36,17 @@ guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" - inkscape:window-width="938" - inkscape:window-height="826" + inkscape:window-width="1272" + inkscape:window-height="1376" id="namedview4455" showgrid="true" - inkscape:zoom="3.7083823" - inkscape:cx="22.472364" - inkscape:cy="66.155904" - inkscape:window-x="1280" + inkscape:zoom="20.977778" + inkscape:cx="54.131178" + inkscape:cy="94.103295" + inkscape:window-x="980" inkscape:window-y="0" inkscape:window-maximized="0" - inkscape:current-layer="svg4185"> + inkscape:current-layer="g74"> <inkscape:grid type="xygrid" id="grid4461" @@ -787,4 +787,31 @@ id="tspan5193-90-6" x="-6.6795936" y="8">6</tspan></text> + <g + transform="translate(13.293,-7.4383945)" + id="g74"> + <path + style="fill:none" + inkscape:connector-curvature="0" + id="path80" + d="M 4.308,4.525 H 20.5404 V 20.7574 H 4.308 z" /> + <path + style="fill-rule:evenodd" + inkscape:connector-curvature="0" + id="path82" + d="M 7.8179366,12.994649 6.707,14.105586 10.040596,17.438394 16.707,10.77199 15.596064,9.6610525 10.040596,15.216521 z" /> + <g + transform="matrix(0.76923077,0,0,0.76923077,19.014692,2.8283064)" + id="g92"> + <path + transform="translate(-64,0)" + d="m 80.44,16.94 c -2.48,0 -4.5,-2.02 -4.5,-4.5 0,-0.88 0.26,-1.7 0.69,-2.39 l 6.2,6.2 c -0.69,0.44 -1.51,0.69 -2.39,0.69 m 4.5,-4.5 c 0,0.88 -0.26,1.7 -0.69,2.39 l -6.2,-6.2 c 0.69,-0.44 1.51,-0.69 2.39,-0.69 2.48,0 4.5,2.02 4.5,4.5 M 80.5,6 C 76.91,6 74,8.91 74,12.5 74,16.09 76.91,19 80.5,19 84.09,19 87,16.09 87,12.5 87,8.91 84.09,6 80.5,6" + id="path96" + inkscape:connector-curvature="0" /> + </g> + <path + style="fill-rule:evenodd" + d="m 55.582,9.6571445 -5.53125,5.5625005 -0.40625,-0.40625 -1.09375,1.125 1.5,1.499999 6.65625,-6.656249 -1.125,-1.1250005 z" + id="path3185" /> + </g> </svg>
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes b/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes index c91f6e8..656c2c3 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes +++ b/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes
@@ -4,8 +4,8 @@ "breakpointConditional.svg": "4cf90210b2af2ed84db2f60b07bcde28", "checkboxCheckmark.svg": "f039bf85cee42ad5c30ca3bfdce7912a", "errorWave.svg": "e183fa242a22ed4784a92f6becbc2c45", - "smallIcons.svg": "a0d37d8680ac0f0fbfa6ab053de90b04", - "mediumIcons.svg": "e63ac6385b0a6efb783d9838517e5e44", + "smallIcons.svg": "911ffe3e3692229022105c5a51d20bb9", + "mediumIcons.svg": "84090b8a5c439d6d3022f5fbc4dd8221", "breakpoint.svg": "69cd92d807259c022791112809b97799", "treeoutlineTriangles.svg": "017d2f89437df0afc6b9cd5ff43735d9", "chevrons.svg": "79b4b527771e30b6388ce664077b3409"
diff --git a/third_party/WebKit/Source/devtools/front_end/color_picker/Contrast.js b/third_party/WebKit/Source/devtools/front_end/color_picker/Contrast.js new file mode 100644 index 0000000..ea0e71cb --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/color_picker/Contrast.js
@@ -0,0 +1,555 @@ +// 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. + +ColorPicker.ContrastInfo = class { + constructor() { + /** @type {?Array<number>} */ + this._hsva = null; + + /** @type {?Common.Color} */ + this._bgColor = null; + + /** @type {?number} */ + this._contrastRatio = null; + + /** @type {?Object<string, number>} */ + this._contrastRatioThresholds = null; + + /** @type {string} */ + this._colorString = ''; + } + + /** + * @param {?SDK.CSSModel.ContrastInfo} contrastInfo + */ + setContrastInfo(contrastInfo) { + this._contrastRatio = null; + this._contrastRatioThresholds = null; + this._bgColor = null; + + // TODO(aboxhall): distinguish between !backgroundColors (no text) and + // !backgroundColors.length (no computed bg color) + if (!contrastInfo.backgroundColors || !contrastInfo.backgroundColors.length) + return; + + if (contrastInfo.computedFontSize && contrastInfo.computedFontWeight && contrastInfo.computedBodyFontSize) { + var isLargeFont = ColorPicker.ContrastInfo.computeIsLargeFont( + contrastInfo.computedFontSize, contrastInfo.computedFontWeight, contrastInfo.computedBodyFontSize); + + this._contrastRatioThresholds = + ColorPicker.ContrastInfo._ContrastThresholds[(isLargeFont ? 'largeFont' : 'normalFont')]; + } + + // TODO(aboxhall): figure out what to do in the case of multiple background colors (i.e. gradients) + var bgColorText = contrastInfo.backgroundColors[0]; + var bgColor = Common.Color.parse(bgColorText); + if (!bgColor) + return; + + this.setBgColor(bgColor); + } + + /** + * @param {!Array<number>} hsva + * @param {string} colorString + */ + setColor(hsva, colorString) { + this._hsva = hsva; + this._colorString = colorString; + this._updateContrastRatio(); + } + + /** + * @return {string} + */ + colorString() { + return this._colorString; + } + + /** + * @return {?Array<number>} + */ + hsva() { + return this._hsva; + } + + /** + * @param {!Common.Color} bgColor + */ + setBgColor(bgColor) { + this._bgColor = bgColor; + + if (!this._hsva) + return; + + var fgRGBA = []; + Common.Color.hsva2rgba(this._hsva, fgRGBA); + + // If we have a semi-transparent background color over an unknown + // background, draw the line for the "worst case" scenario: where + // the unknown background is the same color as the text. + if (bgColor.hasAlpha) { + var blendedRGBA = []; + Common.Color.blendColors(bgColor.rgba(), fgRGBA, blendedRGBA); + this._bgColor = new Common.Color(blendedRGBA, Common.Color.Format.RGBA); + } + + var bgRGBA = this._bgColor.rgba(); + this._contrastRatio = Common.Color.calculateContrastRatio(fgRGBA, bgRGBA); + } + + /** + * @return {?number} + */ + contrastRatio() { + return this._contrastRatio; + } + + /** + * @return {?Common.Color} + */ + bgColor() { + return this._bgColor; + } + + _updateContrastRatio() { + if (!this._bgColor || !this._hsva) + return; + var fgRGBA = []; + Common.Color.hsva2rgba(this._hsva, fgRGBA); + var bgRGBA = this._bgColor.rgba(); + this._contrastRatio = Common.Color.calculateContrastRatio(fgRGBA, bgRGBA); + } + + /** + * @param {string} level + * @return {?number} + */ + contrastRatioThreshold(level) { + return this._contrastRatioThresholds[level]; + } + + /** + * @param {string} fontSize + * @param {string} fontWeight + * @param {?string} bodyFontSize + * @return {boolean} + */ + static computeIsLargeFont(fontSize, fontWeight, bodyFontSize) { + const boldWeights = ['bold', 'bolder', '600', '700', '800', '900']; + + var fontSizePx = parseFloat(fontSize.replace('px', '')); + var isBold = (boldWeights.indexOf(fontWeight) !== -1); + + if (bodyFontSize) { + var bodyFontSizePx = parseFloat(bodyFontSize.replace('px', '')); + if (isBold) { + if (fontSizePx >= (bodyFontSizePx * 1.2)) + return true; + } else if (fontSizePx >= (bodyFontSizePx * 1.5)) { + return true; + } + return false; + } + + var fontSizePt = Math.ceil(fontSizePx * 72 / 96); + if (isBold) + return fontSizePt >= 14; + else + return fontSizePt >= 18; + } +}; + +ColorPicker.ContrastInfo._ContrastThresholds = { + largeFont: {AA: 3.0, AAA: 4.5}, + normalFont: {AA: 4.5, AAA: 7.0} +}; + +ColorPicker.ContrastOverlay = class { + /** + * @param {!Element} colorElement + * @param {!Element} contentElement + * @param {function(boolean=, !Common.Event=)} toggleMainColorPickerCallback + */ + constructor(colorElement, contentElement, toggleMainColorPickerCallback) { + this._contrastInfo = new ColorPicker.ContrastInfo(); + + var contrastRatioSVG = colorElement.createSVGChild('svg', 'spectrum-contrast-container fill'); + this._contrastRatioLine = contrastRatioSVG.createSVGChild('path', 'spectrum-contrast-line'); + + this._contrastValueBubble = colorElement.createChild('div', 'spectrum-contrast-info'); + this._contrastValueBubble.classList.add('force-white-icons'); + this._contrastValueBubble.createChild('span', 'low-contrast').textContent = Common.UIString('Low contrast'); + this._contrastValue = this._contrastValueBubble.createChild('span', 'value'); + this._contrastValueBubble.appendChild(UI.Icon.create('smallicon-contrast-ratio')); + this._contrastValueBubble.title = Common.UIString('Click to toggle contrast ratio details'); + this._contrastValueBubble.addEventListener('mousedown', this._toggleContrastDetails.bind(this), true); + + this._contrastDetails = new ColorPicker.ContrastDetails( + this._contrastInfo, contentElement, toggleMainColorPickerCallback, this._update.bind(this)); + + this._width = 0; + this._height = 0; + } + + /** + * @param {?SDK.CSSModel.ContrastInfo} contrastInfo + */ + setContrastInfo(contrastInfo) { + this._contrastInfo.setContrastInfo(contrastInfo); + this._update(); + } + + /** + * @param {!Array<number>} hsva + * @param {string} colorString + */ + setColor(hsva, colorString) { + this._contrastInfo.setColor(hsva, colorString); + this._update(); + } + + /** + * @param {number} x + * @param {number} y + */ + moveAwayFrom(x, y) { + var bubble = this._contrastValueBubble; + if (!bubble.boxInWindow().contains(x, y)) + return; + + if (bubble.offsetWidth > ((bubble.offsetParent.offsetWidth / 2) - 10)) + bubble.classList.toggle('contrast-info-top'); + else + bubble.classList.toggle('contrast-info-left'); + } + + _update() { + if (this._contrastInfo.contrastRatio() === null) + return; + + this._contrastValue.textContent = this._contrastInfo.contrastRatio().toFixed(2); + + var AA = this._contrastInfo.contrastRatioThreshold('AA'); + if (!AA) + return; + + // TODO(aboxhall): only redraw line if hue value changes + this._drawContrastRatioLine(AA, this._width, this._height); + + var passesAA = this._contrastInfo.contrastRatio() >= AA; + this._contrastValueBubble.classList.toggle('contrast-fail', !passesAA); + + this._contrastDetails.update(); + } + + /** + * @param {number} width + * @param {number} height + * @param {!AnchorBox} draggerBox + */ + show(width, height, draggerBox) { + if (this._contrastInfo.contrastRatio() === null) { + this.hide(); + return; + } + + this._width = width; + this._height = height; + this._update(); + + this._contrastValueBubble.classList.remove('hidden'); + + var dragX = draggerBox.x + (draggerBox.width / 2); + var dragY = draggerBox.y + (draggerBox.height / 2); + this.moveAwayFrom(dragX, dragY); + } + + hide() { + this._contrastValueBubble.classList.add('hidden'); + } + + /** + * @param {!Event} event + */ + _toggleContrastDetails(event) { + if ('button' in event && event.button !== 0) + return; + event.consume(); + this._contrastDetails.toggleVisible(); + } + + /** + * @param {number} requiredContrast + * @param {number} width + * @param {number} height + */ + _drawContrastRatioLine(requiredContrast, width, height) { + // TODO(aboxhall): throttle this to avoid being called in rapid succession when using eyedropper + if (!width || !height) + return; + + var hsva = this._contrastInfo.hsva(); + var bgColor = this._contrastInfo.bgColor(); + if (!hsva || !bgColor) + return; + + const dS = 0.02; + const epsilon = 0.002; + const H = 0; + const S = 1; + const V = 2; + const A = 3; + + var fgRGBA = []; + Common.Color.hsva2rgba(hsva, fgRGBA); + var bgRGBA = bgColor.rgba(); + var bgLuminance = Common.Color.luminance(bgRGBA); + var blendedRGBA = []; + Common.Color.blendColors(fgRGBA, bgRGBA, blendedRGBA); + var fgLuminance = Common.Color.luminance(blendedRGBA); + this._contrastValueBubble.classList.toggle('light', fgLuminance > 0.5); + var fgIsLighter = fgLuminance > bgLuminance; + var desiredLuminance = Common.Color.desiredLuminance(bgLuminance, requiredContrast, fgIsLighter); + + var lastV = hsva[V]; + var currentSlope = 0; + var candidateHSVA = [hsva[H], 0, 0, hsva[A]]; + var pathBuilder = []; + var candidateRGBA = []; + Common.Color.hsva2rgba(candidateHSVA, candidateRGBA); + Common.Color.blendColors(candidateRGBA, bgRGBA, blendedRGBA); + + /** + * Approach the desired contrast ratio by modifying the given component + * from the given starting value. + * @param {number} index + * @param {number} x + * @param {boolean} onAxis + * @return {?number} + */ + function approach(index, x, onAxis) { + while (0 <= x && x <= 1) { + candidateHSVA[index] = x; + Common.Color.hsva2rgba(candidateHSVA, candidateRGBA); + Common.Color.blendColors(candidateRGBA, bgRGBA, blendedRGBA); + var fgLuminance = Common.Color.luminance(blendedRGBA); + var dLuminance = fgLuminance - desiredLuminance; + + if (Math.abs(dLuminance) < (onAxis ? epsilon / 10 : epsilon)) + return x; + else + x += (index === V ? -dLuminance : dLuminance); + } + return null; + } + + for (var s = 0; s < 1 + dS; s += dS) { + s = Math.min(1, s); + candidateHSVA[S] = s; + + var v = lastV; + v = lastV + currentSlope * dS; + + v = approach(V, v, s === 0); + if (v === null) + break; + + currentSlope = (v - lastV) / dS; + + pathBuilder.push(pathBuilder.length ? 'L' : 'M'); + pathBuilder.push(s * width); + pathBuilder.push((1 - v) * height); + } + + if (s < 1 + dS) { + s -= dS; + candidateHSVA[V] = 1; + s = approach(S, s, true); + if (s !== null) + pathBuilder = pathBuilder.concat(['L', s * width, -1]); + } + + this._contrastRatioLine.setAttribute('d', pathBuilder.join(' ')); + } +}; + +ColorPicker.ContrastDetails = class { + /** + * @param {!ColorPicker.ContrastInfo} contrastInfo + * @param {!Element} contentElement + * @param {function(boolean=, !Common.Event=)} toggleMainColorPickerCallback + * @param {function()} backgroundColorPickedCallback + */ + constructor(contrastInfo, contentElement, toggleMainColorPickerCallback, backgroundColorPickedCallback) { + /** @type {!ColorPicker.ContrastInfo} */ + this._contrastInfo = contrastInfo; + + /** @type {function(boolean=, !Common.Event=)} */ + this._toggleMainColorPicker = toggleMainColorPickerCallback; + + /** @type {function()} */ + this._backgroundColorPickedCallback = backgroundColorPickedCallback; + + this._contrastDetails = contentElement.createChild('div', 'spectrum-contrast-details'); + var contrastValueRow = this._contrastDetails.createChild('div'); + contrastValueRow.createTextChild(Common.UIString('Contrast Ratio')); + + var contrastLink = contrastValueRow.appendChild(UI.createExternalLink( + 'https://developers.google.com/web/fundamentals/accessibility/accessible-styles#color_and_contrast', + 'Color and contrast on Web Fundamentals', 'contrast-link')); + contrastLink.textContent = ''; + contrastLink.appendChild(UI.Icon.create('mediumicon-info')); + + this._contrastValueBubble = contrastValueRow.createChild('span', 'contrast-details-value force-white-icons'); + this._contrastValue = this._contrastValueBubble.createChild('span'); + this._contrastValueBubbleIcons = []; + this._contrastValueBubbleIcons.push( + this._contrastValueBubble.appendChild(UI.Icon.create('smallicon-checkmark-square'))); + this._contrastValueBubbleIcons.push( + this._contrastValueBubble.appendChild(UI.Icon.create('smallicon-checkmark-behind'))); + this._contrastValueBubbleIcons.push(this._contrastValueBubble.appendChild(UI.Icon.create('smallicon-no'))); + this._contrastValueBubble.addEventListener('mouseenter', this._toggleContrastValueHovered.bind(this)); + this._contrastValueBubble.addEventListener('mouseleave', this._toggleContrastValueHovered.bind(this)); + + var toolbar = new UI.Toolbar('', contrastValueRow); + var closeButton = new UI.ToolbarButton('Hide contrast ratio details', 'largeicon-delete'); + closeButton.addEventListener(UI.ToolbarButton.Events.Click, this.hide.bind(this)); + toolbar.appendToolbarItem(closeButton); + + this._contrastThresholds = this._contrastDetails.createChild('div', 'contrast-thresholds'); + this._contrastAA = this._contrastThresholds.createChild('div', 'contrast-threshold'); + this._contrastAA.appendChild(UI.Icon.create('smallicon-checkmark-square')); + this._contrastAA.appendChild(UI.Icon.create('smallicon-no')); + this._contrastPassFailAA = this._contrastAA.createChild('span', 'contrast-pass-fail'); + + this._contrastAAA = this._contrastThresholds.createChild('div', 'contrast-threshold'); + this._contrastAAA.appendChild(UI.Icon.create('smallicon-checkmark-square')); + this._contrastAAA.appendChild(UI.Icon.create('smallicon-no')); + this._contrastPassFailAAA = this._contrastAAA.createChild('span', 'contrast-pass-fail'); + + var bgColorRow = this._contrastDetails.createChild('div'); + bgColorRow.createTextChild(Common.UIString('Background color:')); + this._bgColorSwatch = new ColorPicker.Spectrum.Swatch(bgColorRow, 'contrast'); + + this._bgColorPicker = bgColorRow.createChild('button', 'background-color-picker'); + this._bgColorPicker.appendChild(UI.Icon.create('largeicon-eyedropper')); + this._bgColorPicker.addEventListener('click', this._toggleBackgroundColorPicker.bind(this, undefined)); + this._bgColorPickedBound = this._bgColorPicked.bind(this); + } + + update() { + var contrastRatio = this._contrastInfo.contrastRatio(); + var bgColor = this._contrastInfo.bgColor(); + if (!contrastRatio || !bgColor) + return; + + this._contrastValue.textContent = contrastRatio.toFixed(2); + this._bgColorSwatch.setColor(bgColor); + + var AA = this._contrastInfo.contrastRatioThreshold('AA'); + var AAA = this._contrastInfo.contrastRatioThreshold('AAA'); + + var passesAA = this._contrastInfo.contrastRatio() >= AA; + this._contrastPassFailAA.textContent = ''; + this._contrastPassFailAA.createTextChild(passesAA ? Common.UIString('Passes ') : Common.UIString('Fails ')); + this._contrastPassFailAA.createChild('strong').textContent = Common.UIString('AA (%s)', AA.toFixed(1)); + this._contrastAA.classList.toggle('pass', passesAA); + this._contrastAA.classList.toggle('fail', !passesAA); + + var passesAAA = this._contrastInfo.contrastRatio() >= AAA; + this._contrastPassFailAAA.textContent = ''; + this._contrastPassFailAAA.createTextChild(passesAAA ? Common.UIString('Passes ') : Common.UIString('Fails ')); + this._contrastPassFailAAA.createChild('strong').textContent = Common.UIString('AAA (%s)', AAA.toFixed(1)); + this._contrastAAA.classList.toggle('pass', passesAAA); + this._contrastAAA.classList.toggle('fail', !passesAAA); + + this._contrastValueBubble.classList.toggle('contrast-fail', !passesAA); + this._contrastValueBubble.classList.toggle('contrast-aa', passesAA); + this._contrastValueBubble.classList.toggle('contrast-aaa', passesAAA); + this._contrastValueBubble.style.color = this._contrastInfo.colorString(); + for (var i = 0; i < this._contrastValueBubbleIcons.length; i++) + this._contrastValueBubbleIcons[i].style.setProperty('background', this._contrastInfo.colorString(), 'important'); + + var isWhite = (this._contrastInfo.bgColor().hsla()[2] > 0.9); + this._contrastValueBubble.style.background = + /** @type {string} */ (this._contrastInfo.bgColor().asString(Common.Color.Format.RGBA)); + this._contrastValueBubble.classList.toggle('contrast-color-white', isWhite); + + if (isWhite) { + this._contrastValueBubble.style.removeProperty('border-color'); + } else { + this._contrastValueBubble.style.borderColor = + /** @type {string} */ (this._contrastInfo.bgColor().asString(Common.Color.Format.RGBA)); + } + } + + toggleVisible() { + this._contrastDetails.classList.toggle('visible'); + if (this._contrastDetails.classList.contains('visible')) + this._toggleMainColorPicker(false); + else + this._toggleBackgroundColorPicker(false); + } + + hide() { + this._contrastDetails.classList.remove('visible'); + this._toggleMainColorPicker(false); + } + + /** + * @param {boolean=} enabled + */ + _toggleBackgroundColorPicker(enabled) { + if (enabled === undefined) { + this._bgColorPicker.classList.toggle('active'); + enabled = this._bgColorPicker.classList.contains('active'); + } else { + this._bgColorPicker.classList.toggle('active', enabled); + } + UI.ARIAUtils.setPressed(this._bgColorPicker, enabled); + + InspectorFrontendHost.setEyeDropperActive(enabled); + if (enabled) { + InspectorFrontendHost.events.addEventListener( + InspectorFrontendHostAPI.Events.EyeDropperPickedColor, this._bgColorPickedBound); + } else { + InspectorFrontendHost.events.removeEventListener( + InspectorFrontendHostAPI.Events.EyeDropperPickedColor, this._bgColorPickedBound); + } + } + + /** + * @param {!Common.Event} event + */ + _bgColorPicked(event) { + var rgbColor = /** @type {!{r: number, g: number, b: number, a: number}} */ (event.data); + var rgba = [rgbColor.r, rgbColor.g, rgbColor.b, (rgbColor.a / 2.55 | 0) / 100]; + var color = Common.Color.fromRGBA(rgba); + this._contrastInfo.setBgColor(color); + this.update(); + this._backgroundColorPickedCallback(); + InspectorFrontendHost.bringToFront(); + } + + /** + * @param {!Event} event + */ + _toggleContrastValueHovered(event) { + if (!this._contrastValueBubble.classList.contains('contrast-fail')) + return; + + if (event.type === 'mouseenter') { + this._contrastValueBubble.classList.add('hover'); + for (var i = 0; i < this._contrastValueBubbleIcons.length; i++) + this._contrastValueBubbleIcons[i].style.setProperty('background', '#333', 'important'); + } else { + this._contrastValueBubble.classList.remove('hover'); + for (var i = 0; i < this._contrastValueBubbleIcons.length; i++) { + this._contrastValueBubbleIcons[i].style.setProperty( + 'background', this._contrastInfo.colorString(), 'important'); + } + } + } +};
diff --git a/third_party/WebKit/Source/devtools/front_end/color_picker/Spectrum.js b/third_party/WebKit/Source/devtools/front_end/color_picker/Spectrum.js index 8bc5ae7..78493e7 100644 --- a/third_party/WebKit/Source/devtools/front_end/color_picker/Spectrum.js +++ b/third_party/WebKit/Source/devtools/front_end/color_picker/Spectrum.js
@@ -53,8 +53,11 @@ .createChild('div', 'spectrum-val fill') .createChild('div', 'spectrum-dragger'); - if (Runtime.experiments.isEnabled('colorContrastRatio')) - this._setUpContrastRatioUI(); + if (Runtime.experiments.isEnabled('colorContrastRatio')) { + var boundToggleColorPicker = this._toggleColorPicker.bind(this); + this._contrastOverlay = + new ColorPicker.ContrastOverlay(this._colorElement, this.contentElement, boundToggleColorPicker); + } var toolbar = new UI.Toolbar('spectrum-eye-dropper', this.contentElement); this._colorPickerButton = new UI.ToolbarToggle(Common.UIString('Toggle color picker'), 'largeicon-eyedropper'); @@ -63,14 +66,7 @@ UI.ToolbarButton.Events.Click, this._toggleColorPicker.bind(this, undefined)); toolbar.appendToolbarItem(this._colorPickerButton); - var swatchElement = this.contentElement.createChild('span', 'swatch'); - this._swatchInnerElement = swatchElement.createChild('span', 'swatch-inner'); - this._swatchOverlayElement = swatchElement.createChild('span', 'swatch-overlay'); - this._swatchOverlayElement.addEventListener('click', this._onCopyIconClick.bind(this)); - this._swatchOverlayElement.addEventListener('mouseout', this._onCopyIconMouseout.bind(this)); - this._swatchCopyIcon = UI.Icon.create('largeicon-copy', 'copy-color-icon'); - this._swatchCopyIcon.title = Common.UIString('Copy color to clipboard'); - this._swatchOverlayElement.appendChild(this._swatchCopyIcon); + this._swatch = new ColorPicker.Spectrum.Swatch(this.contentElement); this._hueElement = this.contentElement.createChild('div', 'spectrum-hue'); this._hueSlider = this._hueElement.createChild('div', 'spectrum-slider'); @@ -191,34 +187,11 @@ hsva[1] = Number.constrain((event.x - this._colorOffset.left) / this.dragWidth, 0, 1); hsva[2] = Number.constrain(1 - (event.y - this._colorOffset.top) / this.dragHeight, 0, 1); - if (Runtime.experiments.isEnabled('colorContrastRatio')) - positionContrastInfo(this._contrastInfo, event); + if (this._contrastOverlay) + this._contrastOverlay.moveAwayFrom(event.x, event.y); this._innerSetColor(hsva, '', undefined, ColorPicker.Spectrum._ChangeSource.Other); } - - /** - * @param {!Element} info - * @param {!Event} event - */ - function positionContrastInfo(info, event) { - if (!info.boxInWindow().contains(event.x, event.y)) - return; - - if (info.offsetWidth > ((info.offsetParent.offsetWidth / 2) - 10)) - info.classList.toggle('contrast-info-top'); - else - info.classList.toggle('contrast-info-left'); - } - } - - _onCopyIconClick() { - this._swatchCopyIcon.setIconType('largeicon-checkmark'); - InspectorFrontendHost.copyText(this.colorString()); - } - - _onCopyIconMouseout() { - this._swatchCopyIcon.setIconType('largeicon-copy'); } _updatePalettePanel() { @@ -591,6 +564,14 @@ } /** + * @param {?SDK.CSSModel.ContrastInfo} contrastInfo + */ + setContrastInfo(contrastInfo) { + if (this._contrastOverlay) + this._contrastOverlay.setContrastInfo(contrastInfo); + } + + /** * @param {!Array<number>|undefined} hsva * @param {string|undefined} colorString * @param {string|undefined} colorFormat @@ -615,6 +596,9 @@ this._colorFormat = colorFormat; } + if (hsva && this._contrastOverlay) + this._contrastOverlay.setColor(hsva, this.colorString()); + this._updateHelperLocations(); this._updateUI(); @@ -625,14 +609,6 @@ } /** - * @param {!Common.Color} color - */ - setContrastColor(color) { - this._contrastColor = color; - this._updateUI(); - } - - /** * @return {!Common.Color} */ _color() { @@ -718,154 +694,17 @@ } } - /** - * @param {number} requiredContrast - * @param {!Array<number>} bgRGBA - * @param {!Array<number>} fgRGBA - */ - _drawContrastRatioLine(requiredContrast, bgRGBA, fgRGBA) { - if (!this._contrastColor || !this.dragWidth || !this.dragHeight) - return; - - /** const */ var width = this.dragWidth; - /** const */ var height = this.dragHeight; - /** const */ var dS = 0.02; - /** const */ var epsilon = 0.002; - /** const */ var H = 0; - /** const */ var S = 1; - /** const */ var V = 2; - /** const */ var A = 3; - - var bgLuminance = Common.Color.luminance(bgRGBA); - var blendedRGBA = []; - Common.Color.blendColors(fgRGBA, bgRGBA, blendedRGBA); - var fgLuminance = Common.Color.luminance(blendedRGBA); - var fgIsLighter = fgLuminance > bgLuminance; - var desiredLuminance = Common.Color.desiredLuminance(bgLuminance, requiredContrast, fgIsLighter); - - var lastV = this._hsv[V]; - var currentSlope = 0; - var candidateHSVA = [this._hsv[H], 0, 0, this._hsv[A]]; - var pathBuilder = []; - var candidateRGBA = []; - Common.Color.hsva2rgba(candidateHSVA, candidateRGBA); - Common.Color.blendColors(candidateRGBA, bgRGBA, blendedRGBA); - - /** - * Approach the desired contrast ratio by modifying the given component - * from the given starting value. - * @param {number} index - * @param {number} x - * @param {boolean} onAxis - * @return {?number} - */ - function approach(index, x, onAxis) { - while (0 <= x && x <= 1) { - candidateHSVA[index] = x; - Common.Color.hsva2rgba(candidateHSVA, candidateRGBA); - Common.Color.blendColors(candidateRGBA, bgRGBA, blendedRGBA); - var fgLuminance = Common.Color.luminance(blendedRGBA); - var dLuminance = fgLuminance - desiredLuminance; - - if (Math.abs(dLuminance) < (onAxis ? epsilon / 10 : epsilon)) - return x; - else - x += (index === V ? -dLuminance : dLuminance); - } - return null; - } - - for (var s = 0; s < 1 + dS; s += dS) { - s = Math.min(1, s); - candidateHSVA[S] = s; - - var v = lastV; - v = lastV + currentSlope * dS; - - v = approach(V, v, s === 0); - if (v === null) - break; - - currentSlope = (v - lastV) / dS; - - pathBuilder.push(pathBuilder.length ? 'L' : 'M'); - pathBuilder.push(s * width); - pathBuilder.push((1 - v) * height); - } - - if (s < 1 + dS) { - s -= dS; - candidateHSVA[V] = 1; - s = approach(S, s, true); - if (s !== null) - pathBuilder = pathBuilder.concat(['L', s * width, -1]); - } - - this._contrastRatioLine.setAttribute('d', pathBuilder.join(' ')); - } - - _setUpContrastRatioUI() { - var contrastRatioSVG = this._colorElement.createSVGChild('svg', 'spectrum-contrast-container fill'); - this._contrastRatioLine = contrastRatioSVG.createSVGChild('path', 'spectrum-contrast-line'); - this._contrastInfo = this._colorElement.createChild('div', 'spectrum-contrast-info'); - this._contrastInfo.classList.add('force-white-icons'); - this._contrastInfo.createChild('span', 'low-contrast').textContent = Common.UIString('Low contrast'); - this._contrastInfo.createChild('span', 'value'); - this._contrastInfo.appendChild(UI.Icon.create('smallicon-contrast-ratio')); - } - - - /** - * @param {boolean} show - */ - _setContrastInfoVisible(show) { - var info = this._contrastInfo; - if (!show) { - info.classList.add('hidden'); - return; - } - - info.classList.remove('hidden'); - - var fgRGBA = []; - Common.Color.hsva2rgba(this._hsv, fgRGBA); - var bgRGBA = this._contrastColor.rgba(); - var contrastRatio = Common.Color.calculateContrastRatio(fgRGBA, bgRGBA); - - // TODO(aboxhall): Determine size of text and switch between AA/AAA ratings. - var requiredContrast = 4.5; - - this._contrastInfo.querySelector('.value').textContent = contrastRatio.toFixed(2); - this._contrastInfo.classList.toggle('contrast-fail', (contrastRatio < requiredContrast)); - this._drawContrastRatioLine(requiredContrast, bgRGBA, fgRGBA); - - var draggerBox = this._colorDragElement.boxInWindow(); - var dragX = draggerBox.x + (draggerBox.width / 2); - var dragY = draggerBox.y + (draggerBox.height / 2); - var infoBox = info.boxInWindow(); - if (infoBox.contains(dragX, dragY)) { - if (info.offsetWidth > ((info.offsetParent.offsetWidth / 2) - 10)) - info.classList.toggle('contrast-info-top'); - else - info.classList.toggle('contrast-info-left'); - } - } - - _updateUI() { var h = Common.Color.fromHSVA([this._hsv[0], 1, 1, 1]); this._colorElement.style.backgroundColor = /** @type {string} */ (h.asString(Common.Color.Format.RGB)); - if (Runtime.experiments.isEnabled('colorContrastRatio')) { - if (this.dragWidth && this._contrastColor) - this._setContrastInfoVisible(true); + if (this._contrastOverlay) { + if (this.dragWidth) + this._contrastOverlay.show(this.dragWidth, this.dragHeight, this._colorDragElement.boxInWindow()); else - this._setContrastInfoVisible(false); + this._contrastOverlay.hide(); } - this._swatchInnerElement.style.backgroundColor = - /** @type {string} */ (this._color().asString(Common.Color.Format.RGBA)); - // Show border if the swatch is white. - this._swatchInnerElement.classList.toggle('swatch-inner-white', this._color().hsla()[2] > 0.9); + this._swatch.setColor(this._color(), this.colorString()); this._colorDragElement.style.backgroundColor = /** @type {string} */ (this._color().asString(Common.Color.Format.RGBA)); var noAlpha = Common.Color.fromHSVA(this._hsv.slice(0, 3).concat(1)); @@ -1125,3 +964,51 @@ matchUserFormat: true, colors: Object.keys(ColorPicker.Spectrum.MaterialPaletteShades) }; + +ColorPicker.Spectrum.Swatch = class { + /** + * @param {!Element} parentElement + * @param {string=} className + */ + constructor(parentElement, className) { + /** @type {?string} */ + this._colorString; + + var swatchElement = parentElement.createChild('span', 'swatch'); + if (className) + swatchElement.classList.add(className); + this._swatchInnerElement = swatchElement.createChild('span', 'swatch-inner'); + + this._swatchOverlayElement = swatchElement.createChild('span', 'swatch-overlay'); + this._swatchOverlayElement.addEventListener('click', this._onCopyIconClick.bind(this)); + this._swatchOverlayElement.addEventListener('mouseout', this._onCopyIconMouseout.bind(this)); + this._swatchCopyIcon = UI.Icon.create('largeicon-copy', 'copy-color-icon'); + this._swatchCopyIcon.title = Common.UIString('Copy color to clipboard'); + this._swatchOverlayElement.appendChild(this._swatchCopyIcon); + } + + /** + * @param {!Common.Color} color + * @param {string=} colorString + */ + setColor(color, colorString) { + this._swatchInnerElement.style.backgroundColor = + /** @type {string} */ (color.asString(Common.Color.Format.RGBA)); + // Show border if the swatch is white. + this._swatchInnerElement.classList.toggle('swatch-inner-white', color.hsla()[2] > 0.9); + this._colorString = colorString || null; + if (colorString) + this._swatchOverlayElement.hidden = false; + else + this._swatchOverlayElement.hidden = true; + } + + _onCopyIconClick() { + this._swatchCopyIcon.setIconType('largeicon-checkmark'); + InspectorFrontendHost.copyText(this._colorString); + } + + _onCopyIconMouseout() { + this._swatchCopyIcon.setIconType('largeicon-copy'); + } +};
diff --git a/third_party/WebKit/Source/devtools/front_end/color_picker/module.json b/third_party/WebKit/Source/devtools/front_end/color_picker/module.json index b8e7cb6..d5b79a5 100644 --- a/third_party/WebKit/Source/devtools/front_end/color_picker/module.json +++ b/third_party/WebKit/Source/devtools/front_end/color_picker/module.json
@@ -4,6 +4,7 @@ "sdk" ], "scripts": [ + "Contrast.js", "Spectrum.js" ], "resources": [
diff --git a/third_party/WebKit/Source/devtools/front_end/color_picker/spectrum.css b/third_party/WebKit/Source/devtools/front_end/color_picker/spectrum.css index 405c437..90d66c7 100644 --- a/third_party/WebKit/Source/devtools/front_end/color_picker/spectrum.css +++ b/third_party/WebKit/Source/devtools/front_end/color_picker/spectrum.css
@@ -131,6 +131,123 @@ margin-right: 4px; } +.spectrum-contrast-details { + position: absolute; + background-color: white; + width: 100%; + height: 111px; + top: 124px; + z-index: 13; + font-size: 13px; + color: #333; + display: none; + line-height: initial; +} + +.spectrum-contrast-details div.toolbar { + position: absolute; + right: 6px; + top: 6px; + margin: 0; +} + +.spectrum-contrast-details div.toolbar [is=ui-icon] { + position: absolute; + right: 6px; + top: 6px; + margin: 0; + background: transparent; +} + +.spectrum-contrast-details.visible { + display: initial; +} + +.spectrum-contrast-details div { + margin: 12px; +} + +.contrast-pass-fail { + margin-left: 0.5em; +} + +.contrast-threshold .smallicon-checkmark-square, +.contrast-threshold .smallicon-no{ + display: none; +} + +.contrast-threshold.pass .smallicon-checkmark-square { + display: inline-block; + background-color: #00b06f; +} + +.contrast-threshold.fail .smallicon-no { + display: inline-block; + background-color: #b40202; +} + +.contrast-threshold-value { + font-weight: bold; +} +.spectrum-contrast-details .contrast-thresholds div { + margin: 0; +} + +.contrast-link { + margin-left: 0.5em; +} + +.contrast-link .mediumicon-info { + margin-top: -3px; + background-color: #333; +} + +.contrast-details-value { + color: white; + border-radius: 2px; + margin-left: 0.5em; + padding: 1px 3px; + align-items: baseline; +} + +.contrast-details-value.contrast-color-white { + border: 1px solid #ddd; +} + +.contrast-details-value.contrast-fail.hover { + color: #333 !important; + background-color: white !important; +} + +.contrast-details-value.contrast-fail.hover [is=ui-icon] { + background-color: black !important; +} + +.contrast-details-value [is=ui-icon] { + display: none; + margin-left: 0.5em; +} + +.contrast-details-value .smallicon-checkmark-behind { + margin-left: -6px; +} + +.contrast-details-value.contrast-fail .smallicon-no { + display: inline-block; +} + +.contrast-details-value.contrast-fail .smallicon-no { + display: inline-block; +} + +.contrast-details-value.contrast-aa .smallicon-checkmark-square { + display: inline-block; +} + +.contrast-details-value.contrast-aaa .smallicon-checkmark-behind { + display: inline-block; +} + .swatch { width: 32px; height: 32px; @@ -460,3 +577,37 @@ background-color: #ddd; color: white; } + +.swatch.contrast { + width: 20px; + height: 20px; + margin: -10px; + position: relative; + top: -5px; + left: 17px; + background-image: url(Images/checker.png); + border-radius: 10px; + display: inline-block; +} + +.swatch.contrast .swatch-overlay { + padding: 0; +} + +.swatch.contrast [is=ui-icon] { + margin: -2px; +} + +button.background-color-picker { + border: 0; + padding: 0; + background: none; + position: relative; + margin-top: -12px; + left: 26px; + top: 7px; +} + +button.background-color-picker.active [is=ui-icon].largeicon-eyedropper.icon-mask{ + background-color: hsl(218, 81%, 59%); +}
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ColorSwatchPopoverIcon.js b/third_party/WebKit/Source/devtools/front_end/elements/ColorSwatchPopoverIcon.js index 3f8336c..68cd7b24 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/ColorSwatchPopoverIcon.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/ColorSwatchPopoverIcon.js
@@ -102,7 +102,7 @@ var shiftClickMessage = Common.UIString('Shift + Click to change color format.'); this._swatch.iconElement().title = Common.UIString('Open color picker. %s', shiftClickMessage); this._swatch.iconElement().addEventListener('click', this._iconClick.bind(this)); - this._contrastColor = null; + this._contrastInfo = null; this._boundSpectrumChanged = this._spectrumChanged.bind(this); this._boundOnScroll = this._onScroll.bind(this); @@ -117,12 +117,12 @@ } /** - * @param {!Common.Color} color + * @param {?SDK.CSSModel.ContrastInfo} contrastInfo */ - setContrastColor(color) { - this._contrastColor = color; + setContrastInfo(contrastInfo) { + this._contrastInfo = contrastInfo; if (this._spectrum) - this._spectrum.setContrastColor(this._contrastColor); + this._spectrum.setContrastInfo(contrastInfo); } /** @@ -145,8 +145,8 @@ format = color.format(); this._spectrum = new ColorPicker.Spectrum(); this._spectrum.setColor(color, format); - if (this._contrastColor) - this._spectrum.setContrastColor(this._contrastColor); + if (this._contrastInfo) + this._spectrum.setContrastInfo(this._contrastInfo); this._spectrum.addEventListener(ColorPicker.Spectrum.Events.SizeChanged, this._spectrumResized, this); this._spectrum.addEventListener(ColorPicker.Spectrum.Events.ColorChanged, this._boundSpectrumChanged);
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js index 7a0491a..70f2bf7 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
@@ -2016,29 +2016,10 @@ var swatchIcon = new Elements.ColorSwatchPopoverIcon(this, swatchPopoverHelper, swatch); /** - * @param {?Array<string>} backgroundColors + * @param {?SDK.CSSModel.ContrastInfo} contrastInfo */ - function computedCallback(backgroundColors) { - // TODO(aboxhall): distinguish between !backgroundColors (no text) and - // !backgroundColors.length (no computed bg color) - if (!backgroundColors || !backgroundColors.length) - return; - // TODO(samli): figure out what to do in the case of multiple background colors (i.e. gradients) - var bgColorText = backgroundColors[0]; - var bgColor = Common.Color.parse(bgColorText); - if (!bgColor) - return; - - // If we have a semi-transparent background color over an unknown - // background, draw the line for the "worst case" scenario: where - // the unknown background is the same color as the text. - if (bgColor.hasAlpha) { - var blendedRGBA = []; - Common.Color.blendColors(bgColor.rgba(), color.rgba(), blendedRGBA); - bgColor = new Common.Color(blendedRGBA, Common.Color.Format.RGBA); - } - - swatchIcon.setContrastColor(bgColor); + function computedCallback(contrastInfo) { + swatchIcon.setContrastInfo(contrastInfo); } if (Runtime.experiments.isEnabled('colorContrastRatio') && this.property.name === 'color' &&
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js index 8f0d1aa3..30e324f 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js
@@ -362,10 +362,14 @@ /** * @param {number} nodeId - * @return {!Promise<?Array<string>>} + * @return {!Promise<?SDK.CSSModel.ContrastInfo>} */ - backgroundColorsPromise(nodeId) { - return this._agent.getBackgroundColors(nodeId); + async backgroundColorsPromise(nodeId) { + var response = this._agent.invoke_getBackgroundColors({nodeId}); + if (response[Protocol.Error]) + return null; + + return response; } /** @@ -748,6 +752,9 @@ /** @typedef {!{range: !Protocol.CSS.SourceRange, styleSheetId: !Protocol.CSS.StyleSheetId, wasUsed: boolean}} */ SDK.CSSModel.RuleUsage; +/** @typedef {{backgroundColors: ?Array<string>, computedFontSize: string, computedFontWeights: string, computedBodyFontSize: string}} */ +SDK.CSSModel.ContrastInfo; + /** @enum {symbol} */ SDK.CSSModel.Events = { FontsUpdated: Symbol('FontsUpdated'),
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Icon.js b/third_party/WebKit/Source/devtools/front_end/ui/Icon.js index f2be3d00..134be36 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/Icon.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/Icon.js
@@ -119,6 +119,8 @@ UI.Icon.Descriptors = { 'smallicon-bezier': {position: 'a5', spritesheet: 'smallicons', isMask: true}, 'smallicon-checkmark': {position: 'b5', spritesheet: 'smallicons'}, + 'smallicon-checkmark-square': {position: 'b6', spritesheet: 'smallicons', isMask: true}, + 'smallicon-checkmark-behind': {position: 'd6', spritesheet: 'smallicons', isMask: true}, 'smallicon-command-result': {position: 'a4', spritesheet: 'smallicons'}, 'smallicon-contrast-ratio': {position: 'a6', spritesheet: 'smallicons', isMask: true}, 'smallicon-cross': {position: 'b4', spritesheet: 'smallicons'}, @@ -129,6 +131,7 @@ 'smallicon-info': {position: 'c3', spritesheet: 'smallicons'}, 'smallicon-inline-breakpoint-conditional': {position: 'd5', spritesheet: 'smallicons'}, 'smallicon-inline-breakpoint': {position: 'd4', spritesheet: 'smallicons'}, + 'smallicon-no': {position: 'c6', spritesheet: 'smallicons', isMask: true}, 'smallicon-orange-ball': {position: 'd3', spritesheet: 'smallicons'}, 'smallicon-red-ball': {position: 'a2', spritesheet: 'smallicons'}, 'smallicon-shadow': {position: 'b2', spritesheet: 'smallicons', isMask: true}, @@ -147,6 +150,7 @@ 'mediumicon-clear-storage': {position: 'a4', spritesheet: 'mediumicons', isMask: true}, 'mediumicon-cookie': {position: 'b4', spritesheet: 'mediumicons', isMask: true}, 'mediumicon-database': {position: 'c4', spritesheet: 'mediumicons', isMask: true}, + 'mediumicon-info': {position: 'c1', spritesheet: 'mediumicons', isMask: true}, 'mediumicon-manifest': {position: 'd4', spritesheet: 'mediumicons', isMask: true}, 'mediumicon-service-worker': {position: 'a3', spritesheet: 'mediumicons', isMask: true}, 'mediumicon-table': {position: 'b3', spritesheet: 'mediumicons', isMask: true},
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp index 95db08f..804a336 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
@@ -354,6 +354,7 @@ cached_has_inherited_presentational_role_(false), cached_is_presentational_child_(false), cached_ancestor_exposes_active_descendant_(false), + cached_is_editable_root_(false), cached_live_region_root_(nullptr), ax_object_cache_(&ax_object_cache) { ++number_of_live_ax_objects_; @@ -682,11 +683,14 @@ cached_is_presentational_child_ = (AncestorForWhichThisIsAPresentationalChild() != 0); cached_is_ignored_ = ComputeAccessibilityIsIgnored(); + cached_is_editable_root_ = + GetNode() ? IsNativeTextControl() || IsRootEditableElement(*GetNode()) + : false; cached_live_region_root_ = IsLiveRegion() ? const_cast<AXObject*>(this) : (ParentObjectIfExists() ? ParentObjectIfExists()->LiveRegionRoot() - : 0); + : nullptr); cached_ancestor_exposes_active_descendant_ = ComputeAncestorExposesActiveDescendant(); } @@ -1462,6 +1466,11 @@ return !live_region.IsEmpty() && !EqualIgnoringASCIICase(live_region, "off"); } +bool AXObject::IsEditableRoot() const { + UpdateCachedAttributeValuesIfNeeded(); + return cached_is_editable_root_; +} + AXObject* AXObject::LiveRegionRoot() const { UpdateCachedAttributeValuesIfNeeded(); return cached_live_region_root_;
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.h b/third_party/WebKit/Source/modules/accessibility/AXObject.h index 0ebb7b0d..980c02f 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXObject.h +++ b/third_party/WebKit/Source/modules/accessibility/AXObject.h
@@ -639,6 +639,7 @@ virtual void AriaLabelledbyElements(AXObjectVector&) const {} virtual bool AriaHasPopup() const { return false; } virtual bool IsEditable() const { return false; } + bool IsEditableRoot() const; virtual bool IsMultiline() const { return false; } virtual bool IsRichlyEditable() const { return false; } bool AriaCheckedIsPresent() const; @@ -879,6 +880,7 @@ mutable bool cached_has_inherited_presentational_role_ : 1; mutable bool cached_is_presentational_child_ : 1; mutable bool cached_ancestor_exposes_active_descendant_ : 1; + mutable bool cached_is_editable_root_; mutable Member<AXObject> cached_live_region_root_; Member<AXObjectCacheImpl> ax_object_cache_;
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchBridge.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchBridge.cpp index c89b825..f1789c60 100644 --- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchBridge.cpp +++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchBridge.cpp
@@ -45,39 +45,39 @@ BackgroundFetchBridge::~BackgroundFetchBridge() = default; -void BackgroundFetchBridge::Fetch(const String& tag, +void BackgroundFetchBridge::Fetch(const String& id, Vector<WebServiceWorkerRequest> requests, const BackgroundFetchOptions& options, RegistrationCallback callback) { GetService()->Fetch( GetSupplementable()->WebRegistration()->RegistrationId(), - GetSecurityOrigin(), tag, std::move(requests), + GetSecurityOrigin(), id, std::move(requests), mojom::blink::BackgroundFetchOptions::From(options), ConvertToBaseCallback( WTF::Bind(&BackgroundFetchBridge::DidGetRegistration, WrapPersistent(this), WTF::Passed(std::move(callback))))); } -void BackgroundFetchBridge::Abort(const String& tag, AbortCallback callback) { +void BackgroundFetchBridge::Abort(const String& id, AbortCallback callback) { GetService()->Abort(GetSupplementable()->WebRegistration()->RegistrationId(), - GetSecurityOrigin(), tag, + GetSecurityOrigin(), id, ConvertToBaseCallback(std::move(callback))); } -void BackgroundFetchBridge::UpdateUI(const String& tag, +void BackgroundFetchBridge::UpdateUI(const String& id, const String& title, UpdateUICallback callback) { GetService()->UpdateUI( GetSupplementable()->WebRegistration()->RegistrationId(), - GetSecurityOrigin(), tag, title, + GetSecurityOrigin(), id, title, ConvertToBaseCallback(std::move(callback))); } -void BackgroundFetchBridge::GetRegistration(const String& tag, +void BackgroundFetchBridge::GetRegistration(const String& id, RegistrationCallback callback) { GetService()->GetRegistration( GetSupplementable()->WebRegistration()->RegistrationId(), - GetSecurityOrigin(), tag, + GetSecurityOrigin(), id, ConvertToBaseCallback( WTF::Bind(&BackgroundFetchBridge::DidGetRegistration, WrapPersistent(this), WTF::Passed(std::move(callback))))); @@ -98,10 +98,10 @@ callback(error, registration); } -void BackgroundFetchBridge::GetTags(GetTagsCallback callback) { - GetService()->GetTags( - GetSupplementable()->WebRegistration()->RegistrationId(), - GetSecurityOrigin(), ConvertToBaseCallback(std::move(callback))); +void BackgroundFetchBridge::GetIds(GetIdsCallback callback) { + GetService()->GetIds(GetSupplementable()->WebRegistration()->RegistrationId(), + GetSecurityOrigin(), + ConvertToBaseCallback(std::move(callback))); } SecurityOrigin* BackgroundFetchBridge::GetSecurityOrigin() {
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchBridge.h b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchBridge.h index f0ddace4..3ce3b7f 100644 --- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchBridge.h +++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchBridge.h
@@ -31,7 +31,7 @@ public: using AbortCallback = Function<void(mojom::blink::BackgroundFetchError)>; - using GetTagsCallback = + using GetIdsCallback = Function<void(mojom::blink::BackgroundFetchError, const Vector<String>&)>; using RegistrationCallback = Function<void(mojom::blink::BackgroundFetchError, BackgroundFetchRegistration*)>; @@ -42,32 +42,32 @@ virtual ~BackgroundFetchBridge(); - // Creates a new Background Fetch registration identified by |tag| with the + // Creates a new Background Fetch registration identified by |id| with the // given |options| for the sequence of |requests|. The |callback| will be // invoked when the registration has been created. - void Fetch(const String& tag, + void Fetch(const String& id, Vector<WebServiceWorkerRequest> requests, const BackgroundFetchOptions&, RegistrationCallback); - // Updates the user interface for the Background Fetch identified by |tag| + // Updates the user interface for the Background Fetch identified by |id| // with the updated |title|. Will invoke the |callback| when the interface // has been requested to update. - void UpdateUI(const String& tag, const String& title, UpdateUICallback); + void UpdateUI(const String& id, const String& title, UpdateUICallback); - // Aborts the active Background Fetch for |tag|. Will invoke the |callback| - // when the Background Fetch identified by |tag| has been aborted, or could + // Aborts the active Background Fetch for |id|. Will invoke the |callback| + // when the Background Fetch identified by |id| has been aborted, or could // not be aborted for operational reasons. - void Abort(const String& tag, AbortCallback); + void Abort(const String& id, AbortCallback); - // Gets the Background Fetch registration for the given |tag|. Will invoke the + // Gets the Background Fetch registration for the given |id|. Will invoke the // |callback| with the Background Fetch registration, which may be a nullptr - // if the |tag| does not exist, when the Mojo call has completed. - void GetRegistration(const String& tag, RegistrationCallback); + // if the |id| does not exist, when the Mojo call has completed. + void GetRegistration(const String& id, RegistrationCallback); - // Gets the sequence of tags for active Background Fetch registrations. Will - // invoke the |callback| with the tags when the Mojo call has completed. - void GetTags(GetTagsCallback); + // Gets the sequence of ids for active Background Fetch registrations. Will + // invoke the |callback| with the ids when the Mojo call has completed. + void GetIds(GetIdsCallback); private: explicit BackgroundFetchBridge(ServiceWorkerRegistration&);
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchEvent.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchEvent.cpp index 137a691..9d40bd5 100644 --- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchEvent.cpp +++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchEvent.cpp
@@ -12,12 +12,12 @@ BackgroundFetchEvent::BackgroundFetchEvent(const AtomicString& type, const BackgroundFetchEventInit& init, WaitUntilObserver* observer) - : ExtendableEvent(type, init, observer), tag_(init.tag()) {} + : ExtendableEvent(type, init, observer), id_(init.id()) {} BackgroundFetchEvent::~BackgroundFetchEvent() = default; -String BackgroundFetchEvent::tag() const { - return tag_; +String BackgroundFetchEvent::id() const { + return id_; } const AtomicString& BackgroundFetchEvent::InterfaceName() const {
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchEvent.h b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchEvent.h index 8d7cf2bf..3770cbe 100644 --- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchEvent.h +++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchEvent.h
@@ -35,7 +35,7 @@ ~BackgroundFetchEvent() override; // Web Exposed attribute defined in the IDL file. - String tag() const; + String id() const; // ExtendableEvent interface. const AtomicString& InterfaceName() const override; @@ -45,7 +45,7 @@ const BackgroundFetchEventInit&, WaitUntilObserver*); - String tag_; + String id_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchEvent.idl b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchEvent.idl index 3265f3e..632db60 100644 --- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchEvent.idl +++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchEvent.idl
@@ -9,5 +9,5 @@ Exposed=ServiceWorker, RuntimeEnabled=BackgroundFetch ] interface BackgroundFetchEvent : ExtendableEvent { - readonly attribute DOMString tag; + readonly attribute DOMString id; };
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchEventInit.idl b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchEventInit.idl index 64bb8c4..24194f4 100644 --- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchEventInit.idl +++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchEventInit.idl
@@ -5,5 +5,5 @@ // https://wicg.github.io/background-fetch/#background-fetch-event dictionary BackgroundFetchEventInit : ExtendableEventInit { - required DOMString tag; + required DOMString id; };
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.cpp index e564e294..bcb5622 100644 --- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.cpp +++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.cpp
@@ -40,7 +40,7 @@ ScriptPromise BackgroundFetchManager::fetch( ScriptState* script_state, - const String& tag, + const String& id, const RequestOrUSVStringOrRequestOrUSVStringSequence& requests, const BackgroundFetchOptions& options, ExceptionState& exception_state) { @@ -60,7 +60,7 @@ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromise promise = resolver->Promise(); - bridge_->Fetch(tag, std::move(web_requests), options, + bridge_->Fetch(id, std::move(web_requests), options, WTF::Bind(&BackgroundFetchManager::DidFetch, WrapPersistent(this), WrapPersistent(resolver))); @@ -76,14 +76,14 @@ DCHECK(registration); resolver->Resolve(registration); return; - case mojom::blink::BackgroundFetchError::DUPLICATED_TAG: + case mojom::blink::BackgroundFetchError::DUPLICATED_ID: DCHECK(!registration); resolver->Reject(DOMException::Create( kInvalidStateError, - "There already is a registration for the given tag.")); + "There already is a registration for the given id.")); return; case mojom::blink::BackgroundFetchError::INVALID_ARGUMENT: - case mojom::blink::BackgroundFetchError::INVALID_TAG: + case mojom::blink::BackgroundFetchError::INVALID_ID: // Not applicable for this callback. break; } @@ -92,7 +92,7 @@ } ScriptPromise BackgroundFetchManager::get(ScriptState* script_state, - const String& tag) { + const String& id) { if (!registration_->active()) { return ScriptPromise::Reject( script_state, @@ -105,8 +105,8 @@ ScriptPromise promise = resolver->Promise(); bridge_->GetRegistration( - tag, WTF::Bind(&BackgroundFetchManager::DidGetRegistration, - WrapPersistent(this), WrapPersistent(resolver))); + id, WTF::Bind(&BackgroundFetchManager::DidGetRegistration, + WrapPersistent(this), WrapPersistent(resolver))); return promise; } @@ -176,10 +176,10 @@ BackgroundFetchRegistration* registration) { switch (error) { case mojom::blink::BackgroundFetchError::NONE: - case mojom::blink::BackgroundFetchError::INVALID_TAG: + case mojom::blink::BackgroundFetchError::INVALID_ID: resolver->Resolve(registration); return; - case mojom::blink::BackgroundFetchError::DUPLICATED_TAG: + case mojom::blink::BackgroundFetchError::DUPLICATED_ID: case mojom::blink::BackgroundFetchError::INVALID_ARGUMENT: // Not applicable for this callback. break; @@ -188,7 +188,7 @@ NOTREACHED(); } -ScriptPromise BackgroundFetchManager::getTags(ScriptState* script_state) { +ScriptPromise BackgroundFetchManager::getIds(ScriptState* script_state) { if (!registration_->active()) { return ScriptPromise::Reject( script_state, @@ -200,23 +200,22 @@ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromise promise = resolver->Promise(); - bridge_->GetTags(WTF::Bind(&BackgroundFetchManager::DidGetTags, - WrapPersistent(this), WrapPersistent(resolver))); + bridge_->GetIds(WTF::Bind(&BackgroundFetchManager::DidGetIds, + WrapPersistent(this), WrapPersistent(resolver))); return promise; } -void BackgroundFetchManager::DidGetTags( - ScriptPromiseResolver* resolver, - mojom::blink::BackgroundFetchError error, - const Vector<String>& tags) { +void BackgroundFetchManager::DidGetIds(ScriptPromiseResolver* resolver, + mojom::blink::BackgroundFetchError error, + const Vector<String>& ids) { switch (error) { case mojom::blink::BackgroundFetchError::NONE: - resolver->Resolve(tags); + resolver->Resolve(ids); return; - case mojom::blink::BackgroundFetchError::DUPLICATED_TAG: + case mojom::blink::BackgroundFetchError::DUPLICATED_ID: case mojom::blink::BackgroundFetchError::INVALID_ARGUMENT: - case mojom::blink::BackgroundFetchError::INVALID_TAG: + case mojom::blink::BackgroundFetchError::INVALID_ID: // Not applicable for this callback. break; }
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.h b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.h index cbfbdd3..7442c94 100644 --- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.h +++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.h
@@ -40,12 +40,12 @@ // Web Exposed methods defined in the IDL file. ScriptPromise fetch( ScriptState*, - const String& tag, + const String& id, const RequestOrUSVStringOrRequestOrUSVStringSequence& requests, const BackgroundFetchOptions&, ExceptionState&); - ScriptPromise get(ScriptState*, const String& tag); - ScriptPromise getTags(ScriptState*); + ScriptPromise get(ScriptState*, const String& id); + ScriptPromise getIds(ScriptState*); DECLARE_TRACE(); @@ -67,9 +67,9 @@ void DidGetRegistration(ScriptPromiseResolver*, mojom::blink::BackgroundFetchError, BackgroundFetchRegistration*); - void DidGetTags(ScriptPromiseResolver*, - mojom::blink::BackgroundFetchError, - const Vector<String>& tags); + void DidGetIds(ScriptPromiseResolver*, + mojom::blink::BackgroundFetchError, + const Vector<String>& ids); Member<ServiceWorkerRegistration> registration_; Member<BackgroundFetchBridge> bridge_;
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.idl b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.idl index 855ab3b..12e59cc 100644 --- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.idl +++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.idl
@@ -8,7 +8,7 @@ Exposed=(Window,Worker), RuntimeEnabled=BackgroundFetch ] interface BackgroundFetchManager { - [CallWith=ScriptState, RaisesException] Promise<BackgroundFetchRegistration> fetch(DOMString tag, (RequestInfo or sequence<RequestInfo>) requests, optional BackgroundFetchOptions options); - [CallWith=ScriptState] Promise<BackgroundFetchRegistration?> get(DOMString tag); - [CallWith=ScriptState] Promise<FrozenArray<DOMString>> getTags(); + [CallWith=ScriptState, RaisesException] Promise<BackgroundFetchRegistration> fetch(DOMString id, (RequestInfo or sequence<RequestInfo>) requests, optional BackgroundFetchOptions options); + [CallWith=ScriptState] Promise<BackgroundFetchRegistration?> get(DOMString id); + [CallWith=ScriptState] Promise<FrozenArray<DOMString>> getIds(); };
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchRegistration.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchRegistration.cpp index 10cc558..45be653 100644 --- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchRegistration.cpp +++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchRegistration.cpp
@@ -12,11 +12,11 @@ namespace blink { BackgroundFetchRegistration::BackgroundFetchRegistration( - String tag, + String id, HeapVector<IconDefinition> icons, long long total_download_size, String title) - : tag_(tag), + : id_(id), icons_(icons), total_download_size_(total_download_size), title_(title) {} @@ -29,8 +29,8 @@ registration_ = registration; } -String BackgroundFetchRegistration::tag() const { - return tag_; +String BackgroundFetchRegistration::id() const { + return id_; } HeapVector<IconDefinition> BackgroundFetchRegistration::icons() const { @@ -51,8 +51,8 @@ DCHECK(registration_); BackgroundFetchBridge::From(registration_) - ->Abort(tag_, WTF::Bind(&BackgroundFetchRegistration::DidAbort, - WrapPersistent(this), WrapPersistent(resolver))); + ->Abort(id_, WTF::Bind(&BackgroundFetchRegistration::DidAbort, + WrapPersistent(this), WrapPersistent(resolver))); return promise; } @@ -64,10 +64,10 @@ case mojom::blink::BackgroundFetchError::NONE: resolver->Resolve(true /* success */); return; - case mojom::blink::BackgroundFetchError::INVALID_TAG: + case mojom::blink::BackgroundFetchError::INVALID_ID: resolver->Resolve(false /* success */); return; - case mojom::blink::BackgroundFetchError::DUPLICATED_TAG: + case mojom::blink::BackgroundFetchError::DUPLICATED_ID: case mojom::blink::BackgroundFetchError::INVALID_ARGUMENT: // Not applicable for this callback. break;
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchRegistration.h b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchRegistration.h index 5b211ba..76d249a 100644 --- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchRegistration.h +++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchRegistration.h
@@ -27,7 +27,7 @@ DEFINE_WRAPPERTYPEINFO(); public: - BackgroundFetchRegistration(String tag, + BackgroundFetchRegistration(String id, HeapVector<IconDefinition> icons, long long total_download_size, String title); @@ -37,7 +37,7 @@ // has been associated with. void SetServiceWorkerRegistration(ServiceWorkerRegistration*); - String tag() const; + String id() const; HeapVector<IconDefinition> icons() const; long long totalDownloadSize() const; String title() const; @@ -51,7 +51,7 @@ Member<ServiceWorkerRegistration> registration_; - String tag_; + String id_; HeapVector<IconDefinition> icons_; long long total_download_size_; String title_;
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchRegistration.idl b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchRegistration.idl index 8608634c..3b7ef66 100644 --- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchRegistration.idl +++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchRegistration.idl
@@ -8,7 +8,7 @@ Exposed=(Window,Worker), RuntimeEnabled=BackgroundFetch ] interface BackgroundFetchRegistration { - readonly attribute DOMString tag; + readonly attribute DOMString id; readonly attribute FrozenArray<IconDefinition> icons; readonly attribute long totalDownloadSize; readonly attribute DOMString title;
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchTypeConverters.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchTypeConverters.cpp index 1563c3a..1781622f 100644 --- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchTypeConverters.cpp +++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchTypeConverters.cpp
@@ -25,7 +25,7 @@ icons.push_back(iconPtr.To<blink::IconDefinition>()); return new blink::BackgroundFetchRegistration( - mojoRegistration->tag, std::move(icons), + mojoRegistration->id, std::move(icons), mojoRegistration->total_download_size, mojoRegistration->title); }
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchedEvent.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchedEvent.cpp index 8fa3571d..bd48c2b9 100644 --- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchedEvent.cpp +++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchedEvent.cpp
@@ -61,7 +61,7 @@ ScriptPromise promise = resolver->Promise(); BackgroundFetchBridge::From(registration_) - ->UpdateUI(tag(), title, + ->UpdateUI(id(), title, WTF::Bind(&BackgroundFetchedEvent::DidUpdateUI, WrapPersistent(this), WrapPersistent(resolver))); @@ -73,10 +73,10 @@ mojom::blink::BackgroundFetchError error) { switch (error) { case mojom::blink::BackgroundFetchError::NONE: - case mojom::blink::BackgroundFetchError::INVALID_TAG: + case mojom::blink::BackgroundFetchError::INVALID_ID: resolver->Resolve(); return; - case mojom::blink::BackgroundFetchError::DUPLICATED_TAG: + case mojom::blink::BackgroundFetchError::DUPLICATED_ID: case mojom::blink::BackgroundFetchError::INVALID_ARGUMENT: // Not applicable for this callback. break;
diff --git a/third_party/WebKit/Source/modules/exported/WebAXObject.cpp b/third_party/WebKit/Source/modules/exported/WebAXObject.cpp index 22fee68..89ef94e 100644 --- a/third_party/WebKit/Source/modules/exported/WebAXObject.cpp +++ b/third_party/WebKit/Source/modules/exported/WebAXObject.cpp
@@ -36,7 +36,7 @@ #include "core/dom/Document.h" #include "core/dom/Node.h" #include "core/editing/markers/DocumentMarker.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalFrameView.h" #include "core/frame/VisualViewport.h" #include "core/frame/WebLocalFrameImpl.h" @@ -465,6 +465,13 @@ return private_->AriaHasPopup(); } +bool WebAXObject::IsEditableRoot() const { + if (IsDetached()) + return false; + + return private_->IsEditableRoot(); +} + bool WebAXObject::IsEditable() const { if (IsDetached()) return false; @@ -912,7 +919,7 @@ if (!frame) return; - WebViewBase* view = WebLocalFrameImpl::FromFrame(frame)->ViewImpl(); + WebViewImpl* view = WebLocalFrameImpl::FromFrame(frame)->ViewImpl(); if (!view) return;
diff --git a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp index d47d535..fb1ff16 100644 --- a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp +++ b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp
@@ -5,6 +5,7 @@ #include "modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h" #include "bindings/modules/v8/OffscreenRenderingContext.h" +#include "core/css/OffscreenFontSelector.h" #include "core/css/parser/CSSParser.h" #include "core/css/resolver/FontStyleResolver.h" #include "core/dom/ExecutionContext.h" @@ -31,10 +32,11 @@ : CanvasRenderingContext(canvas, attrs) { ExecutionContext* execution_context = canvas->GetTopExecutionContext(); if (execution_context->IsDocument()) { - if (ToDocument(execution_context) - ->GetSettings() - ->GetDisableReadingFromCanvas()) + Settings* settings = ToDocument(execution_context)->GetSettings(); + if (settings->GetDisableReadingFromCanvas()) canvas->SetDisableReadingFromCanvasTrue(); + font_selector_ = + OffscreenFontSelector::Create(settings->GetGenericFontFamilySettings()); return; } dirty_rect_for_commit_.setEmpty(); @@ -42,9 +44,12 @@ ToWorkerGlobalScope(execution_context)->GetWorkerSettings(); if (worker_settings && worker_settings->DisableReadingFromCanvas()) canvas->SetDisableReadingFromCanvasTrue(); + font_selector_ = OffscreenFontSelector::Create( + worker_settings->GetGenericFontFamilySettings()); } DEFINE_TRACE(OffscreenCanvasRenderingContext2D) { + visitor->Trace(font_selector_); CanvasRenderingContext::Trace(visitor); BaseRenderingContext2D::Trace(visitor); } @@ -293,7 +298,7 @@ FontDescription desc = FontStyleResolver::ComputeFont(*style); Font font = Font(desc); - ModifiableState().SetFont(font, nullptr); + ModifiableState().SetFont(font, font_selector_); ModifiableState().SetUnparsedFont(new_font); }
diff --git a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h index 425e3af..4cc50ef 100644 --- a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h +++ b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h
@@ -14,6 +14,7 @@ namespace blink { class Font; +class OffscreenFontSelector; class TextMetrics; class MODULES_EXPORT OffscreenCanvasRenderingContext2D final @@ -139,6 +140,8 @@ String ColorSpaceAsString() const override; CanvasPixelFormat PixelFormat() const override; SkIRect dirty_rect_for_commit_; + + Member<OffscreenFontSelector> font_selector_; }; DEFINE_TYPE_CASTS(OffscreenCanvasRenderingContext2D,
diff --git a/third_party/WebKit/Source/modules/remoteplayback/BUILD.gn b/third_party/WebKit/Source/modules/remoteplayback/BUILD.gn index 0de5988f..1732197 100644 --- a/third_party/WebKit/Source/modules/remoteplayback/BUILD.gn +++ b/third_party/WebKit/Source/modules/remoteplayback/BUILD.gn
@@ -12,5 +12,7 @@ "HTMLMediaElementRemotePlayback.h", "RemotePlayback.cpp", "RemotePlayback.h", + "RemotePlaybackConnectionCallbacks.cpp", + "RemotePlaybackConnectionCallbacks.h", ] }
diff --git a/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp b/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp index 308d817..71c6b5b 100644 --- a/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp +++ b/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp
@@ -18,9 +18,13 @@ #include "modules/EventTargetModules.h" #include "modules/presentation/PresentationController.h" #include "modules/remoteplayback/AvailabilityCallbackWrapper.h" +#include "modules/remoteplayback/RemotePlaybackConnectionCallbacks.h" #include "platform/MemoryCoordinator.h" #include "platform/wtf/text/Base64.h" #include "public/platform/modules/presentation/WebPresentationClient.h" +#include "public/platform/modules/presentation/WebPresentationConnectionProxy.h" +#include "public/platform/modules/presentation/WebPresentationError.h" +#include "public/platform/modules/presentation/WebPresentationInfo.h" namespace blink { @@ -44,10 +48,10 @@ return disconnected_value; } -void RunNotifyInitialAvailabilityTask(ExecutionContext* context, - WTF::Closure task, - std::unique_ptr<int> identifier) { - probe::AsyncTask async_task(context, identifier.get()); +void RunRemotePlaybackTask(ExecutionContext* context, + WTF::Closure task, + std::unique_ptr<int> task_id) { + probe::AsyncTask async_task(context, task_id.get()); task(); } @@ -221,6 +225,35 @@ } void RemotePlayback::PromptInternal() { + DCHECK(RuntimeEnabledFeatures::RemotePlaybackBackendEnabled()); + + if (RuntimeEnabledFeatures::NewRemotePlaybackPipelineEnabled()) { + WebPresentationClient* client = + PresentationController::ClientFromContext(GetExecutionContext()); + if (client && !availability_urls_.IsEmpty()) { + client->StartPresentation( + availability_urls_, + WTF::MakeUnique<RemotePlaybackConnectionCallbacks>(this)); + } else { + // TODO(yuryu): Wrapping PromptCancelled with WTF::Closure as + // InspectorInstrumentation requires a globally unique pointer to track + // tasks. We can remove the wrapper if InspectorInstrumentation returns a + // task id. + WTF::Closure task = + WTF::Bind(&RemotePlayback::PromptCancelled, WrapPersistent(this)); + std::unique_ptr<int> task_id = WTF::MakeUnique<int>(0); + probe::AsyncTaskScheduled(GetExecutionContext(), "promptCancelled", + task_id.get()); + TaskRunnerHelper::Get(TaskType::kMediaElementEvent, GetExecutionContext()) + ->PostTask(BLINK_FROM_HERE, + WTF::Bind(RunRemotePlaybackTask, + WrapPersistent(GetExecutionContext()), + WTF::Passed(std::move(task)), + WTF::Passed(std::move(task_id)))); + } + return; + } + if (state_ == WebRemotePlaybackState::kDisconnected) media_element_->RequestRemotePlayback(); else @@ -248,15 +281,15 @@ // We can remove the wrapper if InspectorInstrumentation returns a task id. WTF::Closure task = WTF::Bind(&RemotePlayback::NotifyInitialAvailability, WrapPersistent(this), id); - std::unique_ptr<int> identifier = WTF::MakeUnique<int>(0); + std::unique_ptr<int> task_id = WTF::MakeUnique<int>(0); probe::AsyncTaskScheduled(GetExecutionContext(), "watchAvailabilityCallback", - identifier.get()); + task_id.get()); TaskRunnerHelper::Get(TaskType::kMediaElementEvent, GetExecutionContext()) ->PostTask(BLINK_FROM_HERE, - WTF::Bind(RunNotifyInitialAvailabilityTask, + WTF::Bind(RunRemotePlaybackTask, WrapPersistent(GetExecutionContext()), WTF::Passed(std::move(task)), - WTF::Passed(std::move(identifier)))); + WTF::Passed(std::move(task_id)))); MaybeStartListeningForAvailability(); return id; @@ -283,12 +316,9 @@ } void RemotePlayback::StateChanged(WebRemotePlaybackState state) { - if (state_ == state) - return; - if (prompt_promise_resolver_) { - // Changing state to Disconnected from "disconnected" or "connecting" means - // that establishing connection with remote playback device failed. + // Changing state to "disconnected" from "disconnected" or "connecting" + // means that establishing connection with remote playback device failed. // Changing state to anything else means the state change intended by // prompt() succeeded. if (state_ != WebRemotePlaybackState::kConnected && @@ -305,6 +335,9 @@ prompt_promise_resolver_ = nullptr; } + if (state_ == state) + return; + state_ = state; switch (state_) { case WebRemotePlaybackState::kConnecting: @@ -403,8 +436,19 @@ availability_callbacks_.clear(); StopListeningForAvailability(); - if (state_ != WebRemotePlaybackState::kDisconnected) + if (state_ == WebRemotePlaybackState::kDisconnected) + return; + + if (RuntimeEnabledFeatures::NewRemotePlaybackPipelineEnabled()) { + WebPresentationClient* client = + PresentationController::ClientFromContext(GetExecutionContext()); + if (client) { + client->CloseConnection(presentation_url_, presentation_id_, + connection_proxy_.get()); + } + } else { media_element_->RequestRemotePlaybackStop(); + } } void RemotePlayback::AvailabilityChanged( @@ -445,6 +489,58 @@ return availability_urls_; } +void RemotePlayback::OnConnectionSuccess( + const WebPresentationInfo& presentation_info) { + DCHECK(RuntimeEnabledFeatures::NewRemotePlaybackPipelineEnabled()); + presentation_id_ = presentation_info.id; + presentation_url_ = presentation_info.url; + + StateChanged(WebRemotePlaybackState::kConnecting); +} + +void RemotePlayback::OnConnectionError(const WebPresentationError& error) { + DCHECK(RuntimeEnabledFeatures::NewRemotePlaybackPipelineEnabled()); + presentation_id_ = ""; + presentation_url_ = KURL(); + if (error.error_type == + WebPresentationError::kErrorTypePresentationRequestCancelled) { + PromptCancelled(); + return; + } + + StateChanged(WebRemotePlaybackState::kDisconnected); +} + +void RemotePlayback::BindProxy( + std::unique_ptr<WebPresentationConnectionProxy> proxy) { + DCHECK(proxy); + connection_proxy_ = std::move(proxy); +} + +void RemotePlayback::DidReceiveTextMessage(const WebString& message) { + NOTREACHED(); +} + +void RemotePlayback::DidReceiveBinaryMessage(const uint8_t* data, + size_t length) { + NOTREACHED(); +} + +void RemotePlayback::DidChangeState(WebPresentationConnectionState state) { + WebRemotePlaybackState remote_playback_state = + WebRemotePlaybackState::kDisconnected; + if (state == WebPresentationConnectionState::kConnecting) + remote_playback_state = WebRemotePlaybackState::kConnecting; + else if (state == WebPresentationConnectionState::kConnected) + remote_playback_state = WebRemotePlaybackState::kConnected; + + StateChanged(remote_playback_state); +} + +void RemotePlayback::DidClose() { + StateChanged(WebRemotePlaybackState::kDisconnected); +} + void RemotePlayback::StopListeningForAvailability() { if (!RuntimeEnabledFeatures::RemotePlaybackBackendEnabled()) return;
diff --git a/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.h b/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.h index 0dd29e8..836e14a 100644 --- a/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.h +++ b/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.h
@@ -15,9 +15,12 @@ #include "platform/wtf/Compiler.h" #include "platform/wtf/text/AtomicString.h" #include "platform/wtf/text/WTFString.h" +#include "public/platform/WebCallbacks.h" #include "public/platform/WebURL.h" #include "public/platform/WebVector.h" #include "public/platform/modules/presentation/WebPresentationAvailabilityObserver.h" +#include "public/platform/modules/presentation/WebPresentationConnection.h" +#include "public/platform/modules/presentation/WebPresentationConnectionProxy.h" #include "public/platform/modules/remoteplayback/WebRemotePlaybackAvailability.h" #include "public/platform/modules/remoteplayback/WebRemotePlaybackClient.h" #include "public/platform/modules/remoteplayback/WebRemotePlaybackState.h" @@ -29,12 +32,16 @@ class RemotePlaybackAvailabilityCallback; class ScriptPromiseResolver; class ScriptState; +class WebPresentationConnectionProxy; +struct WebPresentationError; +struct WebPresentationInfo; class MODULES_EXPORT RemotePlayback final : public EventTargetWithInlineData, public ActiveScriptWrappable<RemotePlayback>, NON_EXPORTED_BASE(public WebRemotePlaybackClient), - public WebPresentationAvailabilityObserver { + public WebPresentationAvailabilityObserver, + public NON_EXPORTED_BASE(WebPresentationConnection) { DEFINE_WRAPPERTYPEINFO(); USING_GARBAGE_COLLECTED_MIXIN(RemotePlayback); @@ -83,10 +90,21 @@ WebRemotePlaybackState GetState() const { return state_; } + // Called by RemotePlaybackConnectionCallbacks. + void OnConnectionSuccess(const WebPresentationInfo&); + void OnConnectionError(const WebPresentationError&); + // WebPresentationAvailabilityObserver implementation. void AvailabilityChanged(mojom::ScreenAvailability) override; const WebVector<WebURL>& Urls() const override; + // WebPresentationConnection implementation. + void BindProxy(std::unique_ptr<WebPresentationConnectionProxy>) override; + void DidReceiveTextMessage(const WebString& message) override; + void DidReceiveBinaryMessage(const uint8_t* data, size_t length) override; + void DidChangeState(WebPresentationConnectionState) override; + void DidClose() override; + // WebRemotePlaybackClient implementation. void StateChanged(WebRemotePlaybackState) override; void AvailabilityChanged(WebRemotePlaybackAvailability) override; @@ -132,6 +150,11 @@ Member<ScriptPromiseResolver> prompt_promise_resolver_; WebVector<WebURL> availability_urls_; bool is_listening_; + + // WebPresentationConnection implementation. + String presentation_id_; + KURL presentation_url_; + std::unique_ptr<WebPresentationConnectionProxy> connection_proxy_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/remoteplayback/RemotePlaybackConnectionCallbacks.cpp b/third_party/WebKit/Source/modules/remoteplayback/RemotePlaybackConnectionCallbacks.cpp new file mode 100644 index 0000000..4de6460 --- /dev/null +++ b/third_party/WebKit/Source/modules/remoteplayback/RemotePlaybackConnectionCallbacks.cpp
@@ -0,0 +1,33 @@ +// 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 "modules/remoteplayback/RemotePlaybackConnectionCallbacks.h" + +#include "modules/remoteplayback/RemotePlayback.h" + +namespace blink { + +RemotePlaybackConnectionCallbacks::RemotePlaybackConnectionCallbacks( + RemotePlayback* remote) + : remote_(remote) { + DCHECK(remote_); +} + +void RemotePlaybackConnectionCallbacks::OnSuccess( + const WebPresentationInfo& presentation_info) { + if (remote_) + remote_->OnConnectionSuccess(presentation_info); +} + +void RemotePlaybackConnectionCallbacks::OnError( + const WebPresentationError& error) { + if (remote_) + remote_->OnConnectionError(error); +} + +WebPresentationConnection* RemotePlaybackConnectionCallbacks::GetConnection() { + return remote_ ? remote_.Get() : nullptr; +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/modules/remoteplayback/RemotePlaybackConnectionCallbacks.h b/third_party/WebKit/Source/modules/remoteplayback/RemotePlaybackConnectionCallbacks.h new file mode 100644 index 0000000..24e5d12 --- /dev/null +++ b/third_party/WebKit/Source/modules/remoteplayback/RemotePlaybackConnectionCallbacks.h
@@ -0,0 +1,42 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RemotePlaybackConnectionCallbacks_h +#define RemotePlaybackConnectionCallbacks_h + +#include "platform/heap/Handle.h" +#include "platform/wtf/Noncopyable.h" +#include "public/platform/WebCallbacks.h" +#include "public/platform/modules/presentation/WebPresentationConnectionCallbacks.h" + +namespace blink { + +class RemotePlayback; +struct WebPresentationError; +struct WebPresentationInfo; + +// RemotePlaybackConnectionCallbacks extends WebCallbacks to handle the result +// of RemotePlayback.prompt(). +class RemotePlaybackConnectionCallbacks final + : public WebPresentationConnectionCallbacks { + public: + explicit RemotePlaybackConnectionCallbacks(RemotePlayback*); + ~RemotePlaybackConnectionCallbacks() override = default; + + // WebCallbacks implementation. + void OnSuccess(const WebPresentationInfo&) override; + void OnError(const WebPresentationError&) override; + + // WebPresentationConnectionCallbacks implementation. + WebPresentationConnection* GetConnection() override; + + private: + WeakPersistent<RemotePlayback> remote_; + + WTF_MAKE_NONCOPYABLE(RemotePlaybackConnectionCallbacks); +}; + +} // namespace blink + +#endif // RemotePlaybackConnectionCallbacks_h
diff --git a/third_party/WebKit/Source/modules/sensor/Accelerometer.cpp b/third_party/WebKit/Source/modules/sensor/Accelerometer.cpp index 21fcf8c..b5918bd 100644 --- a/third_party/WebKit/Source/modules/sensor/Accelerometer.cpp +++ b/third_party/WebKit/Source/modules/sensor/Accelerometer.cpp
@@ -28,15 +28,18 @@ : Sensor(execution_context, options, exception_state, sensor_type) {} double Accelerometer::x(bool& is_null) const { - return ReadingValue(0, is_null); + INIT_IS_NULL_AND_RETURN(is_null, 0.0); + return proxy()->reading().accel.x; } double Accelerometer::y(bool& is_null) const { - return ReadingValue(1, is_null); + INIT_IS_NULL_AND_RETURN(is_null, 0.0); + return proxy()->reading().accel.y; } double Accelerometer::z(bool& is_null) const { - return ReadingValue(2, is_null); + INIT_IS_NULL_AND_RETURN(is_null, 0.0); + return proxy()->reading().accel.z; } DEFINE_TRACE(Accelerometer) {
diff --git a/third_party/WebKit/Source/modules/sensor/AmbientLightSensor.cpp b/third_party/WebKit/Source/modules/sensor/AmbientLightSensor.cpp index dbcd1ea..09410ffc3 100644 --- a/third_party/WebKit/Source/modules/sensor/AmbientLightSensor.cpp +++ b/third_party/WebKit/Source/modules/sensor/AmbientLightSensor.cpp
@@ -35,7 +35,8 @@ SensorType::AMBIENT_LIGHT) {} double AmbientLightSensor::illuminance(bool& is_null) const { - return ReadingValue(0, is_null); + INIT_IS_NULL_AND_RETURN(is_null, 0.0); + return proxy()->reading().als.value; } DEFINE_TRACE(AmbientLightSensor) {
diff --git a/third_party/WebKit/Source/modules/sensor/Gyroscope.cpp b/third_party/WebKit/Source/modules/sensor/Gyroscope.cpp index 672d9c22..467c252 100644 --- a/third_party/WebKit/Source/modules/sensor/Gyroscope.cpp +++ b/third_party/WebKit/Source/modules/sensor/Gyroscope.cpp
@@ -30,15 +30,18 @@ SensorType::GYROSCOPE) {} double Gyroscope::x(bool& is_null) const { - return ReadingValue(0, is_null); + INIT_IS_NULL_AND_RETURN(is_null, 0.0); + return proxy()->reading().gyro.x; } double Gyroscope::y(bool& is_null) const { - return ReadingValue(1, is_null); + INIT_IS_NULL_AND_RETURN(is_null, 0.0); + return proxy()->reading().gyro.y; } double Gyroscope::z(bool& is_null) const { - return ReadingValue(2, is_null); + INIT_IS_NULL_AND_RETURN(is_null, 0.0); + return proxy()->reading().gyro.z; } DEFINE_TRACE(Gyroscope) {
diff --git a/third_party/WebKit/Source/modules/sensor/Magnetometer.cpp b/third_party/WebKit/Source/modules/sensor/Magnetometer.cpp index cd16b8c..bd41cf0 100644 --- a/third_party/WebKit/Source/modules/sensor/Magnetometer.cpp +++ b/third_party/WebKit/Source/modules/sensor/Magnetometer.cpp
@@ -30,15 +30,18 @@ SensorType::MAGNETOMETER) {} double Magnetometer::x(bool& is_null) const { - return ReadingValue(0, is_null); + INIT_IS_NULL_AND_RETURN(is_null, 0.0); + return proxy()->reading().magn.x; } double Magnetometer::y(bool& is_null) const { - return ReadingValue(1, is_null); + INIT_IS_NULL_AND_RETURN(is_null, 0.0); + return proxy()->reading().magn.y; } double Magnetometer::z(bool& is_null) const { - return ReadingValue(2, is_null); + INIT_IS_NULL_AND_RETURN(is_null, 0.0); + return proxy()->reading().magn.z; } DEFINE_TRACE(Magnetometer) {
diff --git a/third_party/WebKit/Source/modules/sensor/OrientationSensor.cpp b/third_party/WebKit/Source/modules/sensor/OrientationSensor.cpp index bface1e..fd748f2 100644 --- a/third_party/WebKit/Source/modules/sensor/OrientationSensor.cpp +++ b/third_party/WebKit/Source/modules/sensor/OrientationSensor.cpp
@@ -13,12 +13,9 @@ Vector<double> OrientationSensor::quaternion(bool& is_null) { reading_dirty_ = false; - is_null = !CanReturnReadings(); - return is_null ? Vector<double>() - : Vector<double>({ReadingValueUnchecked(0), // Vx - ReadingValueUnchecked(1), // Vy - ReadingValueUnchecked(2), // Vz - ReadingValueUnchecked(3)}); // W + INIT_IS_NULL_AND_RETURN(is_null, Vector<double>()); + const auto& quat = proxy()->reading().orientation_quat; + return Vector<double>({quat.x, quat.y, quat.z, quat.w}); } template <typename T> @@ -95,12 +92,9 @@ return; } - double x = ReadingValueUnchecked(0); - double y = ReadingValueUnchecked(1); - double z = ReadingValueUnchecked(2); - double w = ReadingValueUnchecked(3); + const auto& quat = proxy()->reading().orientation_quat; - DoPopulateMatrix(target_matrix, x, y, z, w); + DoPopulateMatrix(target_matrix, quat.x, quat.y, quat.z, quat.w); } void OrientationSensor::populateMatrix(
diff --git a/third_party/WebKit/Source/modules/sensor/Sensor.cpp b/third_party/WebKit/Source/modules/sensor/Sensor.cpp index 1b67570..e2e4bc7d 100644 --- a/third_party/WebKit/Source/modules/sensor/Sensor.cpp +++ b/third_party/WebKit/Source/modules/sensor/Sensor.cpp
@@ -98,7 +98,7 @@ is_null = false; return performance->MonotonicTimeToDOMHighResTimeStamp( - sensor_proxy_->reading().timestamp); + sensor_proxy_->reading().timestamp()); } DEFINE_TRACE(Sensor) { @@ -134,17 +134,6 @@ return result; } -double Sensor::ReadingValue(int index, bool& is_null) const { - is_null = !CanReturnReadings(); - return is_null ? 0.0 : ReadingValueUnchecked(index); -} - -double Sensor::ReadingValueUnchecked(int index) const { - DCHECK(sensor_proxy_); - DCHECK(index >= 0 && index < device::SensorReading::kValuesCount); - return sensor_proxy_->reading().values[index]; -} - void Sensor::InitSensorProxyIfNeeded() { if (sensor_proxy_) return; @@ -182,7 +171,7 @@ return; double elapsedTime = - sensor_proxy_->reading().timestamp - last_reported_timestamp_; + sensor_proxy_->reading().timestamp() - last_reported_timestamp_; DCHECK_GT(elapsedTime, 0.0); DCHECK_GT(configuration_->frequency, 0.0); @@ -317,7 +306,7 @@ void Sensor::NotifyReading() { DCHECK_EQ(state_, SensorState::kActivated); - last_reported_timestamp_ = sensor_proxy_->reading().timestamp; + last_reported_timestamp_ = sensor_proxy_->reading().timestamp(); DispatchEvent(Event::Create(EventTypeNames::reading)); } @@ -349,7 +338,7 @@ if (!IsActivated()) return false; DCHECK(sensor_proxy_); - return sensor_proxy_->reading().timestamp != 0.0; + return sensor_proxy_->reading().timestamp() != 0.0; } bool Sensor::IsIdleOrErrored() const {
diff --git a/third_party/WebKit/Source/modules/sensor/Sensor.h b/third_party/WebKit/Source/modules/sensor/Sensor.h index 84a11e8..7eca325d 100644 --- a/third_party/WebKit/Source/modules/sensor/Sensor.h +++ b/third_party/WebKit/Source/modules/sensor/Sensor.h
@@ -74,11 +74,10 @@ // parameters if needed. virtual SensorConfigurationPtr CreateSensorConfig(); - double ReadingValue(int index, bool& is_null) const; - double ReadingValueUnchecked(int index) const; bool CanReturnReadings() const; bool IsActivated() const { return state_ == SensorState::kActivated; } bool IsIdleOrErrored() const; + const SensorProxy* proxy() const { return sensor_proxy_; } // SensorProxy::Observer overrides. void OnSensorInitialized() override; @@ -122,4 +121,11 @@ } // namespace blink +// To be used in getters in concrete sensors +// bindings code. +#define INIT_IS_NULL_AND_RETURN(is_null, x) \ + is_null = !CanReturnReadings(); \ + if (is_null) \ + return (x) + #endif // Sensor_h
diff --git a/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp b/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp index 6211df4..82ea94d 100644 --- a/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp +++ b/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp
@@ -121,8 +121,8 @@ return; } - if (reading_.timestamp != reading_data.timestamp) { - DCHECK_GT(reading_data.timestamp, reading_.timestamp) + if (reading_.timestamp() != reading_data.timestamp()) { + DCHECK_GT(reading_data.timestamp(), reading_.timestamp()) << "Timestamps must increase monotonically"; reading_ = reading_data; for (Observer* observer : observers_)
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainerClient.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainerClient.cpp index c95d38b..fdb27a7 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainerClient.cpp +++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainerClient.cpp
@@ -44,7 +44,7 @@ return client; } Document* document = ToDocument(context); - if (!document->GetFrame()) + if (!document->GetFrame() || !document->GetFrame()->Client()) return nullptr; ServiceWorkerContainerClient* client =
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.cpp index 7f2823f..78a8bcd 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.cpp +++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.cpp
@@ -287,10 +287,15 @@ ServiceWorkerGlobalScopeClient* ServiceWorkerGlobalScopeClient::From( ExecutionContext* context) { - WorkerClients* clients = ToWorkerGlobalScope(context)->Clients(); - DCHECK(clients); - return static_cast<ServiceWorkerGlobalScopeClient*>( - Supplement<WorkerClients>::From(clients, SupplementName())); + // TODO(horo): Replace CHECK() to DCHECK() when crbug.com/749930 is fixed. + CHECK(context); + WorkerClients* worker_clients = ToWorkerGlobalScope(context)->Clients(); + CHECK(worker_clients); + ServiceWorkerGlobalScopeClient* client = + static_cast<ServiceWorkerGlobalScopeClient*>( + Supplement<WorkerClients>::From(worker_clients, SupplementName())); + CHECK(client); + return client; } DEFINE_TRACE(ServiceWorkerGlobalScopeClient) {
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.cpp index 76acada..51ea65ec 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.cpp +++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.cpp
@@ -130,12 +130,12 @@ void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchAbortEvent( int event_id, - const WebString& tag) { + const WebString& id) { WaitUntilObserver* observer = WaitUntilObserver::Create( WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchAbort, event_id); BackgroundFetchClickEventInit init; - init.setTag(tag); + init.setId(id); BackgroundFetchEvent* event = BackgroundFetchEvent::Create( EventTypeNames::backgroundfetchabort, init, observer); @@ -145,13 +145,13 @@ void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchClickEvent( int event_id, - const WebString& tag, + const WebString& id, BackgroundFetchState status) { WaitUntilObserver* observer = WaitUntilObserver::Create( WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchClick, event_id); BackgroundFetchClickEventInit init; - init.setTag(tag); + init.setId(id); switch (status) { case BackgroundFetchState::kPending: @@ -173,13 +173,13 @@ void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchFailEvent( int event_id, - const WebString& tag, + const WebString& id, const WebVector<WebBackgroundFetchSettledFetch>& fetches) { WaitUntilObserver* observer = WaitUntilObserver::Create( WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchFail, event_id); BackgroundFetchFailEventInit init; - init.setTag(tag); + init.setId(id); ScriptState* script_state = WorkerGlobalScope()->ScriptController()->GetScriptState(); @@ -194,13 +194,13 @@ void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchedEvent( int event_id, - const WebString& tag, + const WebString& id, const WebVector<WebBackgroundFetchSettledFetch>& fetches) { WaitUntilObserver* observer = WaitUntilObserver::Create( WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetched, event_id); BackgroundFetchedEventInit init; - init.setTag(tag); + init.setId(id); ScriptState* script_state = WorkerGlobalScope()->ScriptController()->GetScriptState(); @@ -450,11 +450,11 @@ void ServiceWorkerGlobalScopeProxy::DispatchSyncEvent( int event_id, - const WebString& tag, + const WebString& id, LastChanceOption last_chance) { WaitUntilObserver* observer = WaitUntilObserver::Create( WorkerGlobalScope(), WaitUntilObserver::kSync, event_id); - Event* event = SyncEvent::Create(EventTypeNames::sync, tag, + Event* event = SyncEvent::Create(EventTypeNames::sync, id, last_chance == kIsLastChance, observer); WorkerGlobalScope()->DispatchExtendableEvent(event, observer); }
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.cpp index 1c98702..e7bac5ca4 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.cpp +++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.cpp
@@ -21,14 +21,18 @@ return manager_->IsScriptInstalled(script_url); } -Optional<InstalledScriptsManager::ScriptData> -ServiceWorkerInstalledScriptsManager::GetScriptData(const KURL& script_url) { +InstalledScriptsManager::ScriptStatus +ServiceWorkerInstalledScriptsManager::GetScriptData( + const KURL& script_url, + InstalledScriptsManager::ScriptData* out_script_data) { DCHECK(!IsMainThread()); // This blocks until the script is received from the browser. std::unique_ptr<WebServiceWorkerInstalledScriptsManager::RawScriptData> raw_script_data = manager_->GetRawScriptData(script_url); if (!raw_script_data) - return WTF::nullopt; + return ScriptStatus::kTaken; + if (!raw_script_data->IsValid()) + return ScriptStatus::kFailed; // This is from WorkerScriptLoader::DidReceiveData. std::unique_ptr<TextResourceDecoder> decoder; @@ -59,7 +63,8 @@ InstalledScriptsManager::ScriptData script_data( script_url, source_text_builder.ToString(), std::move(meta_data), raw_script_data->TakeHeaders()); - return Optional<ScriptData>(std::move(script_data)); + *out_script_data = std::move(script_data); + return ScriptStatus::kSuccess; } } // namespace blink
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.h index b306fb34..28cce29 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.h +++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.h
@@ -20,7 +20,8 @@ // InstalledScriptsManager implementation. bool IsScriptInstalled(const KURL& script_url) const override; - Optional<ScriptData> GetScriptData(const KURL& script_url) override; + ScriptStatus GetScriptData(const KURL& script_url, + ScriptData* out_script_data) override; private: std::unique_ptr<WebServiceWorkerInstalledScriptsManager> manager_;
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn index 25fd52ea..58d43cb 100644 --- a/third_party/WebKit/Source/platform/BUILD.gn +++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -706,6 +706,7 @@ "fonts/FontSelectionAlgorithm.h", "fonts/FontSelectionTypes.cpp", "fonts/FontSelectionTypes.h", + "fonts/FontSelector.cpp", "fonts/FontSelector.h", "fonts/FontSelectorClient.h", "fonts/FontSmoothingMode.h",
diff --git a/third_party/WebKit/Source/platform/exported/WebServiceWorkerInstalledScriptsManager.cpp b/third_party/WebKit/Source/platform/exported/WebServiceWorkerInstalledScriptsManager.cpp index d25a33b..e54b1fc0 100644 --- a/third_party/WebKit/Source/platform/exported/WebServiceWorkerInstalledScriptsManager.cpp +++ b/third_party/WebKit/Source/platform/exported/WebServiceWorkerInstalledScriptsManager.cpp
@@ -12,15 +12,27 @@ WebString encoding, WebVector<BytesChunk> script_text, WebVector<BytesChunk> meta_data) { - return WTF::WrapUnique(new RawScriptData( - std::move(encoding), std::move(script_text), std::move(meta_data))); + return WTF::WrapUnique( + new RawScriptData(std::move(encoding), std::move(script_text), + std::move(meta_data), true /* is_valid */)); +} + +// static +std::unique_ptr<WebServiceWorkerInstalledScriptsManager::RawScriptData> +WebServiceWorkerInstalledScriptsManager::RawScriptData:: + CreateInvalidInstance() { + return WTF::WrapUnique( + new RawScriptData(WebString() /* encoding */, WebVector<BytesChunk>(), + WebVector<BytesChunk>(), false /* is_valid */)); } WebServiceWorkerInstalledScriptsManager::RawScriptData::RawScriptData( WebString encoding, WebVector<BytesChunk> script_text, - WebVector<BytesChunk> meta_data) - : encoding_(std::move(encoding)), + WebVector<BytesChunk> meta_data, + bool is_valid) + : is_valid_(is_valid), + encoding_(std::move(encoding)), script_text_(std::move(script_text)), meta_data_(std::move(meta_data)), headers_(WTF::MakeUnique<CrossThreadHTTPHeaderMapData>()) {}
diff --git a/third_party/WebKit/Source/platform/fonts/FontSelector.cpp b/third_party/WebKit/Source/platform/fonts/FontSelector.cpp new file mode 100644 index 0000000..006c41c --- /dev/null +++ b/third_party/WebKit/Source/platform/fonts/FontSelector.cpp
@@ -0,0 +1,50 @@ +// 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 "platform/fonts/FontSelector.h" + +#include "build/build_config.h" +#include "platform/fonts/FontCache.h" +#include "platform/fonts/FontDescription.h" +#include "platform/fonts/GenericFontFamilySettings.h" + +namespace blink { + +AtomicString FontSelector::FamilyNameFromSettings( + const GenericFontFamilySettings& settings, + const FontDescription& font_description, + const AtomicString& generic_family_name) { +#if defined(OS_ANDROID) + if (font_description.GenericFamily() == FontDescription::kStandardFamily) { + return FontCache::GetGenericFamilyNameForScript( + FontFamilyNames::webkit_standard, font_description); + } + + if (generic_family_name.StartsWith("-webkit-")) { + return FontCache::GetGenericFamilyNameForScript(generic_family_name, + font_description); + } +#else + UScriptCode script = font_description.GetScript(); + if (font_description.GenericFamily() == FontDescription::kStandardFamily) + return settings.Standard(script); + if (generic_family_name == FontFamilyNames::webkit_serif) + return settings.Serif(script); + if (generic_family_name == FontFamilyNames::webkit_sans_serif) + return settings.SansSerif(script); + if (generic_family_name == FontFamilyNames::webkit_cursive) + return settings.Cursive(script); + if (generic_family_name == FontFamilyNames::webkit_fantasy) + return settings.Fantasy(script); + if (generic_family_name == FontFamilyNames::webkit_monospace) + return settings.Fixed(script); + if (generic_family_name == FontFamilyNames::webkit_pictograph) + return settings.Pictograph(script); + if (generic_family_name == FontFamilyNames::webkit_standard) + return settings.Standard(script); +#endif + return g_empty_atom; +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/FontSelector.h b/third_party/WebKit/Source/platform/fonts/FontSelector.h index f37f09d7..9ba9e1f 100644 --- a/third_party/WebKit/Source/platform/fonts/FontSelector.h +++ b/third_party/WebKit/Source/platform/fonts/FontSelector.h
@@ -38,6 +38,7 @@ class FontData; class FontDescription; class FontSelectorClient; +class GenericFontFamilySettings; class PLATFORM_EXPORT FontSelector : public FontCacheClient { public: @@ -60,6 +61,12 @@ virtual void RegisterForInvalidationCallbacks(FontSelectorClient*) = 0; virtual void UnregisterForInvalidationCallbacks(FontSelectorClient*) = 0; + + protected: + static AtomicString FamilyNameFromSettings( + const GenericFontFamilySettings&, + const FontDescription&, + const AtomicString& generic_family_name); }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.cpp b/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.cpp index 58b8dda..bf4cc1b9 100644 --- a/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.cpp +++ b/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.cpp
@@ -44,6 +44,42 @@ fantasy_font_family_map_(other.fantasy_font_family_map_), pictograph_font_family_map_(other.pictograph_font_family_map_) {} +void GenericFontFamilySettings::IsolatedCopyTo( + GenericFontFamilySettings& dest) const { + DCHECK(!IsIsolated()); + auto copy_to_vector = [](const ScriptFontFamilyMap& map, + IsolatedCopyVector& vector) { + for (const auto& kv : map) + vector.emplace_back(kv.key, kv.value.GetString().IsolatedCopy()); + }; + + dest.isolated_copy_ = WTF::MakeUnique<IsolatedCopyVector[]>(7); + copy_to_vector(standard_font_family_map_, dest.isolated_copy_[0]); + copy_to_vector(serif_font_family_map_, dest.isolated_copy_[1]); + copy_to_vector(fixed_font_family_map_, dest.isolated_copy_[2]); + copy_to_vector(sans_serif_font_family_map_, dest.isolated_copy_[3]); + copy_to_vector(cursive_font_family_map_, dest.isolated_copy_[4]); + copy_to_vector(fantasy_font_family_map_, dest.isolated_copy_[5]); + copy_to_vector(pictograph_font_family_map_, dest.isolated_copy_[6]); +} + +void GenericFontFamilySettings::MakeAtomic() { + DCHECK(IsIsolated()); + auto copy_from_vector = [](ScriptFontFamilyMap& map, + const IsolatedCopyVector& vector) { + for (const auto& kv : vector) + map.insert(kv.first, AtomicString(kv.second)); + }; + copy_from_vector(standard_font_family_map_, isolated_copy_[0]); + copy_from_vector(serif_font_family_map_, isolated_copy_[1]); + copy_from_vector(fixed_font_family_map_, isolated_copy_[2]); + copy_from_vector(sans_serif_font_family_map_, isolated_copy_[3]); + copy_from_vector(cursive_font_family_map_, isolated_copy_[4]); + copy_from_vector(fantasy_font_family_map_, isolated_copy_[5]); + copy_from_vector(pictograph_font_family_map_, isolated_copy_[6]); + isolated_copy_.reset(); +} + GenericFontFamilySettings& GenericFontFamilySettings::operator=( const GenericFontFamilySettings& other) { standard_font_family_map_ = other.standard_font_family_map_;
diff --git a/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.h b/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.h index 9bf452d..2d388e84 100644 --- a/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.h +++ b/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.h
@@ -34,6 +34,7 @@ #include "platform/PlatformExport.h" #include "platform/wtf/Allocator.h" #include "platform/wtf/HashMap.h" +#include "platform/wtf/Vector.h" #include "platform/wtf/text/AtomicString.h" #include "platform/wtf/text/AtomicStringHash.h" @@ -75,6 +76,19 @@ GenericFontFamilySettings& operator=(const GenericFontFamilySettings&); + // Returns a new instance with String instead of AtomicString objects. + // This allows GenericFontFamilySettings to be sent from one thread to + // another, since AtomicStrings can't be shared cross-threads. + // Before using it, call it MakeAtomic() on the final thread, to bring back + // the AtomicStrings. + void IsolatedCopyTo(GenericFontFamilySettings& dest) const; + + bool IsIsolated() const { return isolated_copy_.get(); } + + // Transform an IsolatedCopy GenericFontFamilySettings into a regular + // GenericFontFamilySettings. + void MakeAtomic(); + private: // UScriptCode uses -1 and 0 for UScriptInvalidCode and UScriptCommon. // We need to use -2 and -3 for empty value and deleted value. @@ -105,6 +119,9 @@ ScriptFontFamilyMap cursive_font_family_map_; ScriptFontFamilyMap fantasy_font_family_map_; ScriptFontFamilyMap pictograph_font_family_map_; + + typedef Vector<std::pair<int, String>> IsolatedCopyVector; + std::unique_ptr<IsolatedCopyVector[]> isolated_copy_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp index 5e84d5e7..ace06512 100644 --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp
@@ -173,6 +173,9 @@ public: static FakeScrollableArea* Create() { return new FakeScrollableArea; } + CompositorElementId GetCompositorElementId() const override { + return CompositorElementId(); + } bool IsActive() const override { return false; } int ScrollSize(ScrollbarOrientation) const override { return 100; } bool IsScrollCornerVisible() const override { return false; }
diff --git a/third_party/WebKit/Source/platform/heap/ThreadState.cpp b/third_party/WebKit/Source/platform/heap/ThreadState.cpp index 331f02ad..3bdceb1 100644 --- a/third_party/WebKit/Source/platform/heap/ThreadState.cpp +++ b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
@@ -1078,6 +1078,8 @@ default: NOTREACHED(); } + + gc_age_++; } #if DCHECK_IS_ON()
diff --git a/third_party/WebKit/Source/platform/heap/ThreadState.h b/third_party/WebKit/Source/platform/heap/ThreadState.h index 948f1ff..c4ca061 100644 --- a/third_party/WebKit/Source/platform/heap/ThreadState.h +++ b/third_party/WebKit/Source/platform/heap/ThreadState.h
@@ -562,6 +562,8 @@ return &FromObject(object)->Heap() == &Heap(); } + int GcAge() const { return gc_age_; } + private: template <typename T> friend class PrefinalizerRegistration; @@ -714,6 +716,8 @@ size_t allocated_object_size_; size_t marked_object_size_; size_t reported_memory_to_v8_; + + int gc_age_ = 0; }; template <ThreadAffinity affinity>
diff --git a/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp b/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp index ed39e24..3667f43 100644 --- a/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp +++ b/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp
@@ -122,7 +122,7 @@ } if (run_state_ == RunState::kWaitingToSendToCompositor) { - if (!compositor_animation_attached_to_element_id_) + if (!element_id_) ReattachCompositorPlayerIfNeeded( GetScrollableArea()->GetCompositorAnimationTimeline());
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp index cfffac255..ec43102 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp
@@ -340,7 +340,7 @@ } if (run_state_ == RunState::kWaitingToSendToCompositor) { - if (!compositor_animation_attached_to_element_id_) + if (!element_id_) ReattachCompositorPlayerIfNeeded( GetScrollableArea()->GetCompositorAnimationTimeline());
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp index 1986012..3b5ca0d 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp
@@ -21,7 +21,7 @@ namespace blink { ScrollAnimatorCompositorCoordinator::ScrollAnimatorCompositorCoordinator() - : compositor_animation_attached_to_element_id_(), + : element_id_(), run_state_(RunState::kIdle), compositor_animation_id_(0), compositor_animation_group_id_(0), @@ -180,34 +180,26 @@ bool ScrollAnimatorCompositorCoordinator::ReattachCompositorPlayerIfNeeded( CompositorAnimationTimeline* timeline) { bool reattached = false; - CompositorElementId compositor_animation_attached_to_element_id; - if (GetScrollableArea()->LayerForScrolling()) { - compositor_animation_attached_to_element_id = GetScrollableArea() - ->LayerForScrolling() - ->PlatformLayer() - ->GetElementId(); - DCHECK(compositor_animation_attached_to_element_id); - } + CompositorElementId element_id = GetScrollElementId(); + DCHECK(element_id || (RuntimeEnabledFeatures::SlimmingPaintV2Enabled() || + !GetScrollableArea()->LayerForScrolling())); - if (compositor_animation_attached_to_element_id != - compositor_animation_attached_to_element_id_) { + if (element_id != element_id_) { if (compositor_player_ && timeline) { // Detach from old layer (if any). - if (compositor_animation_attached_to_element_id_) { + if (element_id_) { if (compositor_player_->IsElementAttached()) compositor_player_->DetachElement(); timeline->PlayerDestroyed(*this); } // Attach to new layer (if any). - if (compositor_animation_attached_to_element_id) { + if (element_id) { DCHECK(!compositor_player_->IsElementAttached()); timeline->PlayerAttached(*this); - compositor_player_->AttachElement( - compositor_animation_attached_to_element_id); + compositor_player_->AttachElement(element_id); reattached = true; } - compositor_animation_attached_to_element_id_ = - compositor_animation_attached_to_element_id; + element_id_ = element_id; } } @@ -253,15 +245,23 @@ impl_only_animation_takeover_; } +CompositorElementId ScrollAnimatorCompositorCoordinator::GetScrollElementId() + const { + if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) + return GetScrollableArea()->GetCompositorElementId(); + + GraphicsLayer* layer = GetScrollableArea()->LayerForScrolling(); + return layer ? layer->PlatformLayer()->GetElementId() : CompositorElementId(); +} + void ScrollAnimatorCompositorCoordinator::UpdateImplOnlyCompositorAnimations() { if (!HasImplOnlyAnimationUpdate()) return; - GraphicsLayer* layer = GetScrollableArea()->LayerForScrolling(); CompositorAnimationHost* host = GetScrollableArea()->GetCompositorAnimationHost(); - if (layer && host) { - CompositorElementId element_id = layer->PlatformLayer()->GetElementId(); + CompositorElementId element_id = GetScrollElementId(); + if (host && element_id) { if (!impl_only_animation_adjustment_.IsZero()) { host->AdjustImplOnlyScrollOffsetAnimation( element_id, gfx::Vector2dF(impl_only_animation_adjustment_.Width(),
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h index 902b9666..d4a1ba02 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h
@@ -169,7 +169,9 @@ FRIEND_TEST_ALL_PREFIXES(ScrollAnimatorTest, ImplOnlyAnimationUpdatesCleared); std::unique_ptr<CompositorAnimationPlayer> compositor_player_; - CompositorElementId compositor_animation_attached_to_element_id_; + // The element id to which the compositor animation is attached when + // the animation is present. + CompositorElementId element_id_; RunState run_state_; int compositor_animation_id_; int compositor_animation_group_id_; @@ -184,6 +186,7 @@ bool impl_only_animation_takeover_; private: + CompositorElementId GetScrollElementId() const; bool HasImplOnlyAnimationUpdate() const; void UpdateImplOnlyCompositorAnimations(); // Accesses compositing state and should only be called when in or after
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp index 950fb14..3b98cf7 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp
@@ -83,6 +83,9 @@ IntSize ScrollOffsetInt() const override { return IntSize(); } int VisibleHeight() const override { return 768; } int VisibleWidth() const override { return 1024; } + CompositorElementId GetCompositorElementId() const override { + return CompositorElementId(); + } bool ScrollAnimatorEnabled() const override { return scroll_animator_enabled_; }
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h index fa03f6b..8889f20 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h +++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
@@ -255,6 +255,7 @@ // of the top-level FrameView. virtual IntRect ScrollableAreaBoundingBox() const = 0; + virtual CompositorElementId GetCompositorElementId() const = 0; virtual bool ScrollAnimatorEnabled() const { return false; } // NOTE: Only called from Internals for testing.
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarTestSuite.h b/third_party/WebKit/Source/platform/scroll/ScrollbarTestSuite.h index c80dbbda..1802537 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollbarTestSuite.h +++ b/third_party/WebKit/Source/platform/scroll/ScrollbarTestSuite.h
@@ -61,6 +61,9 @@ } int VisibleHeight() const override { return 768; } int VisibleWidth() const override { return 1024; } + CompositorElementId GetCompositorElementId() const override { + return CompositorElementId(); + } bool ScrollAnimatorEnabled() const override { return false; } int PageStep(ScrollbarOrientation) const override { return 0; } void ScrollControlWasSetNeedsPaintInvalidation() {}
diff --git a/third_party/WebKit/Source/web/BUILD.gn b/third_party/WebKit/Source/web/BUILD.gn index fa35ef08..5dee02a 100644 --- a/third_party/WebKit/Source/web/BUILD.gn +++ b/third_party/WebKit/Source/web/BUILD.gn
@@ -8,67 +8,3 @@ import("//third_party/WebKit/Source/config.gni") import("//third_party/WebKit/Source/core/core.gni") import("//third_party/WebKit/Source/modules/modules.gni") - -visibility = [ "//third_party/WebKit/*" ] - -group("webkit_unit_tests_data") { - data = [ - "../core/testing/data/", - "../core/paint/test_data/", - ] -} - -test("webkit_unit_tests") { - visibility = [] # Allow re-assignment of list. - visibility = [ "*" ] - - sources = [ - # FIXME: Move the tests from web/tests/ to appropriate places. - # crbug.com/353585 - - "tests/RunAllTests.cpp", - ] - sources += bindings_unittest_files - - deps = [ - "//base", - "//base:i18n", - "//base/test:test_support", - "//content/test:test_support", - "//gpu:test_support", - "//services/device/public/interfaces:interfaces_blink", - "//testing/gmock", - "//testing/gtest", - "//third_party/WebKit/Source/controller", - "//third_party/WebKit/Source/core:unit_tests", - "//third_party/WebKit/Source/modules:unit_tests", - "//third_party/WebKit/Source/modules/exported:test_support", - "//third_party/WebKit/Source/platform:test_support", - "//third_party/WebKit/Source/platform:unit_tests", - "//third_party/WebKit/Source/platform/wtf", - "//third_party/libwebp", - "//third_party/zlib", - "//url", - "//v8", - ] - - data_deps = [ - ":webkit_unit_tests_data", - "//content/shell:pak", - ] - - configs += [ - "//third_party/WebKit/Source:config", - "//third_party/WebKit/Source:inside_blink", - "//third_party/WebKit/Source/core:blink_core_pch", - ] - - if (is_android) { - deps += [ - "//base:base_java", - "//content/public/android:content_java", - "//content/shell/android:content_shell_assets", - "//net/android:net_java", - ] - } -}
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_mock.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_mock.py index efb7e35..08631801 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_mock.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_mock.py
@@ -217,6 +217,7 @@ def mock_git_commands(vals, strict=False): + # TODO(robertma): Support optional look-up by arguments. def run_fn(args): sub_command = args[1] if strict and sub_command not in vals:
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit.py index d176add5..95c320e 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit.py
@@ -6,7 +6,7 @@ import json import logging import os -import urllib +import re from webkitpy.w3c.common import CHROMIUM_WPT_DIR @@ -92,7 +92,16 @@ return self._data.get('has_review_started') def latest_commit_message_with_footers(self): - return self.current_revision['commit_with_footers'] + return self.strip_commit_positions(self.current_revision['commit_with_footers']) + + @staticmethod + def strip_commit_positions(commit_with_footers): + """Strips Cr-{Original-}Commit-Position from the footers. + + Commit positions are incorrect for in-progress CLs, which causes + confusions. See crbug.com/737178 for more context. + """ + return re.sub(r'\nCr-(Original-)?Commit-Position:.*', '', commit_with_footers) @property def current_revision_description(self):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit_unittest.py index b9ace308..b1add065 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit_unittest.py
@@ -33,3 +33,9 @@ cl = GerritCL({'change_id': 1}, MockGerritAPI(None, None, None)) actual_patch = cl.filter_transform_patch(sample_patch) self.assertEqual(actual_patch, expected_patch) + + def test_strip_commit_positions(self): + commit_with_footers = ('Test commit\nChange-Id: foobar\n' + 'Cr-Original-Commit-Position: refs/heads/master@{#10}\n' + 'Cr-Commit-Position: refs/heads/master@{#10}') + self.assertEqual(GerritCL.strip_commit_positions(commit_with_footers), 'Test commit\nChange-Id: foobar')
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt.py index 3ce43afc..1765f73 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt.py
@@ -7,7 +7,6 @@ import logging from webkitpy.common.system.executive import ScriptError -from webkitpy.w3c.chromium_commit import ChromiumCommit from webkitpy.w3c.common import WPT_GH_SSH_URL_TEMPLATE, WPT_MIRROR_URL, CHROMIUM_WPT_DIR _log = logging.getLogger(__name__) @@ -49,24 +48,6 @@ """Runs a command in the local WPT directory.""" return self.host.executive.run_command(command, cwd=self.path, **kwargs) - def most_recent_chromium_commit(self): - """Finds the most recent commit in WPT with a Chromium commit position. - - Returns: - A pair (commit hash, ChromiumCommit instance). - """ - wpt_commit_hash = self.run(['git', 'rev-list', 'HEAD', '-n', '1', '--grep=Cr-Commit-Position']) - if not wpt_commit_hash: - return None, None - - wpt_commit_hash = wpt_commit_hash.strip() - position = self.run(['git', 'footers', '--position', wpt_commit_hash]) - position = position.strip() - assert position - - chromium_commit = ChromiumCommit(self.host, position=position) - return wpt_commit_hash, chromium_commit - def clean(self): """Resets git to a clean state, on origin/master with no changed files.""" self.run(['git', 'reset', '--hard', 'HEAD'])
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt_unittest.py index a982df0..d49f107 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt_unittest.py
@@ -5,7 +5,6 @@ import unittest from webkitpy.common.host_mock import MockHost -from webkitpy.common.system.executive_mock import MockExecutive, mock_git_commands from webkitpy.common.system.filesystem_mock import MockFileSystem from webkitpy.w3c.local_wpt import LocalWPT @@ -49,30 +48,6 @@ local_wpt.run(['echo', 'rutabaga']) self.assertEqual(host.executive.calls, [['echo', 'rutabaga']]) - def test_last_wpt_exported_commit(self): - host = MockHost() - host.executive = mock_git_commands({ - 'rev-list': '9ea4fc353a4b1c11c6e524270b11baa4d1ddfde8', - 'footers': 'Cr-Commit-Position: 123', - 'crrev-parse': 'add087a97844f4b9e307d9a216940582d96db306', - }, strict=True) - host.filesystem = MockFileSystem() - local_wpt = LocalWPT(host, 'token') - - wpt_sha, chromium_commit = local_wpt.most_recent_chromium_commit() - self.assertEqual(wpt_sha, '9ea4fc353a4b1c11c6e524270b11baa4d1ddfde8') - self.assertEqual(chromium_commit.position, '123') - self.assertEqual(chromium_commit.sha, 'add087a97844f4b9e307d9a216940582d96db306') - - def test_last_wpt_exported_commit_not_found(self): - host = MockHost() - host.executive = MockExecutive(run_command_fn=lambda _: '') - host.filesystem = MockFileSystem() - local_wpt = LocalWPT(host, 'token') - - commit = local_wpt.most_recent_chromium_commit() - self.assertEqual(commit, (None, None)) - def test_create_branch_with_patch(self): host = MockHost() host.filesystem = MockFileSystem()
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter.py index 63be892..5f2fed3 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter.py
@@ -119,39 +119,6 @@ except MergeError: _log.info('Could not merge PR.') - def export_first_exportable_commit(self): - """Looks for exportable commits in Chromium, creates PR if found.""" - - wpt_commit, chromium_commit = self.local_wpt.most_recent_chromium_commit() - assert chromium_commit, 'No Chromium commit found, this is impossible' - - wpt_behind_master = self.local_wpt.commits_behind_master(wpt_commit) - - _log.info('\nLast Chromium export commit in web-platform-tests:') - _log.info('web-platform-tests@%s', wpt_commit) - _log.info('(%d behind web-platform-tests@origin/master)', wpt_behind_master) - - _log.info('\nThe above WPT commit points to the following Chromium commit:') - _log.info('chromium@%s', chromium_commit.sha) - _log.info('(%d behind chromium@origin/master)', chromium_commit.num_behind_master()) - - exportable_commits = exportable_commits_over_last_n_commits( - chromium_commit.sha, self.host, self.local_wpt, self.wpt_github) - - if not exportable_commits: - _log.info('No exportable commits found in Chromium, stopping.') - return - - _log.info('Found %d exportable commits in Chromium:', len(exportable_commits)) - for commit in exportable_commits: - _log.info('- %s %s', commit, commit.subject()) - - outbound_commit = exportable_commits[0] - _log.info('Picking the earliest commit and creating a PR') - _log.info('- %s %s', outbound_commit.sha, outbound_commit.subject()) - - self.create_pull_request(outbound_commit) - def create_pull_request(self, outbound_commit): patch = outbound_commit.format_patch() message = outbound_commit.message()
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py index 9ea75de..90495e0c 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
@@ -65,8 +65,8 @@ _log.debug('Noting the current Chromium commit.') # TODO(qyearsley): Use Git (self.host.git) to run git commands. - _, show_ref_output = self.run(['git', 'show-ref', 'HEAD']) - chromium_commit = show_ref_output.split()[0] + _, show_ref_output = self.run(['git', 'show-ref', '--verify', '--head', '--hash', 'HEAD']) + chromium_commit = show_ref_output.strip() local_wpt.fetch() @@ -74,10 +74,12 @@ _log.info('Checking out %s', options.revision) self.run(['git', 'checkout', options.revision], cwd=local_wpt.path) - _log.info('Noting the revision we are importing.') + _log.debug('Noting the revision we are importing.') _, show_ref_output = self.run(['git', 'show-ref', 'origin/master'], cwd=local_wpt.path) import_commit = 'wpt@%s' % show_ref_output.split()[0] + _log.info('Importing wpt@%s to Chromium %s', import_commit, chromium_commit) + commit_message = self._commit_message(chromium_commit, import_commit) if not options.ignore_exportable_commits:
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py index 2f0df3c3..5a2a0566 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py
@@ -264,9 +264,11 @@ if pull_request: return pull_request # The Change ID can't be used for commits made via Rietveld, - # so we fall back to trying to use commit position here, although - # commit position is not correct sometimes (https://crbug.com/737178). - # TODO(qyearsley): Remove this fallback after full Gerrit migration. + # so we fall back to trying to use commit position here. + # Note that Gerrit returns ToT+1 as the commit positions for in-flight + # CLs, but they are scrubbed from the PR description and hence would + # not be mismatched to random Chromium commits in the fallback. + # TODO(robertma): Remove this fallback after Rietveld becomes read-only. return self.pr_with_position(chromium_commit.position) def pr_with_change_id(self, target_change_id):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github_unittest.py index 1a4af1c..49602b0 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github_unittest.py
@@ -118,6 +118,16 @@ with self.assertRaises(GitHubError): self.wpt_github.delete_remote_branch('rutabaga') + def test_pr_for_chromium_commit_change_id_only(self): + self.wpt_github.all_pull_requests = lambda: [ + PullRequest('PR1', 1, 'body\nChange-Id: I00c0ffee', 'open', []), + PullRequest('PR2', 2, 'body\nChange-Id: I00decade', 'open', []), + ] + chromium_commit = MockChromiumCommit( + MockHost(), change_id='I00decade', position='refs/heads/master@{#10}') + pull_request = self.wpt_github.pr_for_chromium_commit(chromium_commit) + self.assertEqual(pull_request.number, 2) + def test_pr_for_chromium_commit_prefers_change_id(self): self.wpt_github.all_pull_requests = lambda: [ PullRequest('PR1', 1, 'body\nChange-Id: I00c0ffee\nCr-Commit-Position: refs/heads/master@{#10}', 'open', []),
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn index cc84766..ff35a751 100644 --- a/third_party/WebKit/public/BUILD.gn +++ b/third_party/WebKit/public/BUILD.gn
@@ -41,12 +41,12 @@ public_deps = [ "//third_party/WebKit/Source/controller", + "//third_party/WebKit/Source/controller:webkit_unit_tests", "//third_party/WebKit/Source/core", "//third_party/WebKit/Source/modules", "//third_party/WebKit/Source/platform:blink_platform_unittests", "//third_party/WebKit/Source/platform/heap:blink_heap_unittests", "//third_party/WebKit/Source/platform/wtf:wtf_unittests", - "//third_party/WebKit/Source/web:webkit_unit_tests", ] }
diff --git a/third_party/WebKit/public/blink_typemaps.gni b/third_party/WebKit/public/blink_typemaps.gni index 68996104..1e0424c 100644 --- a/third_party/WebKit/public/blink_typemaps.gni +++ b/third_party/WebKit/public/blink_typemaps.gni
@@ -7,10 +7,10 @@ "//services/viz/public/cpp/compositing/compositor_frame_for_blink.typemap", "//cc/ipc/frame_sink_id.typemap", "//cc/ipc/local_surface_id.typemap", - "//cc/ipc/returned_resource.typemap", "//cc/ipc/surface_id.typemap", "//cc/ipc/surface_info.typemap", "//cc/ipc/surface_sequence.typemap", "//gpu/ipc/common/mailbox_holder_for_blink.typemap", "//gpu/ipc/common/sync_token.typemap", + "//services/viz/public/cpp/compositing/returned_resource.typemap", ]
diff --git a/third_party/WebKit/public/platform/WebSelectionBound.h b/third_party/WebKit/public/platform/WebSelectionBound.h index afbe9e18..915080e 100644 --- a/third_party/WebKit/public/platform/WebSelectionBound.h +++ b/third_party/WebKit/public/platform/WebSelectionBound.h
@@ -17,7 +17,7 @@ enum Type { kCaret, kSelectionLeft, kSelectionRight }; explicit WebSelectionBound(Type type) - : type(type), layer_id(0), is_text_direction_rtl(false) {} + : type(type), layer_id(0), is_text_direction_rtl(false), hidden(false) {} // The logical type of the endpoint. Note that this is dependent not only on // the bound's relative location, but also the underlying text direction. @@ -33,6 +33,9 @@ // Whether the text direction at this location is RTL. bool is_text_direction_rtl; + + // Whether this bound is hidden (clipped out/occluded). + bool hidden; }; } // namespace blink
diff --git a/third_party/WebKit/public/platform/modules/background_fetch/background_fetch.mojom b/third_party/WebKit/public/platform/modules/background_fetch/background_fetch.mojom index 0c780a4..3d5e49c1 100644 --- a/third_party/WebKit/public/platform/modules/background_fetch/background_fetch.mojom +++ b/third_party/WebKit/public/platform/modules/background_fetch/background_fetch.mojom
@@ -9,9 +9,9 @@ enum BackgroundFetchError { NONE, - DUPLICATED_TAG, + DUPLICATED_ID, INVALID_ARGUMENT, - INVALID_TAG + INVALID_ID }; // Represents the definition of an icon developers can optionally provide with a @@ -36,49 +36,49 @@ // Analogous to the following structure in the spec: // https://wicg.github.io/background-fetch/#background-fetch-registration struct BackgroundFetchRegistration { - string tag; + string id; array<IconDefinition> icons; int64 total_download_size; string title; }; interface BackgroundFetchService { - // Creates a new Background Fetch registration identified by |tag| with the + // Creates a new Background Fetch registration identified by |id| with the // given |options| for the sequence of |requests|. Fetch(int64 service_worker_registration_id, url.mojom.Origin origin, - string tag, + string id, array<FetchAPIRequest> requests, BackgroundFetchOptions options) => (BackgroundFetchError error, BackgroundFetchRegistration? registration); // Updates the user interface for the Background Fetch identified by the - // |service_worker_registration_id| and the |tag|. + // |service_worker_registration_id| and the |id|. UpdateUI(int64 service_worker_registration_id, url.mojom.Origin origin, - string tag, + string id, string title) => (BackgroundFetchError error); // Aborts the Background Fetch registration identified by the - // |service_worker_registration_id| and the |tag|. + // |service_worker_registration_id| and the |id|. Abort(int64 service_worker_registration_id, url.mojom.Origin origin, - string tag) + string id) => (BackgroundFetchError error); // Gets the Background Fetch registration identified by the - // |service_worker_registration_id| and the |tag|. + // |service_worker_registration_id| and the |id|. GetRegistration(int64 service_worker_registration_id, url.mojom.Origin origin, - string tag) + string id) => (BackgroundFetchError error, BackgroundFetchRegistration? registration); - // Gets the sequence of tags for active Background Fetch registrations given + // Gets the sequence of ids for active Background Fetch registrations given // the |service_worker_registration_id|. - GetTags(int64 service_worker_registration_id, url.mojom.Origin origin) + GetIds(int64 service_worker_registration_id, url.mojom.Origin origin) => (BackgroundFetchError error, - array<string> tags); + array<string> ids); };
diff --git a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h index 46be9927..2acd74f 100644 --- a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h +++ b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h
@@ -30,6 +30,7 @@ WebString encoding, WebVector<BytesChunk> script_text, WebVector<BytesChunk> meta_data); + static std::unique_ptr<RawScriptData> CreateInvalidInstance(); // Implementation of the destructor should be in the Blink side because only // Blink can know all of members. @@ -37,19 +38,29 @@ void AddHeader(const WebString& key, const WebString& value); + // Returns false if it fails to receive the script from the browser. + bool IsValid() const { return is_valid_; } // The encoding of the script text. - const WebString& Encoding() const { return encoding_; } + const WebString& Encoding() const { + DCHECK(is_valid_); + return encoding_; + } // An array of raw byte chunks of the script text. const WebVector<BytesChunk>& ScriptTextChunks() const { + DCHECK(is_valid_); return script_text_; } // An array of raw byte chunks of the scripts's meta data from the script's // V8 code cache. - const WebVector<BytesChunk>& MetaDataChunks() const { return meta_data_; } + const WebVector<BytesChunk>& MetaDataChunks() const { + DCHECK(is_valid_); + return meta_data_; + } #if INSIDE_BLINK // The HTTP headers of the script. std::unique_ptr<CrossThreadHTTPHeaderMapData> TakeHeaders() { + DCHECK(is_valid_); return std::move(headers_); } #endif // INSIDE_BLINK @@ -59,7 +70,9 @@ // know the exact size of this instance. RawScriptData(WebString encoding, WebVector<BytesChunk> script_text, - WebVector<BytesChunk> meta_data); + WebVector<BytesChunk> meta_data, + bool is_valid); + const bool is_valid_; WebString encoding_; WebVector<BytesChunk> script_text_; WebVector<BytesChunk> meta_data_;
diff --git a/third_party/WebKit/public/platform/web_feature.mojom b/third_party/WebKit/public/platform/web_feature.mojom index 2e9a4f6b..8fffb86 100644 --- a/third_party/WebKit/public/platform/web_feature.mojom +++ b/third_party/WebKit/public/platform/web_feature.mojom
@@ -1449,7 +1449,6 @@ kWebkitCSSMatrixConstructFromString = 1913, kCanRequestURLHTTPContainingNewline = 1914, kGetGamepads = 1916, - kV8SVGPathElement_GetPathSegAtLength_Method = 1917, kMediaStreamConstraintsAudio = 1918, kMediaStreamConstraintsAudioUnconstrained = 1919, kMediaStreamConstraintsVideo = 1920, @@ -1602,6 +1601,7 @@ kPersistentClientHintHeader = 2065, kStyleSheetListNonNullAnonymousNamedGetter = 2066, kOffMainThreadFetch = 2067, + kHTMLOptionsCollectionNamedGetterReturnsNodeList = 2068, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/public/web/WebAXObject.h b/third_party/WebKit/public/web/WebAXObject.h index 633973b..b139f443 100644 --- a/third_party/WebKit/public/web/WebAXObject.h +++ b/third_party/WebKit/public/web/WebAXObject.h
@@ -161,6 +161,7 @@ BLINK_EXPORT WebString AriaAutoComplete() const; BLINK_EXPORT WebAXAriaCurrentState AriaCurrentState() const; BLINK_EXPORT bool AriaHasPopup() const; + BLINK_EXPORT bool IsEditableRoot() const; BLINK_EXPORT bool IsEditable() const; BLINK_EXPORT bool IsMultiline() const; BLINK_EXPORT bool IsRichlyEditable() const;
diff --git a/third_party/axe-core/README.chromium b/third_party/axe-core/README.chromium index 7ab4e2f..7697284 100644 --- a/third_party/axe-core/README.chromium +++ b/third_party/axe-core/README.chromium
@@ -11,6 +11,8 @@ Description: Accessibility engine for automated Web UI testing. This will be used to run automated accessibility tests in web-ui. +This includes the axe.d.ts file so developers can reference the type definitions +of the aXe audit in code search and function documentation. Local Modifications: 1 Checked out the origin/shadowDOM branch
diff --git a/third_party/axe-core/axe.d.ts b/third_party/axe-core/axe.d.ts new file mode 100644 index 0000000..258cf3dc --- /dev/null +++ b/third_party/axe-core/axe.d.ts
@@ -0,0 +1,169 @@ +// Type definitions for axe-core 2.3.1 +// Project: https://github.com/dequelabs/axe-core +// Definitions by: Marcy Sutton <https://github.com/marcysutton> + +declare module axe { + + type ImpactValue = "minor" | "moderate" | "serious" | "critical"; + + type TagValue = "wcag2a" | "wcag2aa" | "section508" | "best-practice"; + + type ReporterVersion = "v1" | "v2"; + + type RunOnlyType = "rule" | "rules" | "tag" | "tags"; + + interface ElementContext { + node?: Object, + selector?: string, + include?: any[], + exclude?: any[] + } + interface RunOnly { + type: RunOnlyType, + value?: { + include?: string[], + exclude?: string[] + } + values?: TagValue[] + } + interface AxeResults { + url: string, + timestamp: string, + passes: Result[], + violations: Result[], + incomplete: Result[], + inapplicable: Result[] + } + interface Result { + description: string, + help: string, + helpUrl: string, + id: string, + impact: ImpactValue, + tags: TagValue[], + nodes: NodeResult[] + } + interface NodeResult { + html: string, + impact: ImpactValue, + target: string[], + any: CheckResult[], + all: CheckResult[], + none: CheckResult[], + failureSummary?: string + } + interface CheckResult { + id: string, + impact: string, + message: string, + data: any, + relatedNodes?: RelatedNode[] + } + interface RelatedNode { + target: string[], + html: string + } + interface Spec { + branding?: { + brand: string, + application: string + }, + reporter?: ReporterVersion, + checks?: Check[], + rules?: Rule[] + } + interface Check { + id: string, + evaluate: Function, + after?: Function, + options?: any, + matches?: string, + enabled?: boolean + } + interface Rule { + id: string, + selector?: string, + excludeHidden?: boolean, + enabled?: boolean, + pageLevel?: boolean, + any?: string[], + all?: string[], + none?: string[], + tags?: string[], + matches?: string + } + interface AxePlugin { + id: string, + run(...args:any[]): any, + commands: { + id: string, + callback(...args:any[]): void + }[], + cleanup?(callback:Function): void + } + + let plugins: any + + /** + * Source string to use as an injected script in Selenium + */ + let source: string + + /** + * Object for aXe Results + */ + var AxeResults: AxeResults + + /** + * Runs a number of rules against the provided HTML page and returns the resulting issue list + * + * @param {Object} context Optional The `Context` specification object @see Context + * @param {Array} options Optional Options passed into rules or checks, temporarily modifying them. + * @param {Function} callback Optional The function to invoke when analysis is complete. + * @returns {any} results If the callback was not defined, aXe will return a Promise instead. + */ + function run(context?: ElementContext, options?: {runOnly?: RunOnly, rules?: Object, iframes?: Boolean, elementRef?: Boolean, selectors?: Boolean}, callback?: (error: Error, results:AxeResults) => void): any + + /** + * Starts analysis on the current document and its subframes + * + * @param {Object} context The `Context` specification object @see Context + * @param {Array} options Options passed into rules or checks, temporarily modifyint them. + * @param {Function} callback The function to invoke when analysis is complete. + * @returns {Object} results The aXe results object + */ + function a11yCheck(context: ElementContext, options: {runOnly?: RunOnly, rules?: Object, iframes?: Boolean, elementRef?: Boolean, selectors?: Boolean}, callback: (results:AxeResults) => void): AxeResults + + /** + * Method for configuring the data format used by aXe. Helpful for adding new + * rules, which must be registered with the library to execute. + * @param {Spec} Spec Object with valid `branding`, `reporter`, `checks` and `rules` data + */ + function configure(spec: Spec): void + + /** + * Searches and returns rules that contain a tag in the list of tags. + * @param {Array} tags Optional array of tags + * @return {Array} Array of rules + */ + function getRules(tags?: string[]): Object[] + + /** + * Restores the default axe configuration + */ + function reset(): void + + /** + * Function to register a plugin configuration in document and its subframes + * @param {Object} plugin A plugin configuration object + */ + function registerPlugin(plugin: AxePlugin): void + + /** + * Function to clean up plugin configuration in document and its subframes + */ + function cleanup(): void + +} + +export = axe;
diff --git a/third_party/libxslt/BUILD.gn b/third_party/libxslt/BUILD.gn index 30c64408..de06534 100644 --- a/third_party/libxslt/BUILD.gn +++ b/third_party/libxslt/BUILD.gn
@@ -82,7 +82,7 @@ public_configs = [ ":libxslt_config" ] cflags = [] - if (is_linux || is_android) { + if (is_linux || is_android || is_fuchsia) { include_dirs = [ "linux" ] } else if (is_win) { include_dirs = [ "win32" ]
diff --git a/third_party/opus/README.chromium b/third_party/opus/README.chromium index 892499e..d1ff674 100644 --- a/third_party/opus/README.chromium +++ b/third_party/opus/README.chromium
@@ -1,6 +1,6 @@ Name: opus -URL: https://git.xiph.org/?p=opus.git;a=snapshot;h=ed08a3b0ba736d007c1a87b9c5c077b01170e7be;sf=tgz -Version: ed08a3b0ba736d007c1a87b9c5c077b01170e7be +URL: https://git.xiph.org/?p=opus.git;a=snapshot;h=3fe744ea04fdcc418fb85c2c133d13372ebb019b;sf=tgz +Version: 3fe744ea04fdcc418fb85c2c133d13372ebb019b License: BSD License File: src/COPYING Security Critical: yes
diff --git a/third_party/opus/src/celt/arm/pitch_arm.h b/third_party/opus/src/celt/arm/pitch_arm.h index 4ee13bd..bed8b04 100644 --- a/third_party/opus/src/celt/arm/pitch_arm.h +++ b/third_party/opus/src/celt/arm/pitch_arm.h
@@ -90,7 +90,9 @@ (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *, const opus_val16 *, opus_val32 *, int, int, int); # define OVERRIDE_PITCH_XCORR (1) -# define celt_pitch_xcorr (*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK]) +# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \ + ((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \ + xcorr, len, max_pitch, arch)) # elif defined(OPUS_ARM_PRESUME_EDSP) || \ defined(OPUS_ARM_PRESUME_MEDIA) || \ @@ -142,7 +144,9 @@ const opus_val16 *, opus_val32 *, int, int, int); # define OVERRIDE_PITCH_XCORR (1) -# define celt_pitch_xcorr (*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK]) +# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \ + ((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \ + xcorr, len, max_pitch, arch)) # elif defined(OPUS_ARM_PRESUME_NEON_INTR)
diff --git a/third_party/opus/src/doc/draft-ietf-codec-opus-update.xml b/third_party/opus/src/doc/draft-ietf-codec-opus-update.xml index a97124f..6e52a16 100644 --- a/third_party/opus/src/doc/draft-ietf-codec-opus-update.xml +++ b/third_party/opus/src/doc/draft-ietf-codec-opus-update.xml
@@ -10,8 +10,8 @@ <?rfc inline="yes"?> <?rfc compact="yes"?> <?rfc subcompact="no"?> -<rfc category="std" docName="draft-ietf-codec-opus-update-06" - ipr="trust200902"> +<rfc category="std" docName="draft-ietf-codec-opus-update-08" + ipr="trust200902" updates="6716"> <front> <title abbrev="Opus Update">Updates to the Opus Audio Codec</title> @@ -47,21 +47,24 @@ - <date day="19" month="June" year="2017" /> + <date day="26" month="July" year="2017" /> <abstract> <t>This document addresses minor issues that were found in the specification - of the Opus audio codec in <xref target="RFC6716">RFC 6716</xref>.</t> + of the Opus audio codec in RFC 6716.</t> </abstract> </front> <middle> <section title="Introduction"> <t>This document addresses minor issues that were discovered in the reference - implementation of the Opus codec that serves as the specification in - <xref target="RFC6716">RFC 6716</xref>. Only issues affecting the decoder are + implementation of the Opus codec. Unlike most IETF specifications, Opus is defined + in <xref target="RFC6716">RFC 6716</xref> in terms of a normative reference + decoder implementation rather than from the associated text description. + That RFC includes the reference decoder implementation as Appendix A. + That's why only issues affecting the decoder are listed here. An up-to-date implementation of the Opus encoder can be found at - https://opus-codec.org/.</t> + <eref target="https://opus-codec.org/"/>.</t> <t> Some of the changes in this document update normative behaviour in a way that requires new test vectors. The English text of the specification is unaffected, only @@ -75,8 +78,8 @@ at the end of a line and the white space at the beginning of the following line are not part of the patch. A properly formatted patch including all changes is available at - <eref target="https://jmvalin.ca/misc_stuff/opus_update.patch"/>. (EDITOR: - change to an ietf.org link when ready) + <eref target="https://www.ietf.org/proceedings/98/slides/materials-98-codec-opus-update-00.patch"/> + and has a SHA1 029e3aa88fc342c91e67a21e7bfbc9458661cd5f. </t> </section> @@ -96,6 +99,7 @@ </t> <figure> <artwork><![CDATA[ +<CODE BEGINS> for( n = 0; n < DECODER_NUM_CHANNELS; n++ ) { ret = silk_init_decoder( &channel_state[ n ] ); } @@ -106,11 +110,12 @@ return ret; } +<CODE ENDS> ]]></artwork> </figure> <t> - This change affects the normative part of the decoder, although the - amount of change is too small to make a significant impact on testvectors. + This change affects the normative output of the decoder, but the + amount of change is within the tolerance and too small to make the testvector check fail. </t> </section> @@ -123,6 +128,7 @@ </t> <figure> <artwork><![CDATA[ +<CODE BEGINS> /* Padding flag is bit 6 */ if (ch&0x40) { @@ -138,12 +144,13 @@ } while (p==255); - len -= padding; } +<CODE ENDS> ]]></artwork> </figure> <t>This packet parsing issue is limited to reading memory up to about 60 kB beyond the compressed buffer. This can only be triggered by a compressed packet more than about 16 MB long, so it's not a problem - for RTP. In theory, it <spanx style="emph">could</spanx> crash a file + for RTP. In theory, it could crash a file decoder (e.g. Opus in Ogg) if the memory just after the incoming packet is out-of-range, but our attempts to trigger such a crash in a production application built using an affected version of the Opus decoder failed.</t> @@ -156,24 +163,25 @@ local buffer was opus_int16.</t> <t>Because the size was wrong, this potentially allowed the source and destination regions of the memcpy() to overlap. - We <spanx style="emph">believe</spanx> that nSamplesIn is at least fs_in_khZ, + We believe that nSamplesIn (number of input samples) is at least fs_in_khZ (sampling rate in kHz), which is at least 8. Since RESAMPLER_ORDER_FIR_12 is only 8, that should not be a problem once the type size is fixed.</t> <t>The size of the buffer used RESAMPLER_MAX_BATCH_SIZE_IN, but the - data stored in it was actually _twice_ the input batch size + data stored in it was actually twice the input batch size (nSamplesIn<<1).</t> </list></t> <t> The fact that the code never produced any error in testing (including when run under the Valgrind memory debugger), suggests that in practice the batch sizes are reasonable enough that none of the issues above - was ever a problem. However, proving that is non-obvious. + was ever a problem. However, the authors know of no obvious approach to proving that. </t> <t>The code can be fixed by applying the following changes to line 78 of silk/resampler_private_IIR_FIR.c: </t> <figure> <artwork><![CDATA[ +<CODE BEGINS> ) { silk_resampler_state_struct *S = \ @@ -226,6 +234,7 @@ + silk_memcpy( S->sFIR, &buf[ nSamplesIn << 1 ], \ RESAMPLER_ORDER_FIR_12 * sizeof( opus_int16 ) ); } +<CODE ENDS> ]]></artwork> </figure> </section> @@ -240,6 +249,7 @@ </t> <figure> <artwork><![CDATA[ +<CODE BEGINS> /* Update AR coefficient */ for( n = 0; n < k; n++ ) { - tmp_QA = Aold_QA[ n ] - MUL32_FRAC_Q( \ @@ -255,11 +265,12 @@ + } + Anew_QA[ n ] = ( opus_int32 )tmp64; } +<CODE ENDS> ]]></artwork> </figure> </section> - <section title="Integer wrap-around in LSF decoding"> + <section title="Integer wrap-around in LSF decoding" anchor="lsf_overflow"> <t> It was discovered -- also from decoder fuzzing -- that an integer wrap-around could occur when decoding line spectral frequency coefficients from extreme bitstreams. @@ -269,6 +280,7 @@ </t> <figure> <artwork><![CDATA[ +<CODE BEGINS> /* Keep delta_min distance between the NLSFs */ for( i = 1; i < L; i++ ) - NLSF_Q15[i] = silk_max_int( NLSF_Q15[i], \ @@ -277,6 +289,7 @@ silk_ADD_SAT16( NLSF_Q15[i-1], NDeltaMin_Q15[i] ) ); /* Last NLSF should be no higher than 1 - NDeltaMin[L] */ +<CODE ENDS> ]]></artwork> </figure> @@ -285,12 +298,13 @@ <section title="Cap on Band Energy"> <t>On extreme bit-streams, it is possible for log-domain band energy levels to exceed the maximum single-precision floating point value once converted - to a linear scale. This would later cause the decoded values to be NaN, + to a linear scale. This would later cause the decoded values to be NaN (not a number), possibly causing problems in the software using the PCM values. This can be avoided with the following patch to line 552 of celt/quant_bands.c: </t> <figure> <artwork><![CDATA[ +<CODE BEGINS> { opus_val16 lg = ADD16(oldEBands[i+c*m->nbEBands], SHL16((opus_val16)eMeans[i],6)); @@ -298,6 +312,7 @@ eBands[i+c*m->nbEBands] = PSHR32(celt_exp2(lg),4); } for (;i<m->nbEBands;i++) +<CODE ENDS> ]]></artwork> </figure> </section> @@ -307,7 +322,7 @@ enough bits to code a single CELT band (8 - 9.6 kHz). When that happens, the second band (CELT band 18, from 9.6 to 12 kHz) cannot use folding because it is wider than the amount already coded, and falls back to - LCG noise. Because it can also happen on transients (e.g. stops), it + white noise. Because it can also happen on transients (e.g. stops), it can cause audible pre-echo. </t> <t> @@ -319,6 +334,7 @@ </t> <figure> <artwork><![CDATA[ +<CODE BEGINS> b = 0; } @@ -347,6 +363,7 @@ tf_change = tf_res[i]; if (i>=m->effEBands) { +<CODE ENDS> ]]></artwork> </figure> @@ -356,6 +373,7 @@ <figure> <artwork><![CDATA[ +<CODE BEGINS> fold_start = lowband_offset; while(M*eBands[--fold_start] > effective_lowband); fold_end = lowband_offset-1; @@ -366,6 +384,7 @@ fold_i = fold_start; do { x_cm |= collapse_masks[fold_i*C+0]; +<CODE ENDS> ]]></artwork> </figure> <t> @@ -408,8 +427,69 @@ SHOULD be based on the new test vectors rather than the old ones. </t> <t>The new test vectors are located at - <eref target="https://jmvalin.ca/misc_stuff/opus_newvectors.tar.gz"/>. (EDITOR: - change to an ietf.org link when ready) + <eref target="https://www.ietf.org/proceedings/98/slides/materials-98-codec-opus-newvectors-00.tar.gz"/>. + The SHA1 hash of the test vectors are: +<figure> +<artwork> +<![CDATA[ +e49b2862ceec7324790ed8019eb9744596d5be01 testvector01.bit +b809795ae1bcd606049d76de4ad24236257135e0 testvector02.bit +e0c4ecaeab44d35a2f5b6575cd996848e5ee2acc testvector03.bit +a0f870cbe14ebb71fa9066ef3ee96e59c9a75187 testvector04.bit +9b3d92b48b965dfe9edf7b8a85edd4309f8cf7c8 testvector05.bit +28e66769ab17e17f72875283c14b19690cbc4e57 testvector06.bit +bacf467be3215fc7ec288f29e2477de1192947a6 testvector07.bit +ddbe08b688bbf934071f3893cd0030ce48dba12f testvector08.bit +3932d9d61944dab1201645b8eeaad595d5705ecb testvector09.bit +521eb2a1e0cc9c31b8b740673307c2d3b10c1900 testvector10.bit +6bc8f3146fcb96450c901b16c3d464ccdf4d5d96 testvector11.bit +338c3f1b4b97226bc60bc41038becbc6de06b28f testvector12.bit +f5ef93884da6a814d311027918e9afc6f2e5c2c8 testvector01.dec +48ac1ff1995250a756e1e17bd32acefa8cd2b820 testvector02.dec +d15567e919db2d0e818727092c0af8dd9df23c95 testvector03.dec +1249dd28f5bd1e39a66fd6d99449dca7a8316342 testvector04.dec +b85675d81deef84a112c466cdff3b7aaa1d2fc76 testvector05.dec +55f0b191e90bfa6f98b50d01a64b44255cb4813e testvector06.dec +61e8b357ab090b1801eeb578a28a6ae935e25b7b testvector07.dec +a58539ee5321453b2ddf4c0f2500e856b3966862 testvector08.dec +bb96aad2cde188555862b7bbb3af6133851ef8f4 testvector09.dec +1b6cdf0413ac9965b16184b1bea129b5c0b2a37a testvector10.dec +b1fff72b74666e3027801b29dbc48b31f80dee0d testvector11.dec +98e09bbafed329e341c3b4052e9c4ba5fc83f9b1 testvector12.dec +1e7d984ea3fbb16ba998aea761f4893fbdb30157 testvector01m.dec +48ac1ff1995250a756e1e17bd32acefa8cd2b820 testvector02m.dec +d15567e919db2d0e818727092c0af8dd9df23c95 testvector03m.dec +1249dd28f5bd1e39a66fd6d99449dca7a8316342 testvector04m.dec +d70b0bad431e7d463bc3da49bd2d49f1c6d0a530 testvector05m.dec +6ac1648c3174c95fada565161a6c78bdbe59c77d testvector06m.dec +fc5e2f709693738324fb4c8bdc0dad6dda04e713 testvector07m.dec +aad2ba397bf1b6a18e8e09b50e4b19627d479f00 testvector08m.dec +6feb7a7b9d7cdc1383baf8d5739e2a514bd0ba08 testvector09m.dec +1b6cdf0413ac9965b16184b1bea129b5c0b2a37a testvector10m.dec +fd3d3a7b0dfbdab98d37ed9aa04b659b9fefbd18 testvector11m.dec +98e09bbafed329e341c3b4052e9c4ba5fc83f9b1 testvector12m.dec +]]> +</artwork> +</figure> + Note that the decoder input bitstream files (.bit) are unchanged. + </t> + </section> + + <section anchor="security" title="Security Considerations"> + <t>This document fixes two security issues reported on Opus and that affect the + reference implementation in <xref target="RFC6716">RFC 6716</xref>: CVE-2013-0899 + <eref target="https://nvd.nist.gov/vuln/detail/CVE-2013-0899"/> + and CVE-2017-0381 <eref target="https://nvd.nist.gov/vuln/detail/CVE-2017-0381"/>. + CVE-2013-0899 is fixed by <xref target="padding"/> and + could theoretically cause information leak, but the + leaked information would at the very least go through the decoder process before + being accessible to the attacker. Also, the bug can only be triggered by Opus packets + at least 24 MB in size. CVE-2017-0381 is fixed by <xref target="lsf_overflow"/> and, as far + as the authors are aware, could not be exploited in any way (despite the claims in + the CVE) unless the read-only table + was somehow placed very close to sensitive data, which is highly unlikely. + Beyond the two fixed CVEs, this document adds no new security considerations on top of + <xref target="RFC6716">RFC 6716</xref>. </t> </section> @@ -422,13 +502,14 @@ <section anchor="Acknowledgements" title="Acknowledgements"> <t>We would like to thank Juri Aedla for reporting the issue with the parsing of - the Opus padding. Also, thanks to Jonathan Lennox and Mark Harris for their + the Opus padding. Thanks to Felicia Lim for reporting the LSF integer overflow issue. + Also, thanks to Tina le Grand, Jonathan Lennox, and Mark Harris for their feedback on this document.</t> </section> </middle> <back> - <references title="References"> + <references title="Normative References"> <?rfc include="http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml"?> <?rfc include="http://xml.resource.org/public/rfc/bibxml/reference.RFC.6716.xml"?>
diff --git a/third_party/opus/src/tests/opus_decode_fuzzer.c b/third_party/opus/src/tests/opus_decode_fuzzer.c index 4b4a3f37..9002622 100644 --- a/third_party/opus/src/tests/opus_decode_fuzzer.c +++ b/third_party/opus/src/tests/opus_decode_fuzzer.c
@@ -28,6 +28,7 @@ #include "config.h" #endif +#include <stdint.h> #include <stdlib.h> #include <string.h> #include "opus.h"
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index b0021aa..72ff3cc 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -2590,7 +2590,7 @@ <int value="161" label="BDH_INVALID_DESCRIPTOR_ID"/> <int value="162" label="RWH_INVALID_BEGIN_FRAME_ACK_DID_NOT_SWAP"/> <int value="163" label="RWH_INVALID_BEGIN_FRAME_ACK_COMPOSITOR_FRAME"/> - <int value="164" label="BFSI_INVALID_TAG"/> + <int value="164" label="BFSI_INVALID_ID"/> <int value="165" label="BFSI_INVALID_REQUESTS"/> <int value="166" label="BFSI_INVALID_TITLE"/> <int value="167" label="RWH_INVALID_FRAME_TOKEN"/> @@ -16019,6 +16019,7 @@ <int value="2065" label="PersistentClientHintHeader"/> <int value="2066" label="StyleSheetListNonNullAnonymousNamedGetter"/> <int value="2067" label="OffMainThreadFetch"/> + <int value="2068" label="HTMLOptionsCollectionNamedGetterReturnsNodeList"/> </enum> <enum name="FeedbackSource"> @@ -22698,6 +22699,7 @@ <int value="-1972312724" label="OfflinePagesLoadSignalCollecting:enabled"/> <int value="-1972219399" label="NTPSaveToOffline:enabled"/> <int value="-1971086581" label="print-scaling"/> + <int value="-1964261747" label="WebVrVsyncAlign:disabled"/> <int value="-1963427770" label="EmojiHandwritingVoiceInput:disabled"/> <int value="-1963402827" label="enable-topchrome-md"/> <int value="-1961648833" label="show_summary"/> @@ -23906,6 +23908,7 @@ <int value="1928407249" label="NewPhotoPicker:enabled"/> <int value="1930901873" label="disable-sync-app-list"/> <int value="1931309368" label="fill-on-account-select:disabled"/> + <int value="1936810062" label="WebVrVsyncAlign:enabled"/> <int value="1939413645" label="enable-invalid-cert-collection"/> <int value="1942911276" label="enable-grouped-history"/> <int value="1944156526" label="sync-url"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 17c509d..bf3ca92 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -5609,6 +5609,12 @@ </summary> </histogram> +<histogram name="Blink.CookieJar.SyncCookiesTime" units="microseconds"> + <owner>kinuko@chromium.org</owner> + <owner>dcheng@chromium.org</owner> + <summary>Microseconds per sync IPC call to fetch cookies.</summary> +</histogram> + <histogram name="Blink.DecodedImage.CanvasExpanded" enum="BooleanCanvasExpanded"> <obsolete> @@ -14144,6 +14150,16 @@ <summary>Result of DNS probes sent by the probe service.</summary> </histogram> +<histogram name="Document.OutliveTimeAfterShutdown.DestroyedBeforeProcessDies"> + <owner>hajimehoshi@chromium.org</owner> + <owner>keishi@chromium.org</owner> + <summary> + Records the GC count between the time when the document is shut down and and + the time when the document is actually destroyed. This only counts documents + that are destroyed before the process dies. + </summary> +</histogram> + <histogram name="DocumentActivity.Enabled" enum="RunningMode"> <obsolete> Removed 9/2016. @@ -32328,6 +32344,23 @@ <summary>Various usage counts for media galleries.</summary> </histogram> +<histogram name="MediaRouter.Cast.Discovery.ConnectedDevicesCount" + units="devices"> + <owner>zhaobin@chromium.org</owner> + <summary> + The number of connected Cast devices. Recorded when browser finishes + discovering Cast devices. Recording happens roughly once per hour. + </summary> +</histogram> + +<histogram name="MediaRouter.Cast.Discovery.KnownDevicesCount" units="devices"> + <owner>zhaobin@chromium.org</owner> + <summary> + The number of known Cast devices. Recorded when browser finishes discovering + Cast devices. Recording happens roughly once per hour. + </summary> +</histogram> + <histogram name="MediaRouter.Dial.AvailableDevicesCount" units="devices"> <owner>zhaobin@chromium.org</owner> <summary> @@ -47773,6 +47806,18 @@ </summary> </histogram> +<histogram name="Notifications.ExtensionNotificationIdLength" + units="characters"> + <owner>peter@chromium.org</owner> + <summary> + The length, in characters, of the id given to an extension notification. + These can be automatically generated, in which case they will be either 36 + bytes (GUID) or 16 bytes (random data) in length, or provided by the + developer. Measured when the notification is being displayed through the + chrome.notifications.create() extension API. + </summary> +</histogram> + <histogram name="Notifications.ExtensionNotificationType" enum="ExtensionNotificationType"> <owner>dewittj@chromium.org</owner> @@ -56643,6 +56688,13 @@ </summary> </histogram> +<histogram name="Platform.Vpd.UnknownKeys"> + <owner>tnagel@chromium.org</owner> + <summary> + Number of unknown RW_VPD entries on Chrome OS, sent once per boot. + </summary> +</histogram> + <histogram name="Platform.WriteSectorsLong"> <owner>gwendal@google.com</owner> <summary> @@ -60537,6 +60589,14 @@ </summary> </histogram> +<histogram name="Printing.CUPS.IppAttributesSuccess" enum="BooleanSuccess"> + <owner>skau@chromium.org</owner> + <summary> + Record if the request for IPP attributes was successful during printer + setup. This only occurs for setup attempts of IPP and IPPS printers. + </summary> +</histogram> + <histogram name="Printing.CUPS.JobResult" enum="PrintJobResult"> <owner>skau@chromium.org</owner> <summary> @@ -80265,6 +80325,16 @@ </summary> </histogram> +<histogram name="TabManager.Heuristics.FromBackgroundedToFirstTitleUpdated" + units="ms"> + <owner>chrisha@chromium.org</owner> + <owner>lpy@chromium.org</owner> + <summary> + Measures the time duration from when the tab is backgrounded to when its + title is updated. Only recorded when the tab is in the background. + </summary> +</histogram> + <histogram name="TabManager.SessionRestore.CompressedPagesPerSecond" units="pages/s"> <owner>fmeawad@chromium.org</owner>
diff --git a/tools/perf/benchmarks/benchmark_smoke_unittest.py b/tools/perf/benchmarks/benchmark_smoke_unittest.py index 71cd4889..edbe89a 100644 --- a/tools/perf/benchmarks/benchmark_smoke_unittest.py +++ b/tools/perf/benchmarks/benchmark_smoke_unittest.py
@@ -47,6 +47,7 @@ # disable it in tools/perf/benchmarks/*. @benchmark_module.Disabled('chromeos') # crbug.com/351114 @benchmark_module.Disabled('android') # crbug.com/641934 + @benchmark_module.Disabled('all') # crbug.com/753542 def BenchmarkSmokeTest(self): # Only measure a single page so that this test cycles reasonably quickly. benchmark.options['pageset_repeat'] = 1
diff --git a/tools/perf/benchmarks/memory.py b/tools/perf/benchmarks/memory.py index 7adf60e..5722153 100644 --- a/tools/perf/benchmarks/memory.py +++ b/tools/perf/benchmarks/memory.py
@@ -21,6 +21,49 @@ r'(?<!dump)(?<!process)_(std|count|max|min|sum|pct_\d{4}(_\d+)?)$') +def CreateCoreTimelineBasedMemoryMeasurementOptions(): + """Creates necessary TBM options for measuring memory usage. + + Separated out so that code can be re-used in other benchmarks. + """ + # Enable only memory-infra, to get memory dumps, and blink.console, to get + # the timeline markers used for mapping threads to tabs. + trace_memory = chrome_trace_category_filter.ChromeTraceCategoryFilter( + filter_string='-*,blink.console,disabled-by-default-memory-infra') + tbm_options = timeline_based_measurement.Options( + overhead_level=trace_memory) + tbm_options.config.enable_android_graphics_memtrack = True + tbm_options.SetTimelineBasedMetrics(['memoryMetric']) + # Setting an empty memory dump config disables periodic dumps. + tbm_options.config.chrome_trace_config.SetMemoryDumpConfig( + chrome_trace_config.MemoryDumpConfig()) + return tbm_options + + +def SetExtraBrowserOptionsForMemoryMeasurement(options): + """Sets extra browser args necessary for measuring memory usage. + + Separated out so that code can be re-used in other benchmarks. + """ + # Just before we measure memory we flush the system caches + # unfortunately this doesn't immediately take effect, instead + # the next page run is effected. Due to this the first page run + # has anomalous results. This option causes us to flush caches + # each time before Chrome starts so we effect even the first page + # - avoiding the bug. + options.clear_sytem_cache_for_browser_and_profile_on_start = True + + +def DefaultValueCanBeAddedPredicateForMemoryMeasurement(value): + """Default predicate when measuring memory usage. + + Separated out so that code can be re-used in other benchmarks. + """ + # TODO(crbug.com/610962): Remove this stopgap when the perf dashboard + # is able to cope with the data load generated by TBMv2 metrics. + return not _IGNORED_STATS_RE.search(value.name) + + class _MemoryInfra(perf_benchmark.PerfBenchmark): """Base class for new-generation memory benchmarks based on memory-infra. @@ -29,27 +72,10 @@ """ def CreateCoreTimelineBasedMeasurementOptions(self): - # Enable only memory-infra, to get memory dumps, and blink.console, to get - # the timeline markers used for mapping threads to tabs. - trace_memory = chrome_trace_category_filter.ChromeTraceCategoryFilter( - filter_string='-*,blink.console,disabled-by-default-memory-infra') - tbm_options = timeline_based_measurement.Options( - overhead_level=trace_memory) - tbm_options.config.enable_android_graphics_memtrack = True - tbm_options.SetTimelineBasedMetrics(['memoryMetric']) - # Setting an empty memory dump config disables periodic dumps. - tbm_options.config.chrome_trace_config.SetMemoryDumpConfig( - chrome_trace_config.MemoryDumpConfig()) - return tbm_options + return CreateCoreTimelineBasedMemoryMeasurementOptions() def SetExtraBrowserOptions(self, options): - # Just before we measure memory we flush the system caches - # unfortunately this doesn't immediately take effect, instead - # the next page run is effected. Due to this the first page run - # has anomalous results. This option causes us to flush caches - # each time before Chrome starts so we effect even the first page - # - avoiding the bug. - options.clear_sytem_cache_for_browser_and_profile_on_start = True + SetExtraBrowserOptionsForMemoryMeasurement(options) @benchmark.Enabled('mac') @@ -77,9 +103,7 @@ @classmethod def ValueCanBeAddedPredicate(cls, value, is_first_result): - # TODO(crbug.com/610962): Remove this stopgap when the perf dashboard - # is able to cope with the data load generated by TBMv2 metrics. - return not _IGNORED_STATS_RE.search(value.name) + return DefaultValueCanBeAddedPredicateForMemoryMeasurement(value) def GetExpectations(self): class StoryExpectations(story.expectations.StoryExpectations): @@ -109,9 +133,7 @@ @classmethod def ValueCanBeAddedPredicate(cls, value, is_first_result): - # TODO(crbug.com/610962): Remove this stopgap when the perf dashboard - # is able to cope with the data load generated by TBMv2 metrics. - return not _IGNORED_STATS_RE.search(value.name) + return DefaultValueCanBeAddedPredicateForMemoryMeasurement(value) def GetExpectations(self): class StoryExpectations(story.expectations.StoryExpectations):
diff --git a/tools/perf/benchmarks/smoothness.py b/tools/perf/benchmarks/smoothness.py index fd404a7..9ef93ce4 100644 --- a/tools/perf/benchmarks/smoothness.py +++ b/tools/perf/benchmarks/smoothness.py
@@ -124,8 +124,6 @@ return StoryExpectations() -@benchmark.Disabled('android') # crbug.com/526901 -@benchmark.Disabled('linux') # crbug.com/715607 @benchmark.Owner(emails=['junov@chromium.org']) class SmoothnessToughCanvasCases(_Smoothness): """Measures frame rate and a variety of other statistics. @@ -157,8 +155,6 @@ return StoryExpectations() -@benchmark.Disabled('android') # crbug.com/373812 -@benchmark.Disabled('win-reference') # crbug.com/612810 @benchmark.Owner(emails=['kbr@chromium.org', 'zmo@chromium.org']) class SmoothnessToughWebGLCases(_Smoothness): page_set = page_sets.ToughWebglCasesPageSet @@ -431,14 +427,6 @@ def Name(cls): return 'smoothness.tough_pinch_zoom_cases' - @classmethod - def ShouldDisable(cls, possible_browser): - return ( - # http://crbug.com/564008 - cls.IsSvelte(possible_browser) or - # http://crbug.com/630701 - possible_browser.platform.GetDeviceTypeName() == 'Nexus 5X') - def GetExpectations(self): class StoryExpectations(story_module.expectations.StoryExpectations): def SetExpectations(self): @@ -485,10 +473,6 @@ def Name(cls): return 'smoothness.gpu_rasterization.tough_pinch_zoom_cases' - @classmethod - def ShouldDisable(cls, possible_browser): - return cls.IsSvelte(possible_browser) # http://crbug.com/564008 - def GetExpectations(self): class StoryExpectations(story_module.expectations.StoryExpectations): def SetExpectations(self):
diff --git a/tools/perf/benchmarks/start_with_ext.py b/tools/perf/benchmarks/start_with_ext.py index ce326122..c251088 100644 --- a/tools/perf/benchmarks/start_with_ext.py +++ b/tools/perf/benchmarks/start_with_ext.py
@@ -31,6 +31,8 @@ @benchmark.Enabled('has tabs') +@benchmark.Disabled('mac') # crbug.com/563424 +@benchmark.Disabled('win', 'linux', 'reference', 'android') class StartWithExtCold(_StartWithExt): """Measure time to start Chrome cold with extensions.""" options = {'pageset_repeat': 5} @@ -48,6 +50,8 @@ @benchmark.Enabled('has tabs') +@benchmark.Disabled('mac') # crbug.com/563424 +@benchmark.Disabled('win', 'linux', 'reference', 'android') class StartWithExtWarm(_StartWithExt): """Measure time to start Chrome warm with extensions.""" options = {'pageset_repeat': 20}
diff --git a/tools/perf/contrib/vr_benchmarks/BUILD.gn b/tools/perf/contrib/vr_benchmarks/BUILD.gn index 065e2d3..c387908 100644 --- a/tools/perf/contrib/vr_benchmarks/BUILD.gn +++ b/tools/perf/contrib/vr_benchmarks/BUILD.gn
@@ -10,9 +10,11 @@ "./__init__.py", "./run_benchmark", "./vr_config.py", - "benchmarks/", + "./vr_benchmarks/", + "./vr_page_sets/", "//chrome/android/shared_preference_files/test/", "//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk", + "//chrome/test/data/vr/webvr_info/samples/", ] data_deps = [ "//chrome/android:vr_nfc_simulator_apk",
diff --git a/tools/perf/contrib/vr_benchmarks/run_benchmark b/tools/perf/contrib/vr_benchmarks/run_benchmark index 9c2ea23..f7eacc1 100755 --- a/tools/perf/contrib/vr_benchmarks/run_benchmark +++ b/tools/perf/contrib/vr_benchmarks/run_benchmark
@@ -52,7 +52,7 @@ shared_preference_utils.ApplySharedPreferenceSettings(dev, preferences) # Start the benchmarks - return benchmark_runner.main(vr_config.Config(['benchmarks'])) + return benchmark_runner.main(vr_config.Config(['vr_benchmarks'])) if __name__ == '__main__':
diff --git a/tools/perf/contrib/vr_benchmarks/vr_benchmarks/__init__.py b/tools/perf/contrib/vr_benchmarks/vr_benchmarks/__init__.py new file mode 100644 index 0000000..bfbc1f3 --- /dev/null +++ b/tools/perf/contrib/vr_benchmarks/vr_benchmarks/__init__.py
@@ -0,0 +1,9 @@ +# 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. +import os +import sys + +pardir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +if pardir not in sys.path: + sys.path.append(pardir)
diff --git a/tools/perf/contrib/vr_benchmarks/vr_benchmarks/vr_memory.py b/tools/perf/contrib/vr_benchmarks/vr_benchmarks/vr_memory.py new file mode 100644 index 0000000..5b03bb1b --- /dev/null +++ b/tools/perf/contrib/vr_benchmarks/vr_benchmarks/vr_memory.py
@@ -0,0 +1,34 @@ +# 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. +from benchmarks import memory +from core import perf_benchmark +from telemetry import benchmark +try: + from vr_page_sets import webvr_sample_pages +except ImportError: + # Make Pylint happy - doesn't think vr_page_sets can be imported + from contrib.vr_benchmarks.vr_page_sets import webvr_sample_pages + + +@benchmark.Owner(emails=['bsheedy@chromium.org', 'leilei@chromium.org']) +class WebVrMemorySamplePages(perf_benchmark.PerfBenchmark): + """Measures WebVR memory on an official sample page with settings tweaked.""" + + def CreateCoreTimelineBasedMeasurementOptions(self): + return memory.CreateCoreTimelineBasedMemoryMeasurementOptions() + + def CreateStorySet(self, options): + return webvr_sample_pages.WebVrSamplePageSet() + + def SetExtraBrowserOptions(self, options): + memory.SetExtraBrowserOptionsForMemoryMeasurement(options) + options.AppendExtraBrowserArgs(['--enable-webvr',]) + + @classmethod + def Name(cls): + return 'vr_memory.webvr_sample_pages' + + @classmethod + def ValueCanBeAddedPredicate(cls, value, is_first_result): + return memory.DefaultValueCanBeAddedPredicateForMemoryMeasurement(value)
diff --git a/tools/perf/contrib/vr_benchmarks/vr_config.py b/tools/perf/contrib/vr_benchmarks/vr_config.py index 36fdf5e1..fb841d8 100644 --- a/tools/perf/contrib/vr_benchmarks/vr_config.py +++ b/tools/perf/contrib/vr_benchmarks/vr_config.py
@@ -6,7 +6,10 @@ import sys # Add //tools/perf/ to system path -sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..')) +tools_perf_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), + '..', '..')) +if tools_perf_dir not in sys.path: + sys.path.append(tools_perf_dir) from chrome_telemetry_build import chromium_config from core import path_util
diff --git a/tools/perf/contrib/vr_benchmarks/vr_page_sets/__init__.py b/tools/perf/contrib/vr_benchmarks/vr_page_sets/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tools/perf/contrib/vr_benchmarks/vr_page_sets/__init__.py
diff --git a/tools/perf/contrib/vr_benchmarks/vr_page_sets/webvr_sample_pages.py b/tools/perf/contrib/vr_benchmarks/vr_page_sets/webvr_sample_pages.py new file mode 100644 index 0000000..8d00a63a --- /dev/null +++ b/tools/perf/contrib/vr_benchmarks/vr_page_sets/webvr_sample_pages.py
@@ -0,0 +1,53 @@ +# 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. +from telemetry.page import page as page_module +from telemetry import story + +import os + + +SAMPLE_DIR = os.path.join(os.path.dirname(__file__), + '..', '..', '..', '..', '..', + 'chrome', 'test', 'data', 'vr', + 'webvr_info', 'samples') + + +class WebVrSamplePage(page_module.Page): + def __init__(self, get_parameters, page_set): + url = 'test-slow-render.html' + if get_parameters: + url += '?' + '&'.join(get_parameters) + name = url.replace('.html', '') + url = 'file://' + os.path.join(SAMPLE_DIR, url) + super(WebVrSamplePage, self).__init__(url=url, page_set=page_set, + name=name) + + def RunPageInteractions(self, action_runner): + action_runner.TapElement(selector='canvas[id="webgl-canvas"]') + action_runner.MeasureMemory(True) + + +class WebVrSamplePageSet(story.StorySet): + """A page set using the official WebVR sample with settings tweaked.""" + + def __init__(self): + super(WebVrSamplePageSet, self).__init__() + # Standard sample app with no changes + self.AddStory(WebVrSamplePage(['canvasClickPresents=1', + 'renderScale=1'], self)) + # Increased render scale + self.AddStory(WebVrSamplePage(['canvasClickPresents=1', + 'renderScale=1.5'], self)) + # Default render scale, increased load + self.AddStory(WebVrSamplePage(['canvasClickPresents=1', + 'renderScale=1', + 'heavyGpu=1', + 'cubeScale=0.2', + 'workTime=5'], self)) + # Further increased load + self.AddStory(WebVrSamplePage(['canvasClickPresents=1', + 'renderScale=1', + 'heavyGpu=1', + 'cubeScale=0.3', + 'workTime=10'], self))
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index 90aba5a..f79aabd6 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -589,7 +589,7 @@ # Always say this is true regardless of whether the tester # supports swarming. It doesn't hurt. 'can_use_on_swarming_builders': True, - 'expiration': 10 * 60 * 60, # 10 hour timeout for now (crbug.com/699312) + 'expiration': 20 * 60 * 60, # 20 hour timeout for now (crbug.com/753367) 'hard_timeout': swarming_timeout if swarming_timeout else 10800, # 3 hours 'ignore_task_failure': ignore_task_failure, 'io_timeout': 3600,
diff --git a/tools/perf/core/perf_data_generator_unittest.py b/tools/perf/core/perf_data_generator_unittest.py index f542e66..0056acb 100644 --- a/tools/perf/core/perf_data_generator_unittest.py +++ b/tools/perf/core/perf_data_generator_unittest.py
@@ -92,7 +92,7 @@ 'dimension_sets': [{'os': 'SkyNet', 'id': 'T-850', 'pool': 'T-RIP'}], 'hard_timeout': 10800, 'can_use_on_swarming_builders': True, - 'expiration': 36000, + 'expiration': 72000, 'io_timeout': 3600, 'upload_test_results': False, }, @@ -115,7 +115,7 @@ 'dimension_sets': [{'os': 'SkyNet', 'id': 'T-850', 'pool': 'T-RIP'}], 'hard_timeout': 10800, 'can_use_on_swarming_builders': True, - 'expiration': 36000, + 'expiration': 72000, 'io_timeout': 3600, 'upload_test_results': False, }, @@ -164,7 +164,7 @@ 'dimension_sets': [{'os': 'SkyNet', 'id': 'T-850', 'pool': 'T-RIP'}], 'hard_timeout': 10800, 'can_use_on_swarming_builders': True, - 'expiration': 36000, + 'expiration': 72000, 'io_timeout': 3600, 'upload_test_results': True, },
diff --git a/ui/accessibility/ax_enums.idl b/ui/accessibility/ax_enums.idl index 3c201a96..35dd5183 100644 --- a/ui/accessibility/ax_enums.idl +++ b/ui/accessibility/ax_enums.idl
@@ -466,6 +466,9 @@ [cpp_enum_prefix_override="ax_attr"] enum AXBoolAttribute { // Generic busy state, does not have to be on a live region. busy, + // The object is at the root of an editable field, such as a content + // editable. + editable_root, // Live region attributes. container_live_atomic,
diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc index 9bbaa187..63181ae 100644 --- a/ui/accessibility/ax_node_data.cc +++ b/ui/accessibility/ax_node_data.cc
@@ -909,6 +909,9 @@ for (size_t i = 0; i < bool_attributes.size(); ++i) { std::string value = bool_attributes[i].second ? "true" : "false"; switch (bool_attributes[i].first) { + case AX_ATTR_EDITABLE_ROOT: + result += " editable_root=" + value; + break; case AX_ATTR_LIVE_ATOMIC: result += " atomic=" + value; break;
diff --git a/ui/accessibility/ax_node_position_unittest.cc b/ui/accessibility/ax_node_position_unittest.cc index c6641e0b..6fdbe6d 100644 --- a/ui/accessibility/ax_node_position_unittest.cc +++ b/ui/accessibility/ax_node_position_unittest.cc
@@ -419,10 +419,18 @@ ASSERT_NE(nullptr, text_position); EXPECT_TRUE(text_position->AtEndOfLine()); + // A "before text" position anchored at the line break should visually be the + // same as a text position at the end of the previous line. text_position = AXNodePosition::CreateTextPosition( tree_.data().tree_id, line_break_.id, 0 /* text_offset */, AX_TEXT_AFFINITY_DOWNSTREAM); ASSERT_NE(nullptr, text_position); + EXPECT_TRUE(text_position->AtEndOfLine()); + + text_position = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, line_break_.id, 1 /* text_offset */, + AX_TEXT_AFFINITY_DOWNSTREAM); + ASSERT_NE(nullptr, text_position); EXPECT_FALSE(text_position->AtEndOfLine()); text_position = AXNodePosition::CreateTextPosition( @@ -1142,10 +1150,12 @@ TEST_F(AXPositionTest, CreateNextAndPreviousCharacterPositionWithNullPosition) { TestPositionType null_position = AXNodePosition::CreateNullPosition(); ASSERT_NE(nullptr, null_position); - TestPositionType test_position = null_position->CreateNextCharacterPosition(); + TestPositionType test_position = null_position->CreateNextCharacterPosition( + AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsNullPosition()); - test_position = null_position->CreatePreviousCharacterPosition(); + test_position = null_position->CreatePreviousCharacterPosition( + AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsNullPosition()); } @@ -1155,7 +1165,8 @@ tree_.data().tree_id, inline_box1_.id, 4 /* text_offset */, AX_TEXT_AFFINITY_DOWNSTREAM); ASSERT_NE(nullptr, text_position); - TestPositionType test_position = text_position->CreateNextCharacterPosition(); + TestPositionType test_position = text_position->CreateNextCharacterPosition( + AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(inline_box1_.id, test_position->anchor_id()); @@ -1165,19 +1176,34 @@ tree_.data().tree_id, inline_box1_.id, 5 /* text_offset */, AX_TEXT_AFFINITY_DOWNSTREAM); ASSERT_NE(nullptr, text_position); - test_position = text_position->CreateNextCharacterPosition(); + test_position = text_position->CreateNextCharacterPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + EXPECT_NE(nullptr, test_position); + EXPECT_TRUE(test_position->IsTextPosition()); + EXPECT_EQ(inline_box1_.id, test_position->anchor_id()); + EXPECT_EQ(5, test_position->text_offset()); + test_position = text_position->CreateNextCharacterPosition( + AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(line_break_.id, test_position->anchor_id()); EXPECT_EQ(0, test_position->text_offset()); - test_position = test_position->CreateNextCharacterPosition(); + test_position = test_position->CreateNextCharacterPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + EXPECT_NE(nullptr, test_position); + EXPECT_TRUE(test_position->IsTextPosition()); + EXPECT_EQ(line_break_.id, test_position->anchor_id()); + EXPECT_EQ(0, test_position->text_offset()); + test_position = test_position->CreateNextCharacterPosition( + AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(inline_box2_.id, test_position->anchor_id()); EXPECT_EQ(0, test_position->text_offset()); - test_position = test_position->CreateNextCharacterPosition(); + test_position = test_position->CreateNextCharacterPosition( + AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(inline_box2_.id, test_position->anchor_id()); @@ -1187,7 +1213,14 @@ tree_.data().tree_id, check_box_.id, 9 /* text_offset */, AX_TEXT_AFFINITY_DOWNSTREAM); ASSERT_NE(nullptr, text_position); - test_position = text_position->CreateNextCharacterPosition(); + test_position = text_position->CreateNextCharacterPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + EXPECT_NE(nullptr, test_position); + EXPECT_TRUE(test_position->IsTextPosition()); + EXPECT_EQ(check_box_.id, test_position->anchor_id()); + EXPECT_EQ(9, test_position->text_offset()); + test_position = text_position->CreateNextCharacterPosition( + AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(inline_box1_.id, test_position->anchor_id()); @@ -1197,7 +1230,8 @@ tree_.data().tree_id, text_field_.id, 0 /* text_offset */, AX_TEXT_AFFINITY_UPSTREAM); ASSERT_NE(nullptr, text_position); - test_position = text_position->CreateNextCharacterPosition(); + test_position = text_position->CreateNextCharacterPosition( + AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(text_field_.id, test_position->anchor_id()); @@ -1212,7 +1246,8 @@ AX_TEXT_AFFINITY_DOWNSTREAM); ASSERT_NE(nullptr, text_position); TestPositionType test_position = - text_position->CreatePreviousCharacterPosition(); + text_position->CreatePreviousCharacterPosition( + AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(inline_box2_.id, test_position->anchor_id()); @@ -1222,19 +1257,34 @@ tree_.data().tree_id, inline_box2_.id, 0 /* text_offset */, AX_TEXT_AFFINITY_DOWNSTREAM); ASSERT_NE(nullptr, text_position); - test_position = text_position->CreatePreviousCharacterPosition(); + test_position = text_position->CreatePreviousCharacterPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + EXPECT_NE(nullptr, test_position); + EXPECT_TRUE(test_position->IsTextPosition()); + EXPECT_EQ(inline_box2_.id, test_position->anchor_id()); + EXPECT_EQ(0, test_position->text_offset()); + test_position = text_position->CreatePreviousCharacterPosition( + AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(line_break_.id, test_position->anchor_id()); EXPECT_EQ(0, test_position->text_offset()); - test_position = test_position->CreatePreviousCharacterPosition(); + test_position = test_position->CreatePreviousCharacterPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + EXPECT_NE(nullptr, test_position); + EXPECT_TRUE(test_position->IsTextPosition()); + EXPECT_EQ(line_break_.id, test_position->anchor_id()); + EXPECT_EQ(0, test_position->text_offset()); + test_position = test_position->CreatePreviousCharacterPosition( + AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(inline_box1_.id, test_position->anchor_id()); EXPECT_EQ(5, test_position->text_offset()); - test_position = test_position->CreatePreviousCharacterPosition(); + test_position = test_position->CreatePreviousCharacterPosition( + AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(inline_box1_.id, test_position->anchor_id()); @@ -1244,7 +1294,14 @@ tree_.data().tree_id, inline_box1_.id, 0 /* text_offset */, AX_TEXT_AFFINITY_DOWNSTREAM); ASSERT_NE(nullptr, text_position); - test_position = text_position->CreatePreviousCharacterPosition(); + test_position = text_position->CreatePreviousCharacterPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + EXPECT_NE(nullptr, test_position); + EXPECT_TRUE(test_position->IsTextPosition()); + EXPECT_EQ(inline_box1_.id, test_position->anchor_id()); + EXPECT_EQ(0, test_position->text_offset()); + test_position = text_position->CreatePreviousCharacterPosition( + AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(check_box_.id, test_position->anchor_id()); @@ -1254,21 +1311,25 @@ tree_.data().tree_id, text_field_.id, 1 /* text_offset */, AX_TEXT_AFFINITY_UPSTREAM); ASSERT_NE(nullptr, text_position); - test_position = text_position->CreatePreviousCharacterPosition(); + test_position = text_position->CreatePreviousCharacterPosition( + AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(text_field_.id, test_position->anchor_id()); EXPECT_EQ(0, test_position->text_offset()); + // Affinity should have been reset to downstream. EXPECT_EQ(AX_TEXT_AFFINITY_DOWNSTREAM, test_position->affinity()); } TEST_F(AXPositionTest, CreateNextAndPreviousWordStartPositionWithNullPosition) { TestPositionType null_position = AXNodePosition::CreateNullPosition(); ASSERT_NE(nullptr, null_position); - TestPositionType test_position = null_position->CreateNextWordStartPosition(); + TestPositionType test_position = null_position->CreateNextWordStartPosition( + AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsNullPosition()); - test_position = null_position->CreatePreviousWordStartPosition(); + test_position = null_position->CreatePreviousWordStartPosition( + AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsNullPosition()); } @@ -1276,10 +1337,12 @@ TEST_F(AXPositionTest, CreateNextAndPreviousWordEndPositionWithNullPosition) { TestPositionType null_position = AXNodePosition::CreateNullPosition(); ASSERT_NE(nullptr, null_position); - TestPositionType test_position = null_position->CreateNextWordEndPosition(); + TestPositionType test_position = null_position->CreateNextWordEndPosition( + AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsNullPosition()); - test_position = null_position->CreatePreviousWordEndPosition(); + test_position = null_position->CreatePreviousWordEndPosition( + AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsNullPosition()); } @@ -1488,11 +1551,12 @@ // INSTANTIATE_TEST_CASE_P( - CreateNextWordStartPosition, + CreateNextWordStartPositionWithBoundaryBehaviorCrossBoundary, AXPositionTestWithParam, testing::Values( TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreateNextWordStartPosition(); + return position->CreateNextWordStartPosition( + AXBoundaryBehavior::CrossBoundary); }), ROOT_ID, 0 /* text_offset */, @@ -1516,7 +1580,8 @@ "1\nLine <2>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreateNextWordStartPosition(); + return position->CreateNextWordStartPosition( + AXBoundaryBehavior::CrossBoundary); }), TEXT_FIELD_ID, 0 /* text_offset */, @@ -1528,7 +1593,8 @@ "affinity=downstream annotated_text=Line 1\nLine <2>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreateNextWordStartPosition(); + return position->CreateNextWordStartPosition( + AXBoundaryBehavior::CrossBoundary); }), STATIC_TEXT1_ID, 1 /* text_offset */, @@ -1540,7 +1606,8 @@ "affinity=downstream annotated_text=Line <2>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreateNextWordStartPosition(); + return position->CreateNextWordStartPosition( + AXBoundaryBehavior::CrossBoundary); }), INLINE_BOX2_ID, 4 /* text_offset */, @@ -1549,11 +1616,125 @@ "NullPosition"}})); INSTANTIATE_TEST_CASE_P( - CreatePreviousWordStartPosition, + CreateNextWordStartPositionWithBoundaryBehaviorStopAtAnchorBoundary, AXPositionTestWithParam, testing::Values( TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreatePreviousWordStartPosition(); + return position->CreateNextWordStartPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + ROOT_ID, + 0 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=1 text_offset=6 " + "affinity=downstream annotated_text=Button<C>heck boxLine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=12 " + "affinity=downstream annotated_text=ButtonCheck <b>oxLine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=15 " + "affinity=downstream annotated_text=ButtonCheck box<L>ine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=20 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "<1>\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=22 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\n<L>ine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=27 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\nLine <2>", + "TextPosition tree_id=0 anchor_id=1 text_offset=28 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\nLine 2<>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextWordStartPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + TEXT_FIELD_ID, + 0 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=4 text_offset=5 " + "affinity=downstream annotated_text=Line <1>\nLine 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=7 " + "affinity=downstream annotated_text=Line 1\n<L>ine 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=12 " + "affinity=downstream annotated_text=Line 1\nLine <2>", + "TextPosition tree_id=0 anchor_id=4 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextWordStartPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + STATIC_TEXT1_ID, + 1 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=5 text_offset=5 " + "affinity=downstream annotated_text=Line <1>", + "TextPosition tree_id=0 anchor_id=5 text_offset=6 " + "affinity=downstream annotated_text=Line 1<>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextWordStartPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + INLINE_BOX2_ID, + 4 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=9 text_offset=5 " + "affinity=downstream annotated_text=Line <2>", + "TextPosition tree_id=0 anchor_id=9 text_offset=6 " + "affinity=downstream annotated_text=Line 2<>"}})); + +INSTANTIATE_TEST_CASE_P( + CreateNextWordStartPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary, + AXPositionTestWithParam, + testing::Values( + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextWordStartPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + ROOT_ID, + 0 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=1 text_offset=0 " + "affinity=downstream annotated_text=<B>uttonCheck boxLine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=0 " + "affinity=downstream annotated_text=<B>uttonCheck boxLine " + "1\nLine 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextWordStartPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + TEXT_FIELD_ID, + 0 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=4 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextWordStartPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + STATIC_TEXT1_ID, + 1 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=5 text_offset=5 " + "affinity=downstream annotated_text=Line <1>", + "TextPosition tree_id=0 anchor_id=5 text_offset=5 " + "affinity=downstream annotated_text=Line <1>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextWordStartPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + INLINE_BOX2_ID, + 4 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=9 text_offset=5 " + "affinity=downstream annotated_text=Line <2>", + "TextPosition tree_id=0 anchor_id=9 text_offset=5 " + "affinity=downstream annotated_text=Line <2>"}})); + +INSTANTIATE_TEST_CASE_P( + CreatePreviousWordStartPositionWithBoundaryBehaviorCrossBoundary, + AXPositionTestWithParam, + testing::Values( + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousWordStartPosition( + AXBoundaryBehavior::CrossBoundary); }), ROOT_ID, 28 /* text_offset at end of root. */, @@ -1580,7 +1761,8 @@ "1\nLine 2", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreatePreviousWordStartPosition(); + return position->CreatePreviousWordStartPosition( + AXBoundaryBehavior::CrossBoundary); }), TEXT_FIELD_ID, 13 /* text_offset at end of text field */, @@ -1600,7 +1782,8 @@ "affinity=downstream annotated_text=<B>utton", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreatePreviousWordStartPosition(); + return position->CreatePreviousWordStartPosition( + AXBoundaryBehavior::CrossBoundary); }), STATIC_TEXT1_ID, 5 /* text_offset */, @@ -1614,7 +1797,8 @@ "affinity=downstream annotated_text=<B>utton", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreatePreviousWordStartPosition(); + return position->CreatePreviousWordStartPosition( + AXBoundaryBehavior::CrossBoundary); }), INLINE_BOX2_ID, 4 /* text_offset */, @@ -1633,11 +1817,128 @@ "NullPosition"}})); INSTANTIATE_TEST_CASE_P( - CreateNextWordEndPosition, + CreatePreviousWordStartPositionWithBoundaryBehaviorStopAtAnchorBoundary, AXPositionTestWithParam, testing::Values( TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreateNextWordEndPosition(); + return position->CreatePreviousWordStartPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + ROOT_ID, + 28 /* text_offset at end of root. */, + {"TextPosition tree_id=0 anchor_id=1 text_offset=27 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\nLine <2>", + "TextPosition tree_id=0 anchor_id=1 text_offset=22 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\n<L>ine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=20 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "<1>\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=15 " + "affinity=downstream annotated_text=ButtonCheck box<L>ine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=12 " + "affinity=downstream annotated_text=ButtonCheck <b>oxLine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=6 " + "affinity=downstream annotated_text=Button<C>heck boxLine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=0 " + "affinity=downstream annotated_text=<B>uttonCheck boxLine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=0 " + "affinity=downstream annotated_text=<B>uttonCheck boxLine " + "1\nLine 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousWordStartPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + TEXT_FIELD_ID, + 13 /* text_offset at end of text field */, + {"TextPosition tree_id=0 anchor_id=4 text_offset=12 " + "affinity=downstream annotated_text=Line 1\nLine <2>", + "TextPosition tree_id=0 anchor_id=4 text_offset=7 " + "affinity=downstream annotated_text=Line 1\n<L>ine 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=5 " + "affinity=downstream annotated_text=Line <1>\nLine 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousWordStartPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + STATIC_TEXT1_ID, + 5 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=5 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1", + "TextPosition tree_id=0 anchor_id=5 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousWordStartPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + INLINE_BOX2_ID, + 4 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=9 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 2", + "TextPosition tree_id=0 anchor_id=9 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 2"}})); + +INSTANTIATE_TEST_CASE_P( + CreatePreviousWordStartPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary, + AXPositionTestWithParam, + testing::Values( + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousWordStartPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + ROOT_ID, + 28 /* text_offset at end of root. */, + {"TextPosition tree_id=0 anchor_id=1 text_offset=27 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\nLine <2>", + "TextPosition tree_id=0 anchor_id=1 text_offset=27 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\nLine <2>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousWordStartPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + TEXT_FIELD_ID, + 13 /* text_offset at end of text field */, + {"TextPosition tree_id=0 anchor_id=4 text_offset=12 " + "affinity=downstream annotated_text=Line 1\nLine <2>", + "TextPosition tree_id=0 anchor_id=4 text_offset=12 " + "affinity=downstream annotated_text=Line 1\nLine <2>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousWordStartPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + STATIC_TEXT1_ID, + 5 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=5 text_offset=5 " + "affinity=downstream annotated_text=Line <1>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousWordStartPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + INLINE_BOX2_ID, + 4 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=9 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 2", + "TextPosition tree_id=0 anchor_id=9 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 2"}})); + +INSTANTIATE_TEST_CASE_P( + CreateNextWordEndPositionWithBoundaryBehaviorCrossBoundary, + AXPositionTestWithParam, + testing::Values( + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextWordEndPosition( + AXBoundaryBehavior::CrossBoundary); }), ROOT_ID, 0 /* text_offset */, @@ -1664,7 +1965,8 @@ "1\nLine 2<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreateNextWordEndPosition(); + return position->CreateNextWordEndPosition( + AXBoundaryBehavior::CrossBoundary); }), TEXT_FIELD_ID, 0 /* text_offset */, @@ -1678,7 +1980,8 @@ "affinity=downstream annotated_text=Line 1\nLine 2<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreateNextWordEndPosition(); + return position->CreateNextWordEndPosition( + AXBoundaryBehavior::CrossBoundary); }), STATIC_TEXT1_ID, 1 /* text_offset */, @@ -1692,7 +1995,8 @@ "affinity=downstream annotated_text=Line 2<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreateNextWordEndPosition(); + return position->CreateNextWordEndPosition( + AXBoundaryBehavior::CrossBoundary); }), INLINE_BOX2_ID, 4 /* text_offset */, @@ -1701,11 +2005,130 @@ "NullPosition"}})); INSTANTIATE_TEST_CASE_P( - CreatePreviousWordEndPosition, + CreateNextWordEndPositionWithBoundaryBehaviorStopAtAnchorBoundary, AXPositionTestWithParam, testing::Values( TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreatePreviousWordEndPosition(); + return position->CreateNextWordEndPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + ROOT_ID, + 0 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=1 text_offset=6 " + "affinity=downstream annotated_text=Button<C>heck boxLine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=11 " + "affinity=downstream annotated_text=ButtonCheck< >boxLine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=15 " + "affinity=downstream annotated_text=ButtonCheck box<L>ine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=19 " + "affinity=downstream annotated_text=ButtonCheck boxLine< " + ">1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=21 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1<\n>Line 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=26 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\nLine< >2", + "TextPosition tree_id=0 anchor_id=1 text_offset=28 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\nLine 2<>", + "TextPosition tree_id=0 anchor_id=1 text_offset=28 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\nLine 2<>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextWordEndPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + TEXT_FIELD_ID, + 0 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=4 text_offset=4 " + "affinity=downstream annotated_text=Line< >1\nLine 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=11 " + "affinity=downstream annotated_text=Line 1\nLine< >2", + "TextPosition tree_id=0 anchor_id=4 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>", + "TextPosition tree_id=0 anchor_id=4 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextWordEndPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + STATIC_TEXT1_ID, + 1 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=5 text_offset=4 " + "affinity=downstream annotated_text=Line< >1", + "TextPosition tree_id=0 anchor_id=5 text_offset=6 " + "affinity=downstream annotated_text=Line 1<>", + "TextPosition tree_id=0 anchor_id=5 text_offset=6 " + "affinity=downstream annotated_text=Line 1<>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextWordEndPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + INLINE_BOX2_ID, + 4 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=9 text_offset=6 " + "affinity=downstream annotated_text=Line 2<>", + "TextPosition tree_id=0 anchor_id=9 text_offset=6 " + "affinity=downstream annotated_text=Line 2<>"}})); + +INSTANTIATE_TEST_CASE_P( + CreateNextWordEndPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary, + AXPositionTestWithParam, + testing::Values( + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextWordEndPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + ROOT_ID, + 6 /* text_offset before "Check". */, + {"TextPosition tree_id=0 anchor_id=1 text_offset=11 " + "affinity=downstream annotated_text=ButtonCheck< >boxLine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=11 " + "affinity=downstream annotated_text=ButtonCheck< >boxLine " + "1\nLine 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextWordEndPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + TEXT_FIELD_ID, + 0 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=4 text_offset=4 " + "affinity=downstream annotated_text=Line< >1\nLine 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=4 " + "affinity=downstream annotated_text=Line< >1\nLine 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextWordEndPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + STATIC_TEXT1_ID, + 1 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=5 text_offset=4 " + "affinity=downstream annotated_text=Line< >1", + "TextPosition tree_id=0 anchor_id=5 text_offset=4 " + "affinity=downstream annotated_text=Line< >1"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextWordEndPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + INLINE_BOX2_ID, + 4 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=9 text_offset=4 " + "affinity=downstream annotated_text=Line< >2"}})); + +INSTANTIATE_TEST_CASE_P( + CreatePreviousWordEndPositionWithBoundaryBehaviorCrossBoundary, + AXPositionTestWithParam, + testing::Values( + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousWordEndPosition( + AXBoundaryBehavior::CrossBoundary); }), ROOT_ID, 28 /* text_offset at end of root. */, @@ -1729,7 +2152,8 @@ "1\nLine 2", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreatePreviousWordEndPosition(); + return position->CreatePreviousWordEndPosition( + AXBoundaryBehavior::CrossBoundary); }), TEXT_FIELD_ID, 13 /* text_offset at end of text field */, @@ -1747,7 +2171,8 @@ "affinity=downstream annotated_text=Button<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreatePreviousWordEndPosition(); + return position->CreatePreviousWordEndPosition( + AXBoundaryBehavior::CrossBoundary); }), STATIC_TEXT1_ID, 5 /* text_offset */, @@ -1761,7 +2186,8 @@ "affinity=downstream annotated_text=Button<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreatePreviousWordEndPosition(); + return position->CreatePreviousWordEndPosition( + AXBoundaryBehavior::CrossBoundary); }), INLINE_BOX2_ID, 4 /* text_offset */, @@ -1778,11 +2204,116 @@ "NullPosition"}})); INSTANTIATE_TEST_CASE_P( - CreateNextLineStartPosition, + CreatePreviousWordEndPositionWithBoundaryBehaviorStopAtAnchorBoundary, AXPositionTestWithParam, testing::Values( TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreateNextLineStartPosition(); + return position->CreatePreviousWordEndPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + ROOT_ID, + 28 /* text_offset at end of root. */, + {"TextPosition tree_id=0 anchor_id=1 text_offset=26 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\nLine< >2", + "TextPosition tree_id=0 anchor_id=1 text_offset=21 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1<\n>Line 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=19 " + "affinity=downstream annotated_text=ButtonCheck boxLine< " + ">1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=15 " + "affinity=downstream annotated_text=ButtonCheck box<L>ine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=11 " + "affinity=downstream annotated_text=ButtonCheck< >boxLine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=6 " + "affinity=downstream annotated_text=Button<C>heck boxLine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=0 " + "affinity=downstream annotated_text=<B>uttonCheck boxLine " + "1\nLine 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousWordEndPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + TEXT_FIELD_ID, + 13 /* text_offset at end of text field */, + {"TextPosition tree_id=0 anchor_id=4 text_offset=11 " + "affinity=downstream annotated_text=Line 1\nLine< >2", + "TextPosition tree_id=0 anchor_id=4 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=4 " + "affinity=downstream annotated_text=Line< >1\nLine 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousWordEndPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + STATIC_TEXT1_ID, + 5 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=5 text_offset=4 " + "affinity=downstream annotated_text=Line< >1", + "TextPosition tree_id=0 anchor_id=5 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousWordEndPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + INLINE_BOX2_ID, + 4 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=9 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 2"}})); + +INSTANTIATE_TEST_CASE_P( + CreatePreviousWordEndPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary, + AXPositionTestWithParam, + testing::Values( + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousWordEndPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + ROOT_ID, + 28 /* text_offset at end of root. */, + {"TextPosition tree_id=0 anchor_id=1 text_offset=28 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\nLine 2<>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousWordEndPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + TEXT_FIELD_ID, + 13 /* text_offset at end of text field */, + {"TextPosition tree_id=0 anchor_id=4 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousWordEndPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + STATIC_TEXT1_ID, + 5 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=5 text_offset=4 " + "affinity=downstream annotated_text=Line< >1", + "TextPosition tree_id=0 anchor_id=5 text_offset=4 " + "affinity=downstream annotated_text=Line< >1"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousWordEndPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + INLINE_BOX2_ID, + 4 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=9 text_offset=4 " + "affinity=downstream annotated_text=Line< >2"}})); + +INSTANTIATE_TEST_CASE_P( + CreateNextLineStartPositionWithBoundaryBehaviorCrossBoundary, + AXPositionTestWithParam, + testing::Values( + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextLineStartPosition( + AXBoundaryBehavior::CrossBoundary); }), ROOT_ID, 0 /* text_offset */, @@ -1794,7 +2325,8 @@ "1\n<L>ine 2", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreateNextLineStartPosition(); + return position->CreateNextLineStartPosition( + AXBoundaryBehavior::CrossBoundary); }), TEXT_FIELD_ID, 0 /* text_offset */, @@ -1802,7 +2334,8 @@ "affinity=downstream annotated_text=Line 1\n<L>ine 2", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreateNextLineStartPosition(); + return position->CreateNextLineStartPosition( + AXBoundaryBehavior::CrossBoundary); }), STATIC_TEXT1_ID, 1 /* text_offset */, @@ -1810,18 +2343,105 @@ "affinity=downstream annotated_text=<L>ine 2", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreateNextLineStartPosition(); + return position->CreateNextLineStartPosition( + AXBoundaryBehavior::CrossBoundary); }), INLINE_BOX2_ID, 4 /* text_offset */, {"NullPosition"}})); INSTANTIATE_TEST_CASE_P( - CreatePreviousLineStartPosition, + CreateNextLineStartPositionWithBoundaryBehaviorStopAtAnchorBoundary, AXPositionTestWithParam, testing::Values( TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreatePreviousLineStartPosition(); + return position->CreateNextLineStartPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + ROOT_ID, + 0 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=1 text_offset=15 " + "affinity=downstream annotated_text=ButtonCheck box<L>ine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=22 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\n<L>ine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=28 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\nLine 2<>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextLineStartPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + TEXT_FIELD_ID, + 0 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=4 text_offset=7 " + "affinity=downstream annotated_text=Line 1\n<L>ine 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextLineStartPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + STATIC_TEXT1_ID, + 1 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=5 text_offset=6 " + "affinity=downstream annotated_text=Line 1<>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextLineStartPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + INLINE_BOX2_ID, + 4 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=9 text_offset=6 " + "affinity=downstream annotated_text=Line 2<>"}})); + +INSTANTIATE_TEST_CASE_P( + CreateNextLineStartPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary, + AXPositionTestWithParam, + testing::Values( + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextLineStartPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + ROOT_ID, + 0 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=1 text_offset=0 " + "affinity=downstream annotated_text=<B>uttonCheck boxLine " + "1\nLine 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextLineStartPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + TEXT_FIELD_ID, + 0 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=4 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextLineStartPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + STATIC_TEXT1_ID, + 1 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=9 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 2", + "TextPosition tree_id=0 anchor_id=9 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextLineStartPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + INLINE_BOX2_ID, + 4 /* text_offset */, + {"NullPosition"}})); + +INSTANTIATE_TEST_CASE_P( + CreatePreviousLineStartPositionWithBoundaryBehaviorCrossBoundary, + AXPositionTestWithParam, + testing::Values( + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousLineStartPosition( + AXBoundaryBehavior::CrossBoundary); }), ROOT_ID, 28 /* text_offset at the end of root. */, @@ -1836,7 +2456,8 @@ "1\nLine 2", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreatePreviousLineStartPosition(); + return position->CreatePreviousLineStartPosition( + AXBoundaryBehavior::CrossBoundary); }), TEXT_FIELD_ID, 13 /* text_offset at end of text field */, @@ -1848,7 +2469,8 @@ "affinity=downstream annotated_text=<B>utton", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreatePreviousLineStartPosition(); + return position->CreatePreviousLineStartPosition( + AXBoundaryBehavior::CrossBoundary); }), STATIC_TEXT1_ID, 5 /* text_offset */, @@ -1858,7 +2480,8 @@ "affinity=downstream annotated_text=<B>utton", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreatePreviousLineStartPosition(); + return position->CreatePreviousLineStartPosition( + AXBoundaryBehavior::CrossBoundary); }), INLINE_BOX2_ID, 4 /* text_offset */, @@ -1871,11 +2494,114 @@ "NullPosition"}})); INSTANTIATE_TEST_CASE_P( - CreateNextLineEndPosition, + CreatePreviousLineStartPositionWithBoundaryBehaviorStopAtAnchorBoundary, AXPositionTestWithParam, testing::Values( TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreateNextLineEndPosition(); + return position->CreatePreviousLineStartPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + ROOT_ID, + 28 /* text_offset at the end of root. */, + {"TextPosition tree_id=0 anchor_id=1 text_offset=22 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\n<L>ine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=15 " + "affinity=downstream annotated_text=ButtonCheck box<L>ine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=0 " + "affinity=downstream annotated_text=<B>uttonCheck boxLine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=0 " + "affinity=downstream annotated_text=<B>uttonCheck boxLine " + "1\nLine 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousLineStartPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + TEXT_FIELD_ID, + 13 /* text_offset at end of text field */, + {"TextPosition tree_id=0 anchor_id=4 text_offset=7 " + "affinity=downstream annotated_text=Line 1\n<L>ine 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousLineStartPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + STATIC_TEXT1_ID, + 5 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=5 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1", + "TextPosition tree_id=0 anchor_id=5 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousLineStartPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + INLINE_BOX2_ID, + 4 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=9 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 2", + "TextPosition tree_id=0 anchor_id=9 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 2"}})); + +INSTANTIATE_TEST_CASE_P( + CreatePreviousLineStartPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary, + AXPositionTestWithParam, + testing::Values( + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousLineStartPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + ROOT_ID, + 28 /* text_offset at the end of root. */, + {"TextPosition tree_id=0 anchor_id=1 text_offset=22 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\n<L>ine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=22 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\n<L>ine 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousLineStartPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + TEXT_FIELD_ID, + 13 /* text_offset at end of text field */, + {"TextPosition tree_id=0 anchor_id=4 text_offset=7 " + "affinity=downstream annotated_text=Line 1\n<L>ine 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=7 " + "affinity=downstream annotated_text=Line 1\n<L>ine 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousLineStartPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + STATIC_TEXT1_ID, + 5 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=5 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1", + "TextPosition tree_id=0 anchor_id=5 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousLineStartPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + INLINE_BOX2_ID, + 4 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=9 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 2", + "TextPosition tree_id=0 anchor_id=9 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 2"}})); + +INSTANTIATE_TEST_CASE_P( + CreateNextLineEndPositionWithBoundaryBehaviorCrossBoundary, + AXPositionTestWithParam, + testing::Values( + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextLineEndPosition( + AXBoundaryBehavior::CrossBoundary); }), ROOT_ID, 0 /* text_offset */, @@ -1890,7 +2616,8 @@ "1\nLine 2<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreateNextLineEndPosition(); + return position->CreateNextLineEndPosition( + AXBoundaryBehavior::CrossBoundary); }), TEXT_FIELD_ID, 0 /* text_offset */, @@ -1900,7 +2627,8 @@ "affinity=downstream annotated_text=Line 1\nLine 2<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreateNextLineEndPosition(); + return position->CreateNextLineEndPosition( + AXBoundaryBehavior::CrossBoundary); }), STATIC_TEXT1_ID, 1 /* text_offset */, @@ -1910,7 +2638,8 @@ "affinity=downstream annotated_text=Line 2<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreateNextLineEndPosition(); + return position->CreateNextLineEndPosition( + AXBoundaryBehavior::CrossBoundary); }), INLINE_BOX2_ID, 4 /* text_offset */, @@ -1919,7 +2648,112 @@ "NullPosition"}})); INSTANTIATE_TEST_CASE_P( - CreatePreviousLineEndPosition, + CreateNextLineEndPositionWithBoundaryBehaviorStopAtAnchorBoundary, + AXPositionTestWithParam, + testing::Values( + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextLineEndPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + ROOT_ID, + 0 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=1 text_offset=15 " + "affinity=downstream annotated_text=ButtonCheck box<L>ine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=21 " + "affinity=downstream annotated_text=ButtonCheck boxLine 1" + "<\n>Line 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=28 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\nLine 2<>", + "TextPosition tree_id=0 anchor_id=1 text_offset=28 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1\nLine 2<>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextLineEndPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + TEXT_FIELD_ID, + 0 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=4 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>", + "TextPosition tree_id=0 anchor_id=4 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextLineEndPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + STATIC_TEXT1_ID, + 1 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=5 text_offset=6 " + "affinity=downstream annotated_text=Line 1<>", + "TextPosition tree_id=0 anchor_id=5 text_offset=6 " + "affinity=downstream annotated_text=Line 1<>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextLineEndPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + INLINE_BOX2_ID, + 4 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=9 text_offset=6 " + "affinity=downstream annotated_text=Line 2<>", + "TextPosition tree_id=0 anchor_id=9 text_offset=6 " + "affinity=downstream annotated_text=Line 2<>"}})); + +INSTANTIATE_TEST_CASE_P( + CreateNextLineEndPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary, + AXPositionTestWithParam, + testing::Values( + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextLineEndPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + ROOT_ID, + 0 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=1 text_offset=15 " + "affinity=downstream annotated_text=ButtonCheck box<L>ine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=21 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1<\n>Line 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=21 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1<\n>Line 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextLineEndPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + TEXT_FIELD_ID, + 0 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=4 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextLineEndPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + STATIC_TEXT1_ID, + 1 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=5 text_offset=6 " + "affinity=downstream annotated_text=Line 1<>", + "TextPosition tree_id=0 anchor_id=5 text_offset=6 " + "affinity=downstream annotated_text=Line 1<>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreateNextLineEndPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + INLINE_BOX2_ID, + 4 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=9 text_offset=6 " + "affinity=downstream annotated_text=Line 2<>", + "TextPosition tree_id=0 anchor_id=9 text_offset=6 " + "affinity=downstream annotated_text=Line 2<>"}})); + +INSTANTIATE_TEST_CASE_P( + CreatePreviousLineEndPositionWithBoundaryBehaviorCrossBoundary, AXPositionTestWithParam, testing::Values( // Note that for the first test, we can't go past the line ending at the @@ -1928,7 +2762,8 @@ // the beginning of the first line in the text field, and so an infinite // recursion will occur. TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreatePreviousLineEndPosition(); + return position->CreatePreviousLineEndPosition( + AXBoundaryBehavior::CrossBoundary); }), ROOT_ID, 28 /* text_offset at end of root. */, @@ -1939,7 +2774,8 @@ "affinity=downstream annotated_text=ButtonCheck box<L>ine " "1\nLine 2"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreatePreviousLineEndPosition(); + return position->CreatePreviousLineEndPosition( + AXBoundaryBehavior::CrossBoundary); }), TEXT_FIELD_ID, 13 /* text_offset at end of text field */, @@ -1949,7 +2785,8 @@ "affinity=downstream annotated_text=Check box<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreatePreviousLineEndPosition(); + return position->CreatePreviousLineEndPosition( + AXBoundaryBehavior::CrossBoundary); }), INLINE_BOX2_ID, 4 /* text_offset */, @@ -1959,7 +2796,8 @@ "affinity=downstream annotated_text=Check box<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { - return position->CreatePreviousLineEndPosition(); + return position->CreatePreviousLineEndPosition( + AXBoundaryBehavior::CrossBoundary); }), INLINE_BOX2_ID, 0 /* text_offset */, @@ -1969,6 +2807,104 @@ "affinity=downstream annotated_text=Check box<>", "NullPosition"}})); +INSTANTIATE_TEST_CASE_P( + CreatePreviousLineEndPositionWithBoundaryBehaviorStopAtAnchorBoundary, + AXPositionTestWithParam, + testing::Values( + // Note that for the first test, we can't go past the line ending at the + // check box to test for a position at start of anchor, because the tree + // position that is at the end of the check box is equivalent to the one + // that is at the beginning of the first line in the text field, and so + // an infinite recursion will occur. + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousLineEndPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + ROOT_ID, + 28 /* text_offset at end of root. */, + {"TextPosition tree_id=0 anchor_id=1 text_offset=21 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1<\n>Line 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=15 " + "affinity=downstream annotated_text=ButtonCheck box<L>ine " + "1\nLine 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=15 " + "affinity=downstream annotated_text=ButtonCheck box<L>ine " + "1\nLine 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousLineEndPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + TEXT_FIELD_ID, + 13 /* text_offset at end of text field */, + {"TextPosition tree_id=0 anchor_id=4 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousLineEndPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + INLINE_BOX2_ID, + 4 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=9 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousLineEndPosition( + AXBoundaryBehavior::StopAtAnchorBoundary); + }), + INLINE_BOX2_ID, + 0 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=9 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 2"}})); + +INSTANTIATE_TEST_CASE_P( + CreatePreviousLineEndPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary, + AXPositionTestWithParam, + testing::Values( + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousLineEndPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + ROOT_ID, + 27 /* text_offset one before the end of root. */, + {"TextPosition tree_id=0 anchor_id=1 text_offset=21 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1<\n>Line 2", + "TextPosition tree_id=0 anchor_id=1 text_offset=21 " + "affinity=downstream annotated_text=ButtonCheck boxLine " + "1<\n>Line 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousLineEndPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + TEXT_FIELD_ID, + 12 /* text_offset one before the end of text field */, + {"TextPosition tree_id=0 anchor_id=4 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2", + "TextPosition tree_id=0 anchor_id=4 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousLineEndPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + INLINE_BOX2_ID, + 4 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=6 text_offset=6 " + "affinity=downstream annotated_text=Line 1<>", + "TextPosition tree_id=0 anchor_id=6 text_offset=6 " + "affinity=downstream annotated_text=Line 1<>"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousLineEndPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), + INLINE_BOX2_ID, + 0 /* text_offset */, + {"TextPosition tree_id=0 anchor_id=6 text_offset=6 " + "affinity=downstream annotated_text=Line 1<>", + "TextPosition tree_id=0 anchor_id=6 text_offset=6 " + "affinity=downstream annotated_text=Line 1<>"}})); + // // Tests for |AXRange|. //
diff --git a/ui/accessibility/ax_position.h b/ui/accessibility/ax_position.h index 2c49e8d..9e70b25 100644 --- a/ui/accessibility/ax_position.h +++ b/ui/accessibility/ax_position.h
@@ -30,6 +30,15 @@ // a boundary has been reached. enum class AXPositionKind { NULL_POSITION, TREE_POSITION, TEXT_POSITION }; +// Defines how creating the next or previous position should behave whenever we +// are at or are crossing a boundary, such as at the start of an anchor, a word +// or a line. +enum class AXBoundaryBehavior { + CrossBoundary, + StopAtAnchorBoundary, + StopIfAlreadyAtBoundary +}; + // Forward declarations. template <class AXPositionType, class AXNodeType> class AXPosition; @@ -296,8 +305,15 @@ NOTREACHED(); return false; case AXPositionKind::TEXT_POSITION: - return !text_position->IsInLineBreak() && - GetNextOnLineID(text_position->anchor_id_) == + // Special case, when the caret is right before a line break and the + // previous position is not another line break. We should return |true| + // because visually the caret is at the end of the current line. + if (text_position->IsInLineBreak()) { + return text_position->AtStartOfAnchor() && + !text_position->CreatePreviousTextAnchorPosition() + ->IsInLineBreak(); + } + return GetNextOnLineID(text_position->anchor_id_) == INVALID_ANCHOR_ID && text_position->AtEndOfAnchor(); } @@ -571,14 +587,21 @@ return previous_leaf->AsTextPosition(); } - // The following methods work across anchors. - - AXPositionInstance CreateNextCharacterPosition() const { + AXPositionInstance CreateNextCharacterPosition( + AXBoundaryBehavior boundary_behavior) const { bool was_tree_position = IsTreePosition(); AXPositionInstance text_position = AsTextPosition(); if (text_position->IsNullPosition()) return text_position; + // Note that |BoundaryBehavior::StopIfAlreadyAtBoundary| doesn't make + // sense for character boundaries. + DCHECK_NE(boundary_behavior, AXBoundaryBehavior::StopIfAlreadyAtBoundary); + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary && + (text_position->text_offset_ + 1) >= text_position->MaxTextOffset()) { + return Clone(); + } + if ((text_position->text_offset_ + 1) < text_position->MaxTextOffset()) { text_position->text_offset_ += 1; // Even if our affinity was upstream, moving to the next character should @@ -597,7 +620,16 @@ return text_position; } - AXPositionInstance CreatePreviousCharacterPosition() const { + AXPositionInstance CreatePreviousCharacterPosition( + AXBoundaryBehavior boundary_behavior) const { + // Note that |BoundaryBehavior::StopIfAlreadyAtBoundary| doesn't make + // sense for character boundaries. + DCHECK_NE(boundary_behavior, AXBoundaryBehavior::StopIfAlreadyAtBoundary); + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary && + AtStartOfAnchor()) { + return Clone(); + } + bool was_tree_position = IsTreePosition(); AXPositionInstance text_position = AsTextPosition(); if (text_position->IsNullPosition()) @@ -620,11 +652,18 @@ return text_position; } - AXPositionInstance CreateNextWordStartPosition() const { + AXPositionInstance CreateNextWordStartPosition( + AXBoundaryBehavior boundary_behavior) const { bool was_tree_position = IsTreePosition(); AXPositionInstance text_position = AsLeafTextPosition(); if (text_position->IsNullPosition()) return text_position; + if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary && + text_position->AtStartOfWord()) { + AXPositionInstance clone = Clone(); + clone->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM; + return clone; + } const std::vector<int32_t> word_starts = text_position->GetWordStartOffsets(); @@ -638,8 +677,11 @@ } while (!text_position->IsNullPosition() && (!text_position->MaxTextOffset() || text_position->GetWordStartOffsets().empty())); - if (text_position->IsNullPosition()) + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtEndOfAnchor(); return text_position; + } const std::vector<int32_t> word_starts = text_position->GetWordStartOffsets(); @@ -656,24 +698,37 @@ // be in the shadow DOM if the original position was not. AXPositionInstance common_ancestor = text_position->LowestCommonAncestor(*this); - if (GetAnchor() == common_ancestor->GetAnchor()) + if (GetAnchor() == common_ancestor->GetAnchor()) { text_position = std::move(common_ancestor); + } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) { + return CreatePositionAtEndOfAnchor(); + } if (was_tree_position) text_position = text_position->AsTreePosition(); return text_position; } - AXPositionInstance CreatePreviousWordStartPosition() const { + AXPositionInstance CreatePreviousWordStartPosition( + AXBoundaryBehavior boundary_behavior) const { bool was_tree_position = IsTreePosition(); AXPositionInstance text_position = AsLeafTextPosition(); + if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary && + text_position->AtStartOfWord()) { + AXPositionInstance clone = Clone(); + clone->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM; + return clone; + } if (text_position->AtStartOfAnchor()) { text_position = text_position->CreatePreviousTextAnchorPosition(); text_position = text_position->CreatePositionAtEndOfAnchor(); } - if (text_position->IsNullPosition()) + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtStartOfAnchor(); return text_position; + } const std::vector<int32_t> word_starts = text_position->GetWordStartOffsets(); @@ -687,8 +742,11 @@ } while (!text_position->IsNullPosition() && (!text_position->MaxTextOffset() || text_position->GetWordStartOffsets().empty())); - if (text_position->IsNullPosition()) + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtStartOfAnchor(); return text_position; + } const std::vector<int32_t> word_starts = text_position->GetWordStartOffsets(); @@ -705,8 +763,11 @@ // be in the shadow DOM if the original position was not. AXPositionInstance common_ancestor = text_position->LowestCommonAncestor(*this); - if (GetAnchor() == common_ancestor->GetAnchor()) + if (GetAnchor() == common_ancestor->GetAnchor()) { text_position = std::move(common_ancestor); + } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) { + return CreatePositionAtStartOfAnchor(); + } if (was_tree_position) text_position = text_position->AsTreePosition(); @@ -714,14 +775,24 @@ } // Word end positions are one past the last character of the word. - AXPositionInstance CreateNextWordEndPosition() const { + AXPositionInstance CreateNextWordEndPosition( + AXBoundaryBehavior boundary_behavior) const { bool was_tree_position = IsTreePosition(); AXPositionInstance text_position = AsLeafTextPosition(); + if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary && + text_position->AtEndOfWord()) { + AXPositionInstance clone = Clone(); + clone->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM; + return clone; + } if (text_position->AtEndOfAnchor()) text_position = text_position->CreateNextTextAnchorPosition(); - if (text_position->IsNullPosition()) + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtEndOfAnchor(); return text_position; + } const std::vector<int32_t> word_ends = text_position->GetWordEndOffsets(); auto iterator = @@ -734,8 +805,11 @@ } while (!text_position->IsNullPosition() && (!text_position->MaxTextOffset() || text_position->GetWordEndOffsets().empty())); - if (text_position->IsNullPosition()) + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtEndOfAnchor(); return text_position; + } const std::vector<int32_t> word_ends = text_position->GetWordEndOffsets(); DCHECK(!word_ends.empty()); @@ -751,8 +825,11 @@ // be in the shadow DOM if the original position was not. AXPositionInstance common_ancestor = text_position->LowestCommonAncestor(*this); - if (GetAnchor() == common_ancestor->GetAnchor()) + if (GetAnchor() == common_ancestor->GetAnchor()) { text_position = std::move(common_ancestor); + } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) { + return CreatePositionAtEndOfAnchor(); + } if (was_tree_position) text_position = text_position->AsTreePosition(); @@ -760,16 +837,26 @@ } // Word end positions are one past the last character of the word. - AXPositionInstance CreatePreviousWordEndPosition() const { + AXPositionInstance CreatePreviousWordEndPosition( + AXBoundaryBehavior boundary_behavior) const { bool was_tree_position = IsTreePosition(); AXPositionInstance text_position = AsLeafTextPosition(); + if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary && + text_position->AtEndOfWord()) { + AXPositionInstance clone = Clone(); + clone->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM; + return clone; + } if (text_position->AtStartOfAnchor()) { text_position = text_position->CreatePreviousTextAnchorPosition(); text_position = text_position->CreatePositionAtEndOfAnchor(); } - if (text_position->IsNullPosition()) + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtStartOfAnchor(); return text_position; + } const std::vector<int32_t> word_ends = text_position->GetWordEndOffsets(); auto iterator = @@ -782,8 +869,11 @@ } while (!text_position->IsNullPosition() && (!text_position->MaxTextOffset() || text_position->GetWordStartOffsets().empty())); - if (text_position->IsNullPosition()) + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtStartOfAnchor(); return text_position; + } const std::vector<int32_t> word_ends = text_position->GetWordEndOffsets(); DCHECK(!word_ends.empty()); @@ -799,19 +889,29 @@ // be in the shadow DOM if the original position was not. AXPositionInstance common_ancestor = text_position->LowestCommonAncestor(*this); - if (GetAnchor() == common_ancestor->GetAnchor()) + if (GetAnchor() == common_ancestor->GetAnchor()) { text_position = std::move(common_ancestor); + } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) { + return CreatePositionAtStartOfAnchor(); + } if (was_tree_position) text_position = text_position->AsTreePosition(); return text_position; } - AXPositionInstance CreateNextLineStartPosition() const { + AXPositionInstance CreateNextLineStartPosition( + AXBoundaryBehavior boundary_behavior) const { bool was_tree_position = IsTreePosition(); AXPositionInstance text_position = AsLeafTextPosition(); if (text_position->IsNullPosition()) return text_position; + if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary && + text_position->AtStartOfLine()) { + AXPositionInstance clone = Clone(); + clone->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM; + return clone; + } // Find the next line break. int32_t next_on_line_id = text_position->anchor_id_; @@ -824,8 +924,11 @@ text_position->AsLeafTextPosition()->CreateNextTextAnchorPosition(); while (text_position->IsInLineBreak()) text_position = text_position->CreateNextTextAnchorPosition(); - if (text_position->IsNullPosition()) + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtEndOfAnchor(); return text_position; + } // If the line boundary is in the same subtree, return a position rooted at // the current position. @@ -833,21 +936,35 @@ // be in the shadow DOM if the original position was not. AXPositionInstance common_ancestor = text_position->LowestCommonAncestor(*this); - if (GetAnchor() == common_ancestor->GetAnchor()) + if (GetAnchor() == common_ancestor->GetAnchor()) { text_position = std::move(common_ancestor); + } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) { + return CreatePositionAtEndOfAnchor(); + } if (was_tree_position) text_position = text_position->AsTreePosition(); return text_position; } - AXPositionInstance CreatePreviousLineStartPosition() const { + AXPositionInstance CreatePreviousLineStartPosition( + AXBoundaryBehavior boundary_behavior) const { bool was_tree_position = IsTreePosition(); AXPositionInstance text_position = AsLeafTextPosition(); + if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary && + text_position->AtStartOfLine()) { + AXPositionInstance clone = Clone(); + clone->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM; + return clone; + } + if (text_position->IsInLineBreak() || text_position->AtStartOfAnchor()) text_position = text_position->CreatePreviousTextAnchorPosition(); - if (text_position->IsNullPosition()) + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtStartOfAnchor(); return text_position; + } int32_t previous_on_line_id = text_position->anchor_id_; while (GetPreviousOnLineID(previous_on_line_id) != INVALID_ANCHOR_ID) @@ -856,8 +973,11 @@ CreateTextPosition(tree_id_, previous_on_line_id, 0 /* text_offset */, AX_TEXT_AFFINITY_DOWNSTREAM); text_position = text_position->AsLeafTextPosition(); - if (text_position->IsNullPosition()) + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtStartOfAnchor(); return text_position; + } // If the line boundary is in the same subtree, return a position rooted at // the current position. @@ -865,8 +985,11 @@ // be in the shadow DOM if the original position was not. AXPositionInstance common_ancestor = text_position->LowestCommonAncestor(*this); - if (GetAnchor() == common_ancestor->GetAnchor()) + if (GetAnchor() == common_ancestor->GetAnchor()) { text_position = std::move(common_ancestor); + } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) { + return CreatePositionAtStartOfAnchor(); + } if (was_tree_position) text_position = text_position->AsTreePosition(); @@ -875,15 +998,26 @@ // Line end positions are one past the last character of the line, excluding // any newline characters. - AXPositionInstance CreateNextLineEndPosition() const { + AXPositionInstance CreateNextLineEndPosition( + AXBoundaryBehavior boundary_behavior) const { bool was_tree_position = IsTreePosition(); AXPositionInstance text_position = AsLeafTextPosition(); + if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary && + text_position->AtEndOfLine()) { + AXPositionInstance clone = Clone(); + clone->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM; + return clone; + } + // Skip forward to the next line if we are at the end of one. // Note that not all lines end with a hard line break. while (text_position->IsInLineBreak() || text_position->AtEndOfAnchor()) text_position = text_position->CreateNextTextAnchorPosition(); - if (text_position->IsNullPosition()) + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtEndOfAnchor(); return text_position; + } // Find the next line break. int32_t next_on_line_id = text_position->anchor_id_; @@ -895,8 +1029,11 @@ text_position = text_position->AsLeafTextPosition(); while (text_position->IsInLineBreak()) text_position = text_position->CreatePreviousTextAnchorPosition(); - if (text_position->IsNullPosition()) + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtEndOfAnchor(); return text_position; + } text_position = text_position->CreatePositionAtEndOfAnchor(); // If the line boundary is in the same subtree, return a position rooted at @@ -905,8 +1042,11 @@ // be in the shadow DOM if the original position was not. AXPositionInstance common_ancestor = text_position->LowestCommonAncestor(*this); - if (GetAnchor() == common_ancestor->GetAnchor()) + if (GetAnchor() == common_ancestor->GetAnchor()) { text_position = std::move(common_ancestor); + } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) { + return CreatePositionAtEndOfAnchor(); + } if (was_tree_position) text_position = text_position->AsTreePosition(); @@ -915,11 +1055,18 @@ // Line end positions are one past the last character of the line, excluding // any newline characters. - AXPositionInstance CreatePreviousLineEndPosition() const { + AXPositionInstance CreatePreviousLineEndPosition( + AXBoundaryBehavior boundary_behavior) const { bool was_tree_position = IsTreePosition(); AXPositionInstance text_position = AsLeafTextPosition(); if (text_position->IsNullPosition()) return text_position; + if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary && + text_position->AtEndOfLine()) { + AXPositionInstance clone = Clone(); + clone->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM; + return clone; + } int32_t previous_on_line_id = text_position->anchor_id_; while (GetPreviousOnLineID(previous_on_line_id) != INVALID_ANCHOR_ID) @@ -931,8 +1078,11 @@ text_position->AsLeafTextPosition()->CreatePreviousTextAnchorPosition(); while (text_position->IsInLineBreak()) text_position = text_position->CreatePreviousTextAnchorPosition(); - if (text_position->IsNullPosition()) + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtStartOfAnchor(); return text_position; + } text_position = text_position->CreatePositionAtEndOfAnchor(); // If the line boundary is in the same subtree, return a position rooted at @@ -941,8 +1091,11 @@ // be in the shadow DOM if the original position was not. AXPositionInstance common_ancestor = text_position->LowestCommonAncestor(*this); - if (GetAnchor() == common_ancestor->GetAnchor()) + if (GetAnchor() == common_ancestor->GetAnchor()) { text_position = std::move(common_ancestor); + } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) { + return CreatePositionAtStartOfAnchor(); + } if (was_tree_position) text_position = text_position->AsTreePosition();
diff --git a/ui/accessibility/platform/ax_platform_node_mac.h b/ui/accessibility/platform/ax_platform_node_mac.h index 73657fb..36ee003 100644 --- a/ui/accessibility/platform/ax_platform_node_mac.h +++ b/ui/accessibility/platform/ax_platform_node_mac.h
@@ -36,6 +36,10 @@ DISALLOW_COPY_AND_ASSIGN(AXPlatformNodeMac); }; +// Convenience function to determine whether an internal object role should +// expose its accessible name in AXValue (as opposed to AXTitle/AXDescription). +AX_EXPORT bool IsNameExposedInAXValueForRole(AXRole role); + } // namespace ui AX_EXPORT
diff --git a/ui/accessibility/platform/ax_platform_node_mac.mm b/ui/accessibility/platform/ax_platform_node_mac.mm index c2513cb..2c2bd33 100644 --- a/ui/accessibility/platform/ax_platform_node_mac.mm +++ b/ui/accessibility/platform/ax_platform_node_mac.mm
@@ -636,14 +636,13 @@ } - (id)AXValue { - switch (node_->GetData().role) { - case ui::AX_ROLE_TAB: - return [self AXSelected]; - case ui::AX_ROLE_STATIC_TEXT: - return [self AXTitle]; - default: - break; - } + ui::AXRole role = node_->GetData().role; + if (role == ui::AX_ROLE_TAB) + return [self AXSelected]; + + if (ui::IsNameExposedInAXValueForRole(role)) + return [self getStringAttribute:ui::AX_ATTR_NAME]; + return [self getStringAttribute:ui::AX_ATTR_VALUE]; } @@ -693,6 +692,9 @@ } - (NSString*)AXTitle { + if (ui::IsNameExposedInAXValueForRole(node_->GetData().role)) + return @""; + return [self getStringAttribute:ui::AX_ATTR_NAME]; } @@ -860,4 +862,16 @@ return -1; } +bool IsNameExposedInAXValueForRole(AXRole role) { + switch (role) { + case AX_ROLE_LIST_BOX_OPTION: + case AX_ROLE_LIST_MARKER: + case AX_ROLE_MENU_LIST_OPTION: + case AX_ROLE_STATIC_TEXT: + return true; + default: + return false; + } +} + } // namespace ui
diff --git a/ui/app_list/app_list_constants.cc b/ui/app_list/app_list_constants.cc index 6cf98b8e4..1b503f8 100644 --- a/ui/app_list/app_list_constants.cc +++ b/ui/app_list/app_list_constants.cc
@@ -133,7 +133,6 @@ // The padding around the outside of the search box (top and sides). const int kSearchBoxPadding = 16; const int kSearchBoxTopPadding = 24; -const int kSearchBoxBottomPadding = 21; // The background border corner radius of the search box in fullscreen mode. const int kSearchBoxBorderCornerRadiusFullscreen = 24;
diff --git a/ui/app_list/app_list_constants.h b/ui/app_list/app_list_constants.h index 0efc7bd..01ab81d 100644 --- a/ui/app_list/app_list_constants.h +++ b/ui/app_list/app_list_constants.h
@@ -99,7 +99,6 @@ APP_LIST_EXPORT extern const int kAppsGridLeftRightPaddingFullscreen; APP_LIST_EXPORT extern const int kSearchBoxPadding; APP_LIST_EXPORT extern const int kSearchBoxTopPadding; -APP_LIST_EXPORT extern const int kSearchBoxBottomPadding; APP_LIST_EXPORT extern const int kSearchBoxBorderCornerRadiusFullscreen; APP_LIST_EXPORT extern size_t kMaxFolderItems;
diff --git a/ui/app_list/app_list_view_delegate.h b/ui/app_list/app_list_view_delegate.h index 0746f9a7..2dce75d 100644 --- a/ui/app_list/app_list_view_delegate.h +++ b/ui/app_list/app_list_view_delegate.h
@@ -8,6 +8,7 @@ #include <vector> #include "base/time/time.h" +#include "third_party/skia/include/core/SkColor.h" #include "ui/app_list/app_list_export.h" namespace gfx { @@ -21,6 +22,7 @@ namespace app_list { class AppListModel; +class AppListViewDelegateObserver; class SearchResult; class SpeechUIModel; @@ -88,6 +90,13 @@ // Returns true if the delegate supports speech recognition. virtual bool IsSpeechRecognitionEnabled() = 0; + + // Gets the wallpaper prominent colors. + virtual void GetWallpaperProminentColors(std::vector<SkColor>* colors) = 0; + + // Add/remove observer for AppListViewDelegate. + virtual void AddObserver(AppListViewDelegateObserver* observer) = 0; + virtual void RemoveObserver(AppListViewDelegateObserver* observer) = 0; }; } // namespace app_list
diff --git a/ui/app_list/app_list_view_delegate_observer.h b/ui/app_list/app_list_view_delegate_observer.h new file mode 100644 index 0000000..032ccab --- /dev/null +++ b/ui/app_list/app_list_view_delegate_observer.h
@@ -0,0 +1,23 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_APP_LIST_APP_LIST_VIEW_DELEGATE_OBSERVER_H_ +#define UI_APP_LIST_APP_LIST_VIEW_DELEGATE_OBSERVER_H_ + +#include "ui/app_list/app_list_export.h" + +namespace app_list { + +class APP_LIST_EXPORT AppListViewDelegateObserver { + public: + // Invoked when wallpaper prominent colors are changed. + virtual void OnWallpaperColorsChanged() = 0; + + protected: + virtual ~AppListViewDelegateObserver() {} +}; + +} // namespace app_list + +#endif // UI_APP_LIST_APP_LIST_VIEW_DELEGATE_OBSERVER_H_
diff --git a/ui/app_list/search_box_model.cc b/ui/app_list/search_box_model.cc index 7527cfa..cf5f5d7 100644 --- a/ui/app_list/search_box_model.cc +++ b/ui/app_list/search_box_model.cc
@@ -84,16 +84,6 @@ observer.Update(); } -void SearchBoxModel::SetWallpaperProminentColors( - const std::vector<SkColor>& colors) { - if (wallpaper_prominent_colors_ == colors) - return; - - wallpaper_prominent_colors_ = colors; - for (auto& observer : observers_) - observer.WallpaperProminentColorsChanged(); -} - void SearchBoxModel::AddObserver(SearchBoxModelObserver* observer) { observers_.AddObserver(observer); }
diff --git a/ui/app_list/search_box_model.h b/ui/app_list/search_box_model.h index 36b27781..fe53744 100644 --- a/ui/app_list/search_box_model.h +++ b/ui/app_list/search_box_model.h
@@ -74,12 +74,6 @@ const base::string16& text() const { return text_; } bool is_voice_query() const { return is_voice_query_; } - // Sets/gets the wallpaper prominent colors. - void SetWallpaperProminentColors(const std::vector<SkColor>& colors); - const std::vector<SkColor>& wallpaper_prominent_colors() const { - return wallpaper_prominent_colors_; - } - void AddObserver(SearchBoxModelObserver* observer); void RemoveObserver(SearchBoxModelObserver* observer); @@ -90,7 +84,6 @@ gfx::SelectionModel selection_model_; base::string16 text_; bool is_voice_query_ = false; - std::vector<SkColor> wallpaper_prominent_colors_; base::ObserverList<SearchBoxModelObserver> observers_;
diff --git a/ui/app_list/search_box_model_observer.h b/ui/app_list/search_box_model_observer.h index 090f87a..9dfd2e8 100644 --- a/ui/app_list/search_box_model_observer.h +++ b/ui/app_list/search_box_model_observer.h
@@ -24,9 +24,6 @@ // Invoked when text or voice search flag is changed. virtual void Update() = 0; - // Invoked when wallpaper prominent colors are changed. - virtual void WallpaperProminentColorsChanged() = 0; - protected: virtual ~SearchBoxModelObserver() {} };
diff --git a/ui/app_list/test/app_list_test_view_delegate.h b/ui/app_list/test/app_list_test_view_delegate.h index c708dd3..f3efd07a 100644 --- a/ui/app_list/test/app_list_test_view_delegate.h +++ b/ui/app_list/test/app_list_test_view_delegate.h
@@ -73,6 +73,10 @@ void CustomLauncherPageAnimationChanged(double progress) override {} void CustomLauncherPagePopSubpage() override {} bool IsSpeechRecognitionEnabled() override; + void GetWallpaperProminentColors(std::vector<SkColor>* colors) override {} + void AddObserver(app_list::AppListViewDelegateObserver* observer) override {} + void RemoveObserver( + app_list::AppListViewDelegateObserver* observer) override {} // Do a bulk replacement of the items in the model. void ReplaceTestModel(int item_count); @@ -88,6 +92,7 @@ std::map<size_t, int> open_search_result_counts_; std::unique_ptr<AppListTestModel> model_; SpeechUIModel speech_ui_; + std::vector<SkColor> wallpaper_prominent_colors_; base::TimeDelta auto_launch_timeout_; DISALLOW_COPY_AND_ASSIGN(AppListTestViewDelegate);
diff --git a/ui/app_list/views/app_list_view.cc b/ui/app_list/views/app_list_view.cc index 0099119..1dfeb83 100644 --- a/ui/app_list/views/app_list_view.cc +++ b/ui/app_list/views/app_list_view.cc
@@ -12,6 +12,7 @@ #include "base/profiler/scoped_tracker.h" #include "base/strings/string_util.h" #include "build/build_config.h" +#include "components/wallpaper/wallpaper_color_profile.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" #include "ui/app_list/app_list_model.h" @@ -48,6 +49,8 @@ #include "ui/views/widget/widget.h" #include "ui/wm/core/shadow_types.h" +using wallpaper::ColorProfileType; + namespace app_list { namespace { @@ -189,12 +192,16 @@ CHECK(delegate); delegate_->GetSpeechUI()->AddObserver(this); - if (is_fullscreen_app_list_enabled_) + if (is_fullscreen_app_list_enabled_) { display_observer_.Add(display::Screen::GetScreen()); + delegate_->AddObserver(this); + } } AppListView::~AppListView() { delegate_->GetSpeechUI()->RemoveObserver(this); + if (is_fullscreen_app_list_enabled_) + delegate_->RemoveObserver(this); animation_observer_.reset(); // Remove child views first to ensure no remaining dependencies on delegate_. RemoveAllChildViews(true); @@ -223,8 +230,7 @@ if (is_fullscreen_app_list_enabled_) SetState(app_list_state_); - if (delegate_) - delegate_->ViewInitialized(); + delegate_->ViewInitialized(); UMA_HISTOGRAM_TIMES("Apps.AppListCreationTime", base::Time::Now() - start_time); @@ -345,8 +351,8 @@ // makes it transparent. app_list_background_shield_ = new views::View; app_list_background_shield_->SetPaintToLayer(ui::LAYER_SOLID_COLOR); - app_list_background_shield_->layer()->SetColor(SK_ColorBLACK); app_list_background_shield_->layer()->SetOpacity(kAppListOpacity); + SetBackgroundShieldColor(); if (features::IsBackgroundBlurEnabled()) { app_list_background_shield_->layer()->SetBackgroundBlur( kAppListBlurRadius); @@ -1115,4 +1121,35 @@ return coefficient * kAppListOpacity; } +void AppListView::GetWallpaperProminentColors(std::vector<SkColor>* colors) { + delegate_->GetWallpaperProminentColors(colors); +} + +void AppListView::OnWallpaperColorsChanged() { + SetBackgroundShieldColor(); +} + +void AppListView::SetBackgroundShieldColor() { + // There is a chance when AppListView::OnWallpaperColorsChanged called from + // AppListViewDelegate and the app_list_background_shield_ is not initialized. + if (!is_fullscreen_app_list_enabled_ && !app_list_background_shield_) + return; + + std::vector<SkColor> prominent_colors; + GetWallpaperProminentColors(&prominent_colors); + + if (prominent_colors.empty()) { + app_list_background_shield_->layer()->SetColor(kDefaultBackgroundColor); + } else { + DCHECK_EQ(static_cast<size_t>(ColorProfileType::NUM_OF_COLOR_PROFILES), + prominent_colors.size()); + + const SkColor dark_muted = + prominent_colors[static_cast<int>(ColorProfileType::DARK_MUTED)]; + const SkColor dark_muted_mixed = color_utils::AlphaBlend( + SK_ColorBLACK, dark_muted, kDarkMutedBlendAlpha); + app_list_background_shield_->layer()->SetColor(dark_muted_mixed); + } +} + } // namespace app_list
diff --git a/ui/app_list/views/app_list_view.h b/ui/app_list/views/app_list_view.h index f13eddc9..b052b497 100644 --- a/ui/app_list/views/app_list_view.h +++ b/ui/app_list/views/app_list_view.h
@@ -12,6 +12,7 @@ #include "base/scoped_observer.h" #include "build/build_config.h" #include "ui/app_list/app_list_export.h" +#include "ui/app_list/app_list_view_delegate_observer.h" #include "ui/app_list/speech_ui_model_observer.h" #include "ui/display/display_observer.h" #include "ui/views/bubble/bubble_dialog_delegate.h" @@ -39,7 +40,8 @@ // and hosts a AppsGridView and passes AppListModel to it for display. class APP_LIST_EXPORT AppListView : public views::BubbleDialogDelegateView, public SpeechUIModelObserver, - public display::DisplayObserver { + public display::DisplayObserver, + public AppListViewDelegateObserver { public: // The height/width of the shelf from the bottom/side of the screen. static constexpr int kShelfSize = 48; @@ -51,6 +53,12 @@ // The opacity of the app list background. static constexpr float kAppListOpacity = 0.8; + // The preferred blend alpha with wallpaper color for background. + static constexpr int kDarkMutedBlendAlpha = 0x7F; + + // The defualt color of the app list background. + static constexpr SkColor kDefaultBackgroundColor = SK_ColorBLACK; + enum AppListState { // Closes |app_list_main_view_| and dismisses the delegate. CLOSED = 0, @@ -230,6 +238,12 @@ // Gets app list background opacity during dragging. float GetAppListBackgroundOpacityDuringDragging(); + // Overridden from AppListViewDelegateObserver: + void OnWallpaperColorsChanged() override; + + void GetWallpaperProminentColors(std::vector<SkColor>* colors); + void SetBackgroundShieldColor(); + AppListViewDelegate* delegate_; // Weak. Owned by AppListService. AppListMainView* app_list_main_view_;
diff --git a/ui/app_list/views/apps_grid_view.cc b/ui/app_list/views/apps_grid_view.cc index 624a1f56..4302cfb 100644 --- a/ui/app_list/views/apps_grid_view.cc +++ b/ui/app_list/views/apps_grid_view.cc
@@ -69,9 +69,8 @@ constexpr int kTileLeftRightPadding = 10; constexpr int kTileBottomPadding = 6; constexpr int kTileTopPadding = 6; -constexpr int kTileLeftRightPaddingFullscreen = 12; -constexpr int kTileBottomPaddingFullscreen = 6; -constexpr int kTileTopPaddingFullscreen = 6; +constexpr int kTileHorizontalPadding = 12; +constexpr int kTileVerticalPadding = 6; // Width in pixels of the area on the sides that triggers a page flip. constexpr int kPageFlipZoneSize = 40; @@ -95,15 +94,17 @@ // UI. constexpr int kFolderDroppingCircleRadius = 39; -// Padding between suggested apps tiles and all apps indicator. -constexpr int kSuggestionsAllAppsIndicatorPadding = 28; +// Bottom padding for search box. +constexpr int kSearchBoxBottomPadding = 24; -// Extra padding needed between all apps indicator and all apps tiles on -// non-first page. -constexpr int kAllAppsIndicatorExtraPadding = 2; +// Padding between suggested apps tiles and all apps indicator. +constexpr int kSuggestionsAllAppsIndicatorPadding = 16; + +// Extra padding needed between all apps indicator and all apps tiles. +constexpr int kAllAppsIndicatorExtraPadding = 6; // The height of gradient fade-out zones. -constexpr int kFadeoutZoneHeight = 21; +constexpr int kFadeoutZoneHeight = 24; // Returns the size of a tile view excluding its padding. gfx::Size GetTileViewSize() { @@ -115,9 +116,8 @@ // Returns the padding around a tile view. gfx::Insets GetTilePadding() { if (features::IsFullscreenAppListEnabled()) { - return gfx::Insets( - -kTileTopPaddingFullscreen, -kTileLeftRightPaddingFullscreen, - -kTileBottomPaddingFullscreen, -kTileLeftRightPaddingFullscreen); + return gfx::Insets(-kTileVerticalPadding, -kTileHorizontalPadding, + -kTileVerticalPadding, -kTileHorizontalPadding); } return gfx::Insets(-kTileTopPadding, -kTileLeftRightPadding, @@ -290,14 +290,14 @@ layer()->SetFillsBoundsOpaquely(false); if (is_fullscreen_app_list_enabled_) { - suggested_apps_indicator_ = CreateIndicator(IDS_SUGGESTED_APPS_INDICATOR); - suggestions_container_ = new SuggestionsContainerView(contents_view_, nullptr); AddChildView(suggestions_container_); UpdateSuggestions(); - all_apps_indicator_ = CreateIndicator(IDS_ALL_APPS_INDICATOR); + all_apps_indicator_ = new IndicatorChipView( + l10n_util::GetStringUTF16(IDS_ALL_APPS_INDICATOR)); + AddChildView(all_apps_indicator_); } pagination_model_.SetTransitionDurations(kPageTransitionDurationInMs, @@ -776,9 +776,8 @@ if (!folder_delegate_) { gfx::Rect indicator_rect(rect); - LayoutSuggestedAppsIndicator(&indicator_rect); if (suggestions_container_) { - gfx::Rect suggestions_rect(indicator_rect); + gfx::Rect suggestions_rect(rect); suggestions_rect.set_height( suggestions_container_->GetHeightForWidth(suggestions_rect.width())); suggestions_rect.Offset((suggestions_rect.width() - kGridTileWidth) / 2 - @@ -934,14 +933,6 @@ SchedulePaint(); } -IndicatorChipView* AppsGridView::CreateIndicator( - int indicator_text_message_id) { - IndicatorChipView* indicator = new IndicatorChipView( - l10n_util::GetStringUTF16(indicator_text_message_id)); - AddChildView(indicator); - return indicator; -} - void AppsGridView::UpdateSuggestions() { if (!suggestions_container_) return; @@ -951,21 +942,6 @@ ->results()); } -void AppsGridView::LayoutSuggestedAppsIndicator(gfx::Rect* rect) { - if (!suggested_apps_indicator_) - return; - - DCHECK(rect); - gfx::Rect indicator_rect(*rect); - const gfx::Size indicator_size = - suggested_apps_indicator_->GetPreferredSize(); - indicator_rect.Inset((indicator_rect.width() - indicator_size.width()) / 2, - 0); - indicator_rect.Offset(CalculateTransitionOffset(0)); - suggested_apps_indicator_->SetBoundsRect(indicator_rect); - rect->Inset(0, suggested_apps_indicator_->GetPreferredSize().height(), 0, 0); -} - void AppsGridView::LayoutAllAppsIndicator(gfx::Rect* rect) { if (!all_apps_indicator_) return; @@ -975,11 +951,7 @@ const gfx::Size indicator_size = all_apps_indicator_->GetPreferredSize(); indicator_rect.Inset((indicator_rect.width() - indicator_size.width()) / 2, 0); - const gfx::Vector2d page_zero_offset = CalculateTransitionOffset(0); - const int y_offset_limit = -kSuggestionsAllAppsIndicatorPadding - - kGridTileHeight - indicator_size.height(); - indicator_rect.Offset(page_zero_offset.x(), - std::max(y_offset_limit, page_zero_offset.y())); + indicator_rect.Offset(CalculateTransitionOffset(0)); all_apps_indicator_->SetBoundsRect(indicator_rect); } @@ -1334,17 +1306,18 @@ // When transition is progressing, eliminate empty spaces between pages. if (is_fullscreen_app_list_enabled_ && transition.progress > 0) { const int current_page = pagination_model_.selected_page(); - const bool forward = transition.target_page > current_page ? false : true; - // When transiting to next page, eliminate empty space from just previous - // page since only the previous page is visiable; vice versa. - if (forward && view_index.page == current_page - 1) { + const bool forward = transition.target_page > current_page ? true : false; + // When transiting to previous page, eliminate empty space from just + // previous page since only the previous page is visiable; vice versa. + if (!forward && view_index.page == current_page - 1) { if (view_index.page == 0) { offset.set_y(offset.y() + GetHeightOnTopOfAllAppsTiles(0) - - GetHeightOnTopOfAllAppsTiles(1)); + GetHeightOnTopOfAllAppsTiles(1) - + 2 * kTileVerticalPadding); } else { offset.set_y(offset.y() + GetHeightOnTopOfAllAppsTiles(current_page)); } - } else if (!forward && view_index.page == current_page + 1) { + } else if (forward && view_index.page == current_page + 1) { offset.set_y(offset.y() - GetHeightOnTopOfAllAppsTiles(current_page)); } } @@ -1715,12 +1688,6 @@ work_area_bottom_ = work_area_bottom; is_end_gesture_ = is_end_gesture; - // Updates the opacity of suggested indicator. - gfx::Rect suggested_indicator_bounds = - suggested_apps_indicator_->GetLabelBoundsInScreen(); - UpdateOpacityOfItem(suggested_apps_indicator_, - suggested_indicator_bounds.CenterPoint().y()); - // Updates the opacity of suggestions container. gfx::Rect suggestions_container_bounds = suggestions_container_->GetBoundsInScreen(); @@ -2278,15 +2245,12 @@ if (page == 0) { return kSearchBoxBottomPadding + - suggested_apps_indicator_->GetPreferredSize().height() + suggestions_container_->GetPreferredSize().height() + kSuggestionsAllAppsIndicatorPadding + - all_apps_indicator_->GetPreferredSize().height() - - kTileTopPaddingFullscreen; + all_apps_indicator_->GetPreferredSize().height() + + kAllAppsIndicatorExtraPadding; } - return kSearchBoxBottomPadding + - all_apps_indicator_->GetPreferredSize().height() + - kAllAppsIndicatorExtraPadding; + return kSearchBoxBottomPadding - kTileVerticalPadding; } gfx::Rect AppsGridView::GetExpectedTileBounds(int slot) const {
diff --git a/ui/app_list/views/apps_grid_view.h b/ui/app_list/views/apps_grid_view.h index b33ad4c..37cb41f4 100644 --- a/ui/app_list/views/apps_grid_view.h +++ b/ui/app_list/views/apps_grid_view.h
@@ -257,14 +257,10 @@ int slot; // Which slot in the page an item view is in. }; - // Creates indicator based on the indicator text message id. - IndicatorChipView* CreateIndicator(int indicator_text_message_id); - // Updates suggestions from app list model. void UpdateSuggestions(); // Helper method for layouting indicator based on the given bounds |rect|. - void LayoutSuggestedAppsIndicator(gfx::Rect* rect); void LayoutAllAppsIndicator(gfx::Rect* rect); // Returns all apps tiles per page based on |page|. @@ -442,10 +438,7 @@ // slot if |point| is outside the page's bounds. Index GetNearestTileIndexForPoint(const gfx::Point& point) const; - // Gets height on top of the all apps tiles for |page|. For the first page, - // that includes suggested apps indicator, suggested apps tiles, all apps - // indicator views; For the non-first pages, that include all apps indicator - // view only. + // Gets height on top of the all apps tiles for |page|. int GetHeightOnTopOfAllAppsTiles(int page) const; // Gets the bounds of the tile located at |slot| on the current page. @@ -513,7 +506,6 @@ ContentsView* contents_view_ = nullptr; // Views below are owned by views hierarchy. - IndicatorChipView* suggested_apps_indicator_ = nullptr; SuggestionsContainerView* suggestions_container_ = nullptr; IndicatorChipView* all_apps_indicator_ = nullptr;
diff --git a/ui/app_list/views/search_box_view.cc b/ui/app_list/views/search_box_view.cc index 872b037..6cbddf10 100644 --- a/ui/app_list/views/search_box_view.cc +++ b/ui/app_list/views/search_box_view.cc
@@ -229,12 +229,16 @@ } view_delegate_->GetSpeechUI()->AddObserver(this); + if (is_fullscreen_app_list_enabled_) + view_delegate_->AddObserver(this); ModelChanged(); } SearchBoxView::~SearchBoxView() { view_delegate_->GetSpeechUI()->RemoveObserver(this); model_->search_box()->RemoveObserver(this); + if (is_fullscreen_app_list_enabled_) + view_delegate_->RemoveObserver(this); } void SearchBoxView::ModelChanged() { @@ -246,9 +250,10 @@ if (is_fullscreen_app_list_enabled_) UpdateSearchIcon(); model_->search_box()->AddObserver(this); + SpeechRecognitionButtonPropChanged(); HintTextChanged(); - WallpaperProminentColorsChanged(); + OnWallpaperColorsChanged(); } bool SearchBoxView::HasSearch() const { @@ -835,11 +840,12 @@ NotifyQueryChanged(); } -void SearchBoxView::WallpaperProminentColorsChanged() { +void SearchBoxView::OnWallpaperColorsChanged() { if (!is_fullscreen_app_list_enabled_) return; - const std::vector<SkColor> prominent_colors = GetWallpaperProminentColors(); + std::vector<SkColor> prominent_colors; + GetWallpaperProminentColors(&prominent_colors); if (prominent_colors.empty()) return; DCHECK_EQ(static_cast<size_t>(ColorProfileType::NUM_OF_COLOR_PROFILES), @@ -880,8 +886,8 @@ gfx::CreateVectorIcon(icon, kSearchIconSize, search_box_color_)); } -const std::vector<SkColor>& SearchBoxView::GetWallpaperProminentColors() const { - return model_->search_box()->wallpaper_prominent_colors(); +void SearchBoxView::GetWallpaperProminentColors(std::vector<SkColor>* colors) { + view_delegate_->GetWallpaperProminentColors(colors); } void SearchBoxView::SetBackgroundColor(SkColor light_vibrant) {
diff --git a/ui/app_list/views/search_box_view.h b/ui/app_list/views/search_box_view.h index 511e75a..25af2b31 100644 --- a/ui/app_list/views/search_box_view.h +++ b/ui/app_list/views/search_box_view.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_model.h" +#include "ui/app_list/app_list_view_delegate_observer.h" #include "ui/app_list/search_box_model_observer.h" #include "ui/app_list/speech_ui_model_observer.h" #include "ui/gfx/shadow_value.h" @@ -50,7 +51,8 @@ public views::TextfieldController, public views::ButtonListener, public SearchBoxModelObserver, - public SpeechUIModelObserver { + public SpeechUIModelObserver, + public AppListViewDelegateObserver { public: SearchBoxView(SearchBoxViewDelegate* delegate, AppListViewDelegate* view_delegate, @@ -158,8 +160,8 @@ // Updates the search icon. void UpdateSearchIcon(); - // Gets the wallpaper prominent colors, returning empty if there aren't any. - const std::vector<SkColor>& GetWallpaperProminentColors() const; + // Gets the wallpaper prominent colors. + void GetWallpaperProminentColors(std::vector<SkColor>* colors); // Sets the background color. void SetBackgroundColor(SkColor light_vibrant); @@ -189,12 +191,14 @@ void HintTextChanged() override; void SelectionModelChanged() override; void Update() override; - void WallpaperProminentColorsChanged() override; // Overridden from SpeechUIModelObserver: void OnSpeechRecognitionStateChanged( SpeechRecognitionState new_state) override; + // Overridden from AppListViewDelegateObserver: + void OnWallpaperColorsChanged() override; + void SetDefaultBorder(); bool selected() { return selected_; }
diff --git a/ui/app_list/views/search_result_page_view.cc b/ui/app_list/views/search_result_page_view.cc index 2f3c99c..0f4d9ad 100644 --- a/ui/app_list/views/search_result_page_view.cc +++ b/ui/app_list/views/search_result_page_view.cc
@@ -58,9 +58,6 @@ GetShadowForZHeight(kSearchResultZHeight))); content_view->SetBackground( views::CreateSolidBackground(kCardBackgroundColor)); - } else { - content_view->SetBackground( - views::CreateSolidBackground(kCardBackgroundColorFullscreen)); } SetLayoutManager(new views::FillLayout()); AddChildView(content_view); @@ -152,9 +149,11 @@ new views::BoxLayout(views::BoxLayout::kVertical, gfx::Insets(), 0)); // Hides this view behind the search box by using the same color and - // background border corner radius. + // background border corner radius. All child views' background should be + // set transparent so that the rounded corner is not overwritten. SetBackground(base::MakeUnique<SearchResultPageBackground>( - kSearchBoxBackgroundDefault, kSearchBoxBorderCornerRadiusFullscreen)); + kCardBackgroundColorFullscreen, + kSearchBoxBorderCornerRadiusFullscreen)); } else { gfx::ShadowValue shadow = GetShadowForZHeight(kSearchResultZHeight); std::unique_ptr<views::Border> border(new views::ShadowBorder(shadow));
diff --git a/ui/app_list/views/search_result_view.cc b/ui/app_list/views/search_result_view.cc index e7adcbf..ee34ac3 100644 --- a/ui/app_list/views/search_result_view.cc +++ b/ui/app_list/views/search_result_view.cc
@@ -328,9 +328,8 @@ const bool selected = list_view_->IsResultViewSelected(this); const bool hover = state() == STATE_HOVERED || state() == STATE_PRESSED; - canvas->FillRect(content_rect, is_fullscreen_app_list_enabled_ - ? kCardBackgroundColorFullscreen - : kCardBackgroundColor); + if (!is_fullscreen_app_list_enabled_) + canvas->FillRect(content_rect, kCardBackgroundColor); // Possibly call FillRect a second time (these colours are partially // transparent, so the previous FillRect is not redundant).
diff --git a/ui/app_list/views/start_page_view.cc b/ui/app_list/views/start_page_view.cc index 3ed30288..f982bb6 100644 --- a/ui/app_list/views/start_page_view.cc +++ b/ui/app_list/views/start_page_view.cc
@@ -25,7 +25,6 @@ #include "ui/app_list/views/contents_view.h" #include "ui/app_list/views/custom_launcher_page_view.h" #include "ui/app_list/views/expand_arrow_view.h" -#include "ui/app_list/views/indicator_chip_view.h" #include "ui/app_list/views/search_box_view.h" #include "ui/app_list/views/search_result_container_view.h" #include "ui/app_list/views/search_result_tile_item_view.h" @@ -48,6 +47,7 @@ // Layout constants. constexpr int kInstantContainerSpacing = 24; +constexpr int kSearchBoxBottomPadding = 12; constexpr int kSearchBoxAndTilesSpacing = 35; constexpr int kStartPageSearchBoxWidth = 480; constexpr int kStartPageSearchBoxWidthFullscreen = 544; @@ -57,7 +57,7 @@ constexpr int kWebViewWidth = 700; constexpr int kWebViewHeight = 224; -constexpr int kExpandArrowTopPadding = 28; +constexpr int kExpandArrowTopPadding = 29; constexpr int kLauncherPageBackgroundWidth = 400; } // namespace @@ -123,12 +123,6 @@ InitInstantContainer(); AddChildView(instant_container_); - if (is_fullscreen_app_list_enabled_) { - indicator_ = new IndicatorChipView( - l10n_util::GetStringUTF16(IDS_SUGGESTED_APPS_INDICATOR)); - AddChildView(indicator_); - } - // The view containing the start page tiles. AddChildView(suggestions_container_); if (is_fullscreen_app_list_enabled_) { @@ -257,17 +251,8 @@ bounds.set_height(instant_container_->GetHeightForWidth(bounds.width())); instant_container_->SetBoundsRect(bounds); - // For old launcher, tiles begin where the instant container ends; for - // fullscreen app list launcher, tiles begin where the |indicator_| ends. + // Tiles begin where the instant container ends. bounds.set_y(bounds.bottom()); - if (indicator_) { - gfx::Rect indicator_rect(bounds); - indicator_rect.Offset( - (indicator_rect.width() - indicator_->GetPreferredSize().width()) / 2, - 0); - indicator_->SetBoundsRect(indicator_rect); - bounds.Inset(0, indicator_->GetPreferredSize().height(), 0, 0); - } bounds.set_height(suggestions_container_->GetHeightForWidth(bounds.width())); if (is_fullscreen_app_list_enabled_) { bounds.Offset((bounds.width() - kGridTileWidth) / 2 - @@ -442,10 +427,6 @@ work_area_bottom_ = work_area_bottom; is_end_gesture_ = is_end_gesture; - // Updates opacity of suggested apps indicator. - gfx::Rect indicator_bounds = indicator_->GetLabelBoundsInScreen(); - UpdateOpacityOfItem(indicator_, indicator_bounds.CenterPoint().y()); - // Updates opacity of suggestions container. gfx::Rect suggestions_container_bounds = suggestions_container_->GetBoundsInScreen();
diff --git a/ui/app_list/views/start_page_view.h b/ui/app_list/views/start_page_view.h index f9ca276b..dec5711a 100644 --- a/ui/app_list/views/start_page_view.h +++ b/ui/app_list/views/start_page_view.h
@@ -20,7 +20,6 @@ class AppListViewDelegate; class CustomLauncherPageBackgroundView; class ExpandArrowView; -class IndicatorChipView; class SearchResultTileItemView; class SuggestionsContainerView; class TileItemView; @@ -96,7 +95,6 @@ views::View* instant_container_; // Owned by views hierarchy. CustomLauncherPageBackgroundView* custom_launcher_page_background_; // Owned by views hierarchy. - IndicatorChipView* indicator_ = nullptr; // Owned by views hierarchy. SuggestionsContainerView* suggestions_container_; // Owned by views hierarchy. ExpandArrowView* expand_arrow_view_ = nullptr; // Owned by views hierarchy.
diff --git a/ui/arc/notification/arc_notification_content_view.cc b/ui/arc/notification/arc_notification_content_view.cc index 6b0c5d1..af9d0aa 100644 --- a/ui/arc/notification/arc_notification_content_view.cc +++ b/ui/arc/notification/arc_notification_content_view.cc
@@ -61,7 +61,7 @@ // TODO(yoshiki): Use a better tigger (eg. focusing EditText on // notification) than clicking (crbug.com/697379). if (event->type() == ui::ET_MOUSE_PRESSED) - owner_->ActivateToast(); + owner_->Activate(); views::Widget* widget = owner_->GetWidget(); if (!widget) @@ -555,12 +555,18 @@ static_cast<ArcNotificationView*>(parent())->OnContentBlured(); } -void ArcNotificationContentView::ActivateToast() { - if (message_center::ToastContentsView::kViewClassName == - parent()->parent()->GetClassName()) { - static_cast<message_center::ToastContentsView*>(parent()->parent()) - ->ActivateToast(); +void ArcNotificationContentView::Activate() { + if (!GetWidget()) + return; + + // Make the widget active. + if (!GetWidget()->IsActive()) { + GetWidget()->widget_delegate()->set_can_activate(true); + GetWidget()->Activate(); } + + // Focus the surface window. + surface_->FocusSurfaceWindow(); } views::FocusTraversable* ArcNotificationContentView::GetFocusTraversable() {
diff --git a/ui/arc/notification/arc_notification_content_view.h b/ui/arc/notification/arc_notification_content_view.h index 2d9ef0ad..f6330766 100644 --- a/ui/arc/notification/arc_notification_content_view.h +++ b/ui/arc/notification/arc_notification_content_view.h
@@ -68,7 +68,7 @@ void UpdatePinnedState(); void UpdateSnapshot(); void AttachSurface(); - void ActivateToast(); + void Activate(); void UpdateAccessibleName(); // views::NativeViewHost
diff --git a/ui/arc/notification/arc_notification_surface.h b/ui/arc/notification/arc_notification_surface.h index 7f012d4..29fe3bc2 100644 --- a/ui/arc/notification/arc_notification_surface.h +++ b/ui/arc/notification/arc_notification_surface.h
@@ -52,6 +52,9 @@ // if it doesn't attach to any host. virtual views::NativeViewHost* GetAttachedHost() const = 0; + // Focuses the surface window manually. + virtual void FocusSurfaceWindow() = 0; + private: DISALLOW_COPY_AND_ASSIGN(ArcNotificationSurface); };
diff --git a/ui/arc/notification/arc_notification_surface_impl.cc b/ui/arc/notification/arc_notification_surface_impl.cc index cf72c2a..964de60 100644 --- a/ui/arc/notification/arc_notification_surface_impl.cc +++ b/ui/arc/notification/arc_notification_surface_impl.cc
@@ -8,16 +8,76 @@ #include "components/exo/notification_surface.h" #include "components/exo/surface.h" #include "ui/aura/window.h" +#include "ui/aura/window_delegate.h" +#include "ui/base/cursor/cursor.h" +#include "ui/base/hit_test.h" #include "ui/views/controls/native/native_view_host.h" +#include "ui/views/widget/widget.h" namespace arc { +namespace { + +class CustomWindowDelegate : public aura::WindowDelegate { + public: + explicit CustomWindowDelegate(exo::NotificationSurface* notification_surface) + : notification_surface_(notification_surface) {} + ~CustomWindowDelegate() override {} + + // Overridden from aura::WindowDelegate: + gfx::Size GetMinimumSize() const override { return gfx::Size(); } + gfx::Size GetMaximumSize() const override { return gfx::Size(); } + void OnBoundsChanged(const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) override {} + gfx::NativeCursor GetCursor(const gfx::Point& point) override { + return notification_surface_->GetCursor(point); + } + int GetNonClientComponent(const gfx::Point& point) const override { + return HTNOWHERE; + } + bool ShouldDescendIntoChildForEventHandling( + aura::Window* child, + const gfx::Point& location) override { + return true; + } + bool CanFocus() override { return true; } + void OnCaptureLost() override {} + void OnPaint(const ui::PaintContext& context) override {} + void OnDeviceScaleFactorChanged(float device_scale_factor) override {} + void OnWindowDestroying(aura::Window* window) override {} + void OnWindowDestroyed(aura::Window* window) override { delete this; } + void OnWindowTargetVisibilityChanged(bool visible) override {} + bool HasHitTestMask() const override { + return notification_surface_->HasHitTestMask(); + } + void GetHitTestMask(gfx::Path* mask) const override { + notification_surface_->GetHitTestMask(mask); + } + void OnKeyEvent(ui::KeyEvent* event) override { + // Propagates the key event upto the top-level views Widget so that we can + // trigger proper events in the views/ash level there. Event handling for + // Surfaces is done in a post event handler in keyboard.cc. + views::Widget* widget = views::Widget::GetTopLevelWidgetForNativeView( + notification_surface_->host_window()); + if (widget) + widget->OnKeyEvent(event); + } + + private: + exo::NotificationSurface* const notification_surface_; + + DISALLOW_COPY_AND_ASSIGN(CustomWindowDelegate); +}; + +} // namespace + // Handles notification surface role of a given surface. ArcNotificationSurfaceImpl::ArcNotificationSurfaceImpl( exo::NotificationSurface* surface) : surface_(surface) { DCHECK(surface); - native_view_ = base::MakeUnique<aura::Window>(nullptr); + native_view_ = + base::MakeUnique<aura::Window>(new CustomWindowDelegate(surface)); native_view_->SetType(aura::client::WINDOW_TYPE_CONTROL); native_view_->set_owned_by_parent(false); native_view_->Init(ui::LAYER_NOT_DRAWN); @@ -67,4 +127,15 @@ return surface_->notification_key(); } +void ArcNotificationSurfaceImpl::FocusSurfaceWindow() { + DCHECK(surface_->root_surface()); + DCHECK(surface_->root_surface()->window()); + + // Focus the surface window manually to handle key events for notification. + // Message center is unactivatable by default, but we make it activatable when + // user is about to use Direct Reply. In that case, we also need to focus the + // surface window manually to send events to Android. + return surface_->root_surface()->window()->Focus(); +} + } // namespace arc
diff --git a/ui/arc/notification/arc_notification_surface_impl.h b/ui/arc/notification/arc_notification_surface_impl.h index de9fd856..3714b07 100644 --- a/ui/arc/notification/arc_notification_surface_impl.h +++ b/ui/arc/notification/arc_notification_surface_impl.h
@@ -30,6 +30,7 @@ void Detach() override; bool IsAttached() const override; views::NativeViewHost* GetAttachedHost() const override; + void FocusSurfaceWindow() override; exo::NotificationSurface* surface() const { return surface_; }
diff --git a/ui/aura/mus/window_tree_client_unittest.cc b/ui/aura/mus/window_tree_client_unittest.cc index 55c1921..f4bfd95 100644 --- a/ui/aura/mus/window_tree_client_unittest.cc +++ b/ui/aura/mus/window_tree_client_unittest.cc
@@ -1878,7 +1878,7 @@ bool root_destroyed() const { return root_destroyed_; } // aura::WindowTreeHostObserver:: - void OnHostCloseRequested(const aura::WindowTreeHost* host) override { + void OnHostCloseRequested(aura::WindowTreeHost* host) override { root_destroyed_ = true; }
diff --git a/ui/aura/window_tree_host.cc b/ui/aura/window_tree_host.cc index 1e915d1f..dc6bcfd 100644 --- a/ui/aura/window_tree_host.cc +++ b/ui/aura/window_tree_host.cc
@@ -256,7 +256,8 @@ //window()->RemoveOrDestroyChildren(); } -void WindowTreeHost::CreateCompositor(const viz::FrameSinkId& frame_sink_id) { +void WindowTreeHost::CreateCompositor(const viz::FrameSinkId& frame_sink_id, + bool force_software_compositor) { DCHECK(Env::GetInstance()); ui::ContextFactory* context_factory = Env::GetInstance()->context_factory(); DCHECK(context_factory); @@ -272,7 +273,7 @@ : context_factory_private->AllocateFrameSinkId(), context_factory, context_factory_private, base::ThreadTaskRunnerHandle::Get(), enable_surface_synchronization, - ui::IsPixelCanvasRecordingEnabled())); + ui::IsPixelCanvasRecordingEnabled(), false, force_software_compositor)); if (!dispatcher()) { window()->Init(ui::LAYER_NOT_DRAWN); window()->set_host(this); @@ -282,6 +283,7 @@ } void WindowTreeHost::InitCompositor() { + DCHECK(!compositor_->root_layer()); display::Display display = display::Screen::GetScreen()->GetDisplayNearestWindow(window()); compositor_->SetScaleAndSize(display.device_scale_factor(),
diff --git a/ui/aura/window_tree_host.h b/ui/aura/window_tree_host.h index f0757f56..31301558 100644 --- a/ui/aura/window_tree_host.h +++ b/ui/aura/window_tree_host.h
@@ -195,7 +195,8 @@ // If frame_sink_id is not passed in, one will be grabbed from // ContextFactoryPrivate. void CreateCompositor( - const viz::FrameSinkId& frame_sink_id = viz::FrameSinkId()); + const viz::FrameSinkId& frame_sink_id = viz::FrameSinkId(), + bool force_software_compositor = false); void InitCompositor(); void OnAcceleratedWidgetAvailable();
diff --git a/ui/aura/window_tree_host_observer.h b/ui/aura/window_tree_host_observer.h index f5c112ad..e71455dc 100644 --- a/ui/aura/window_tree_host_observer.h +++ b/ui/aura/window_tree_host_observer.h
@@ -17,17 +17,17 @@ class AURA_EXPORT WindowTreeHostObserver { public: // Called when the host's client size has changed. - virtual void OnHostResized(const WindowTreeHost* host) {} + virtual void OnHostResized(WindowTreeHost* host) {} // Called when the host is moved on screen. - virtual void OnHostMovedInPixels(const WindowTreeHost* host, + virtual void OnHostMovedInPixels(WindowTreeHost* host, const gfx::Point& new_origin_in_pixels) {} // Called when the host is moved to a different workspace. - virtual void OnHostWorkspaceChanged(const WindowTreeHost* host) {} + virtual void OnHostWorkspaceChanged(WindowTreeHost* host) {} // Called when the native window system sends the host request to close. - virtual void OnHostCloseRequested(const WindowTreeHost* host) {} + virtual void OnHostCloseRequested(WindowTreeHost* host) {} protected: virtual ~WindowTreeHostObserver() {}
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index 951c062..f1e6c73b 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -583,10 +583,13 @@ ] deps += [ - "//ui/events/ozone:events_ozone_evdev", "//ui/events/ozone:events_ozone_layout", "//ui/ozone:ozone_base", ] + + if (!is_fuchsia) { + deps += [ "//ui/events/ozone:events_ozone_evdev" ] + } } if (!toolkit_views && !use_aura) {
diff --git a/ui/base/dragdrop/os_exchange_data_provider_factory.cc b/ui/base/dragdrop/os_exchange_data_provider_factory.cc index 962fd2c..4789d0f4 100644 --- a/ui/base/dragdrop/os_exchange_data_provider_factory.cc +++ b/ui/base/dragdrop/os_exchange_data_provider_factory.cc
@@ -5,6 +5,7 @@ #include "ui/base/dragdrop/os_exchange_data_provider_factory.h" #include "base/memory/ptr_util.h" +#include "build/build_config.h" #if defined(USE_X11) && !defined(OS_CHROMEOS) #include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h" @@ -48,6 +49,10 @@ return ui::BuildOSExchangeDataProviderMac(); #elif defined(OS_WIN) return base::MakeUnique<OSExchangeDataProviderWin>(); +#elif defined(OS_FUCHSIA) + // TODO(fuchsia): Implement this when UI support is added. (crbug.com/750934) + NOTIMPLEMENTED(); + return nullptr; #else #error "Unknown operating system" #endif
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index 3a64eaf4..262ac1f 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc
@@ -61,13 +61,15 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner, bool enable_surface_synchronization, bool enable_pixel_canvas, - bool external_begin_frames_enabled) + bool external_begin_frames_enabled, + bool force_software_compositor) : context_factory_(context_factory), context_factory_private_(context_factory_private), frame_sink_id_(frame_sink_id), task_runner_(task_runner), vsync_manager_(new CompositorVSyncManager()), external_begin_frames_enabled_(external_begin_frames_enabled), + force_software_compositor_(force_software_compositor), layer_animator_collection_(this), scheduled_timeout_(base::TimeTicks()), allow_locks_to_extend_timeout_(false),
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h index f70914f..6babbc1c 100644 --- a/ui/compositor/compositor.h +++ b/ui/compositor/compositor.h
@@ -195,7 +195,8 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner, bool enable_surface_synchronization, bool enable_pixel_canvas, - bool external_begin_frames_enabled = false); + bool external_begin_frames_enabled = false, + bool force_software_compositor = false); ~Compositor() override; ui::ContextFactory* context_factory() { return context_factory_; } @@ -321,6 +322,8 @@ // the compositor if the enable_external_begin_frames setting is true. void OnNeedsExternalBeginFrames(bool needs_begin_frames); + bool force_software_compositor() { return force_software_compositor_; } + // Returns the main thread task runner this compositor uses. Users of the // compositor generally shouldn't use this. scoped_refptr<base::SingleThreadTaskRunner> task_runner() const { @@ -461,6 +464,8 @@ ExternalBeginFrameClient* external_begin_frame_client_ = nullptr; bool needs_external_begin_frames_ = false; + const bool force_software_compositor_; + // The device scale factor of the monitor that this compositor is compositing // layers on. float device_scale_factor_ = 0.f;
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks.js b/ui/file_manager/file_manager/foreground/js/file_tasks.js index 6014c84c..907476b 100644 --- a/ui/file_manager/file_manager/foreground/js/file_tasks.js +++ b/ui/file_manager/file_manager/foreground/js/file_tasks.js
@@ -384,10 +384,13 @@ break; case chrome.fileManagerPrivate.Verb.SHARE_WITH: // Even when the task has SHARE_WITH verb, we don't prefix the title - // with "Share with" when the task is from SEND intent handlers from - // Android apps, since the title can already have an appropriate verb. - if (!(taskParts[1] == 'arc' && taskParts[2] == 'send')) + // with "Share with" when the task is from SEND/SEND_MULTIPLE intent + // handlers from Android apps, since the title can already have an + // appropriate verb. + if (!(taskParts[1] == 'arc' && + (taskParts[2] == 'send' || taskParts[2] == 'send_multiple'))) { verb_button_label = 'SHARE_WITH_VERB_BUTTON_LABEL'; + } break; case chrome.fileManagerPrivate.Verb.OPEN_WITH: verb_button_label = 'OPEN_WITH_VERB_BUTTON_LABEL';
diff --git a/ui/login/account_picker/md_screen_account_picker.js b/ui/login/account_picker/md_screen_account_picker.js index 1ebf46f..483bdcc 100644 --- a/ui/login/account_picker/md_screen_account_picker.js +++ b/ui/login/account_picker/md_screen_account_picker.js
@@ -493,14 +493,22 @@ return; } + var wasForeground = + this.lockScreenAppsState_ === LOCK_SCREEN_APPS_STATE.FOREGROUND; this.lockScreenAppsState_ = state; + $('login-header-bar').lockScreenAppsState = state; $('top-header-bar').lockScreenAppsState = state; // Reset the focused pod if app window is being shown on top of the user // pods. Main goal is to clear any credentials the user might have input. - if (state === LOCK_SCREEN_APPS_STATE.FOREGROUND) + if (state === LOCK_SCREEN_APPS_STATE.FOREGROUND) { $('pod-row').clearFocusedPod(); + } else if (wasForeground) { + // If the app window was moved to background, ensure the active pod is + // focused. + $('pod-row').refocusCurrentPod(); + } }, /**
diff --git a/ui/message_center/message_center.cc b/ui/message_center/message_center.cc index d9e7a7e..aa305a37 100644 --- a/ui/message_center/message_center.cc +++ b/ui/message_center/message_center.cc
@@ -38,8 +38,17 @@ // static bool MessageCenter::IsNewStyleNotificationEnabled() { +// For Chrome OS, the default is Enabled. +// For other platforms, the default is Disabled. +#if defined(OS_CHROMEOS) + // Returns true if not explicitly disabled. + return !base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableMessageCenterNewStyleNotification); +#else + // Returns true if explicitly enabled. return base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableMessageCenterNewStyleNotification); +#endif } MessageCenter::MessageCenter() {
diff --git a/ui/message_center/views/message_center_view.cc b/ui/message_center/views/message_center_view.cc index b2c2cf9f..3c50946 100644 --- a/ui/message_center/views/message_center_view.cc +++ b/ui/message_center/views/message_center_view.cc
@@ -515,7 +515,12 @@ int index) { MessageView* view = MessageViewFactory::Create(this, notification, false); // Not top-level. - view->set_context_menu_controller(context_menu_controller_.get()); + + // TODO(yoshiki): Temporary disable context menu on custom notifications. + // See crbug.com/750307 for detail. + if (notification.type() != NOTIFICATION_TYPE_CUSTOM) + view->set_context_menu_controller(context_menu_controller_.get()); + notification_views_[notification.id()] = view; view->set_scroller(scroller_); message_list_view_->AddNotificationAt(view, index);
diff --git a/ui/message_center/views/message_center_view_unittest.cc b/ui/message_center/views/message_center_view_unittest.cc index 7a5a4f9..b48b000 100644 --- a/ui/message_center/views/message_center_view_unittest.cc +++ b/ui/message_center/views/message_center_view_unittest.cc
@@ -458,7 +458,10 @@ GetMessageListView()->GetInsets().height()); } -TEST_F(MessageCenterViewTest, SizeAfterUpdate) { +// TODO(tetsui): The test is broken because there's no guarantee anymore that +// height would change after setting longer message, as NotificationViewMD +// implements collapse / expand functionality of long message. +TEST_F(MessageCenterViewTest, DISABLED_SizeAfterUpdate) { EXPECT_EQ(2, GetMessageListView()->child_count()); int width = GetMessageListView()->width() - GetMessageListView()->GetInsets().width();
diff --git a/ui/message_center/views/message_popup_collection.cc b/ui/message_center/views/message_popup_collection.cc index 396721d..be17705 100644 --- a/ui/message_center/views/message_popup_collection.cc +++ b/ui/message_center/views/message_popup_collection.cc
@@ -210,7 +210,11 @@ view = MessageViewFactory::Create(NULL, *(*iter), true); } - view->set_context_menu_controller(context_menu_controller_.get()); + // TODO(yoshiki): Temporary disable context menu on custom notifications. + // See crbug.com/750307 for detail. + if ((*iter)->type() != NOTIFICATION_TYPE_CUSTOM) + view->set_context_menu_controller(context_menu_controller_.get()); + int view_height = ToastContentsView::GetToastSizeForView(view).height(); int height_available = top_down ? alignment_delegate_->GetWorkArea().bottom() - base
diff --git a/ui/message_center/views/message_view_factory.cc b/ui/message_center/views/message_view_factory.cc index 60567af..bbd2b49 100644 --- a/ui/message_center/views/message_view_factory.cc +++ b/ui/message_center/views/message_view_factory.cc
@@ -5,7 +5,7 @@ #include "ui/message_center/views/message_view_factory.h" #include "base/command_line.h" -#include "ui/message_center/message_center_switches.h" +#include "ui/message_center/message_center.h" #include "ui/message_center/notification_types.h" #include "ui/message_center/views/notification_view.h" #include "ui/message_center/views/notification_view_md.h" @@ -26,23 +26,13 @@ case NOTIFICATION_TYPE_IMAGE: case NOTIFICATION_TYPE_MULTIPLE: case NOTIFICATION_TYPE_SIMPLE: - case NOTIFICATION_TYPE_PROGRESS: { - bool new_style_notification_enabled = false; // default value - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableMessageCenterNewStyleNotification)) { - new_style_notification_enabled = true; - } else if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableMessageCenterNewStyleNotification)) { - new_style_notification_enabled = false; - } - + case NOTIFICATION_TYPE_PROGRESS: // All above roads lead to the generic NotificationView. - if (new_style_notification_enabled) + if (MessageCenter::IsNewStyleNotificationEnabled()) notification_view = new NotificationViewMD(controller, notification); else notification_view = new NotificationView(controller, notification); break; - } #if defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX) case NOTIFICATION_TYPE_CUSTOM: notification_view =
diff --git a/ui/message_center/views/notification_view_unittest.cc b/ui/message_center/views/notification_view_unittest.cc index 4e5ac15..3f87c9d7 100644 --- a/ui/message_center/views/notification_view_unittest.cc +++ b/ui/message_center/views/notification_view_unittest.cc
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkCanvas.h" @@ -38,6 +39,10 @@ #include "ui/views/test/widget_test.h" #include "ui/views/widget/widget_delegate.h" +#if defined(OS_WIN) +#include "ui/base/win/shell.h" +#endif + namespace message_center { // A test delegate used for tests that deal with the notification settings @@ -238,8 +243,21 @@ notification_->set_image(CreateTestImage(320, 240)); // Then create a new NotificationView with that single notification. - notification_view_.reset(static_cast<NotificationView*>( - MessageViewFactory::Create(this, *notification_, true))); + notification_view_.reset(new NotificationView(this, *notification_)); + + // It depends on platform whether shadows are added. + // See MessageViewFactory::Create. + bool is_nested = true; +#if defined(OS_LINUX) + is_nested = false; +#endif +#if defined(OS_WIN) + if (!ui::win::IsAeroGlassEnabled()) + is_nested = false; +#endif + if (is_nested) + notification_view_->SetIsNested(); + notification_view_->set_owned_by_client(); views::Widget::InitParams init_params(
diff --git a/ui/message_center/views/toast_contents_view.cc b/ui/message_center/views/toast_contents_view.cc index 7455eb1d..6224f780 100644 --- a/ui/message_center/views/toast_contents_view.cc +++ b/ui/message_center/views/toast_contents_view.cc
@@ -171,12 +171,6 @@ bounds_animation_->Show(); } -void ToastContentsView::ActivateToast() { - set_can_activate(true); - if (GetWidget()) - GetWidget()->Activate(); -} - void ToastContentsView::StartFadeIn() { // The decrement is done in OnBoundsAnimationEndedOrCancelled callback. if (collection_)
diff --git a/ui/message_center/views/toast_contents_view.h b/ui/message_center/views/toast_contents_view.h index 7c762d1..ee18955 100644 --- a/ui/message_center/views/toast_contents_view.h +++ b/ui/message_center/views/toast_contents_view.h
@@ -75,9 +75,6 @@ void SetBoundsWithAnimation(gfx::Rect new_bounds); - // Makes the toast activatable, then activate. - void ActivateToast(); - // Origin and bounds are not 'instant', but rather 'current stable values', // there could be animation in progress that targets these values. gfx::Point origin() { return origin_; }
diff --git a/ui/views/cocoa/native_widget_mac_nswindow.mm b/ui/views/cocoa/native_widget_mac_nswindow.mm index af19ce7..a61d582b 100644 --- a/ui/views/cocoa/native_widget_mac_nswindow.mm +++ b/ui/views/cocoa/native_widget_mac_nswindow.mm
@@ -21,6 +21,7 @@ - (ViewsNSWindowDelegate*)viewsNSWindowDelegate; - (views::Widget*)viewsWidget; - (BOOL)hasViewsMenuActive; +- (id)rootAccessibilityObject; // Private API on NSWindow, determines whether the title is drawn on the title // bar. The title is still visible in menus, Expose, etc. @@ -74,6 +75,11 @@ return menuController && menuController->owner() == [self viewsWidget]; } +- (id)rootAccessibilityObject { + views::Widget* widget = [self viewsWidget]; + return widget ? widget->GetRootView()->GetNativeViewAccessible() : nil; +} + // NSWindow overrides. - (BOOL)_isTitleHidden { @@ -222,4 +228,39 @@ forHandler:commandHandler_]; } +// NSWindow overrides (NSAccessibility informal protocol implementation). + +- (id)accessibilityFocusedUIElement { + // The SDK documents this as "The deepest descendant of the accessibility + // hierarchy that has the focus" and says "if a child element does not have + // the focus, either return self or, if available, invoke the superclass's + // implementation." + // The behavior of NSWindow is usually to return null, except when the window + // is first shown, when it returns self. But in the second case, we can + // provide richer a11y information by reporting the views::RootView instead. + // Additionally, if we don't do this, VoiceOver reads out the partial a11y + // properties on the NSWindow and repeats them when focusing an item in the + // RootView's a11y group. See http://crbug.com/748221. + views::Widget* widget = [self viewsWidget]; + id superFocus = [super accessibilityFocusedUIElement]; + if (!widget || superFocus != self) + return superFocus; + + return widget->GetRootView()->GetNativeViewAccessible(); +} + +- (id)accessibilityAttributeValue:(NSString*)attribute { + // Check when NSWindow is asked for its title to provide the title given by + // the views::RootView (and WidgetDelegate::GetAccessibleWindowTitle()). For + // all other attributes, use what NSWindow provides by default since diverging + // from NSWindow's behavior can easily break VoiceOver integration. + if (![attribute isEqualToString:NSAccessibilityTitleAttribute]) + return [super accessibilityAttributeValue:attribute]; + + id viewsValue = + [[self rootAccessibilityObject] accessibilityAttributeValue:attribute]; + return viewsValue ? viewsValue + : [super accessibilityAttributeValue:attribute]; +} + @end
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc index a9fdec6..1524e4d 100644 --- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc +++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -1150,12 +1150,11 @@ //////////////////////////////////////////////////////////////////////////////// // DesktopNativeWidgetAura, aura::WindowTreeHostObserver implementation: -void DesktopNativeWidgetAura::OnHostCloseRequested( - const aura::WindowTreeHost* host) { +void DesktopNativeWidgetAura::OnHostCloseRequested(aura::WindowTreeHost* host) { GetWidget()->Close(); } -void DesktopNativeWidgetAura::OnHostResized(const aura::WindowTreeHost* host) { +void DesktopNativeWidgetAura::OnHostResized(aura::WindowTreeHost* host) { // Don't update the bounds of the child layers when animating closed. If we // did it would force a paint, which we don't want. We don't want the paint // as we can't assume any of the children are valid. @@ -1168,12 +1167,12 @@ } void DesktopNativeWidgetAura::OnHostWorkspaceChanged( - const aura::WindowTreeHost* host) { + aura::WindowTreeHost* host) { native_widget_delegate_->OnNativeWidgetWorkspaceChanged(); } void DesktopNativeWidgetAura::OnHostMovedInPixels( - const aura::WindowTreeHost* host, + aura::WindowTreeHost* host, const gfx::Point& new_origin_in_pixels) { TRACE_EVENT1("views", "DesktopNativeWidgetAura::OnHostMovedInPixels", "new_origin_in_pixels", new_origin_in_pixels.ToString());
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h index 01faa59..1f2ab25 100644 --- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h +++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
@@ -231,10 +231,10 @@ int OnPerformDrop(const ui::DropTargetEvent& event) override; // Overridden from aura::WindowTreeHostObserver: - void OnHostCloseRequested(const aura::WindowTreeHost* host) override; - void OnHostResized(const aura::WindowTreeHost* host) override; - void OnHostWorkspaceChanged(const aura::WindowTreeHost* host) override; - void OnHostMovedInPixels(const aura::WindowTreeHost* host, + void OnHostCloseRequested(aura::WindowTreeHost* host) override; + void OnHostResized(aura::WindowTreeHost* host) override; + void OnHostWorkspaceChanged(aura::WindowTreeHost* host) override; + void OnHostMovedInPixels(aura::WindowTreeHost* host, const gfx::Point& new_origin_in_pixels) override; private:
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc index 4d0dfbe8..0ef74d84 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -843,6 +843,11 @@ return event.handled(); } +bool DesktopWindowTreeHostWin::HandlePointerEvent(ui::PointerEvent* event) { + SendEventToSink(event); + return event->handled(); +} + void DesktopWindowTreeHostWin::HandleKeyEvent(ui::KeyEvent* event) { SendEventToSink(event); }
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h index 3f1c7bf..673baad 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
@@ -188,6 +188,7 @@ void HandleNativeFocus(HWND last_focused_window) override; void HandleNativeBlur(HWND focused_window) override; bool HandleMouseEvent(const ui::MouseEvent& event) override; + bool HandlePointerEvent(ui::PointerEvent* event) override; void HandleKeyEvent(ui::KeyEvent* event) override; void HandleTouchEvent(const ui::TouchEvent& event) override; bool HandleIMEMessage(UINT message,
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc index e8a7a79..f43f179 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -166,8 +166,7 @@ has_pointer_focus_(false), modal_dialog_counter_(0), close_widget_factory_(this), - weak_factory_(this) { -} + weak_factory_(this) {} DesktopWindowTreeHostX11::~DesktopWindowTreeHostX11() { window()->ClearProperty(kHostForRootWindow); @@ -1530,7 +1529,10 @@ if (window_icon) { SetWindowIcons(gfx::ImageSkia(), *window_icon); } - CreateCompositor(); + // Disable compositing on tooltips as a workaround for + // https://crbug.com/442111. + CreateCompositor(viz::FrameSinkId(), + params.type == Widget::InitParams::TYPE_TOOLTIP); OnAcceleratedWidgetAvailable(); }
diff --git a/ui/views/widget/native_widget_mac_accessibility_unittest.mm b/ui/views/widget/native_widget_mac_accessibility_unittest.mm index 357897b..a9debe7 100644 --- a/ui/views/widget/native_widget_mac_accessibility_unittest.mm +++ b/ui/views/widget/native_widget_mac_accessibility_unittest.mm
@@ -24,19 +24,6 @@ #include "ui/views/test/widget_test.h" #include "ui/views/widget/widget.h" -// Expose some methods from AXPlatformNodeCocoa for testing purposes only. -@interface AXPlatformNodeCocoa (Testing) -- (NSString*)AXRole; -- (id)AXValue; - -// Text attributes. -- (NSString*)AXSelectedText; -- (NSValue*)AXSelectedTextRange; -- (NSNumber*)AXNumberOfCharacters; -- (NSValue*)AXVisibleCharacterRange; -- (NSNumber*)AXInsertionPointLineNumber; -@end - namespace views { namespace { @@ -92,28 +79,44 @@ DISALLOW_COPY_AND_ASSIGN(TestLabelButton); }; +class TestWidgetDelegate : public test::TestDesktopWidgetDelegate { + public: + TestWidgetDelegate() = default; + + static constexpr char kAccessibleWindowTitle[] = "My Accessible Window"; + + // WidgetDelegate: + base::string16 GetAccessibleWindowTitle() const override { + return base::ASCIIToUTF16(kAccessibleWindowTitle); + } + + private: + DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate); +}; + +constexpr char TestWidgetDelegate::kAccessibleWindowTitle[]; + class NativeWidgetMacAccessibilityTest : public test::WidgetTest { public: NativeWidgetMacAccessibilityTest() {} void SetUp() override { test::WidgetTest::SetUp(); - widget_ = CreateTopLevelPlatformWidget(); - widget_->SetBounds(gfx::Rect(50, 50, 100, 100)); + widget_delegate_.InitWidget(CreateParams(Widget::InitParams::TYPE_WINDOW)); widget()->Show(); } void TearDown() override { - widget_->CloseNow(); + widget()->CloseNow(); test::WidgetTest::TearDown(); } id A11yElementAtMidpoint() { // Accessibility hit tests come in Cocoa screen coordinates. NSPoint midpoint_in_screen_ = gfx::ScreenPointToNSPoint( - widget_->GetWindowBoundsInScreen().CenterPoint()); + widget()->GetWindowBoundsInScreen().CenterPoint()); return - [widget_->GetNativeWindow() accessibilityHitTest:midpoint_in_screen_]; + [widget()->GetNativeWindow() accessibilityHitTest:midpoint_in_screen_]; } id AttributeValueAtMidpoint(NSString* attribute) { @@ -129,11 +132,71 @@ return textfield; } - Widget* widget() { return widget_; } - gfx::Rect GetWidgetBounds() { return widget_->GetClientAreaBoundsInScreen(); } + // Shorthand helpers to get a11y properties from A11yElementAtMidpoint(). + NSString* AXRole() { + return AttributeValueAtMidpoint(NSAccessibilityRoleAttribute); + } + id AXParent() { + return AttributeValueAtMidpoint(NSAccessibilityParentAttribute); + } + id AXValue() { + return AttributeValueAtMidpoint(NSAccessibilityValueAttribute); + } + NSString* AXTitle() { + return AttributeValueAtMidpoint(NSAccessibilityTitleAttribute); + } + NSString* AXDescription() { + return AttributeValueAtMidpoint(NSAccessibilityDescriptionAttribute); + } + NSString* AXSelectedText() { + return AttributeValueAtMidpoint(NSAccessibilitySelectedTextAttribute); + } + NSValue* AXSelectedTextRange() { + return AttributeValueAtMidpoint(NSAccessibilitySelectedTextRangeAttribute); + } + NSNumber* AXNumberOfCharacters() { + return AttributeValueAtMidpoint(NSAccessibilityNumberOfCharactersAttribute); + } + NSValue* AXVisibleCharacterRange() { + return AttributeValueAtMidpoint( + NSAccessibilityVisibleCharacterRangeAttribute); + } + NSNumber* AXInsertionPointLineNumber() { + return AttributeValueAtMidpoint( + NSAccessibilityInsertionPointLineNumberAttribute); + } + NSNumber* AXLineForIndex(id parameter) { + return [A11yElementAtMidpoint() + accessibilityAttributeValue: + NSAccessibilityLineForIndexParameterizedAttribute + forParameter:parameter]; + } + NSValue* AXRangeForLine(id parameter) { + return [A11yElementAtMidpoint() + accessibilityAttributeValue: + NSAccessibilityRangeForLineParameterizedAttribute + forParameter:parameter]; + } + NSString* AXStringForRange(id parameter) { + return [A11yElementAtMidpoint() + accessibilityAttributeValue: + NSAccessibilityStringForRangeParameterizedAttribute + forParameter:parameter]; + } + NSAttributedString* AXAttributedStringForRange(id parameter) { + return [A11yElementAtMidpoint() + accessibilityAttributeValue: + NSAccessibilityAttributedStringForRangeParameterizedAttribute + forParameter:parameter]; + } + + Widget* widget() { return widget_delegate_.GetWidget(); } + gfx::Rect GetWidgetBounds() { + return widget()->GetClientAreaBoundsInScreen(); + } private: - Widget* widget_ = nullptr; + TestWidgetDelegate widget_delegate_; DISALLOW_COPY_AND_ASSIGN(NativeWidgetMacAccessibilityTest); }; @@ -229,8 +292,7 @@ TestLabelButton* button = new TestLabelButton(); button->SetSize(widget()->GetContentsView()->size()); widget()->GetContentsView()->AddChildView(button); - EXPECT_NSEQ(NSAccessibilityButtonRole, - AttributeValueAtMidpoint(NSAccessibilityRoleAttribute)); + EXPECT_NSEQ(NSAccessibilityButtonRole, AXRole()); EXPECT_EQ( 0u, [[button->GetNativeViewAccessible() @@ -290,7 +352,7 @@ // Views with Widget parents will have a NSWindow parent. EXPECT_NSEQ( NSAccessibilityWindowRole, - [AttributeValueAtMidpoint(NSAccessibilityParentAttribute) AXRole]); + [AXParent() accessibilityAttributeValue:NSAccessibilityRoleAttribute]); // Views with non-Widget parents will have the role of the parent view. widget()->GetContentsView()->RemoveChildView(child); @@ -299,13 +361,13 @@ widget()->GetContentsView()->AddChildView(parent); EXPECT_NSEQ( NSAccessibilityGroupRole, - [AttributeValueAtMidpoint(NSAccessibilityParentAttribute) AXRole]); + [AXParent() accessibilityAttributeValue:NSAccessibilityRoleAttribute]); // Test an ignored role parent is skipped in favor of the grandparent. parent->set_role(ui::AX_ROLE_IGNORED); EXPECT_NSEQ( NSAccessibilityWindowRole, - [AttributeValueAtMidpoint(NSAccessibilityParentAttribute) AXRole]); + [AXParent() accessibilityAttributeValue:NSAccessibilityRoleAttribute]); } // Test for NSAccessibilityPositionAttribute, including on Widget movement @@ -337,20 +399,22 @@ AttributeValueAtMidpoint(NSAccessibilityHelpAttribute)); } -// Test for NSAccessibilityWindowAttribute and -// NSAccessibilityTopLevelUIElementAttribute. -TEST_F(NativeWidgetMacAccessibilityTest, WindowAndTopLevelUIElementAttributes) { +// Test view properties that should report the native NSWindow, and test +// specific properties on that NSWindow. +TEST_F(NativeWidgetMacAccessibilityTest, NativeWindowProperties) { FlexibleRoleTestView* view = new FlexibleRoleTestView(ui::AX_ROLE_GROUP); view->SetSize(GetWidgetBounds().size()); widget()->GetContentsView()->AddChildView(view); // Make sure it's |view| in the hit test by checking its accessibility role. - EXPECT_EQ(NSAccessibilityGroupRole, - AttributeValueAtMidpoint(NSAccessibilityRoleAttribute)); - EXPECT_NSEQ(widget()->GetNativeWindow(), - AttributeValueAtMidpoint(NSAccessibilityWindowAttribute)); + EXPECT_EQ(NSAccessibilityGroupRole, AXRole()); + + NSWindow* window = widget()->GetNativeWindow(); + EXPECT_NSEQ(window, AttributeValueAtMidpoint(NSAccessibilityWindowAttribute)); + EXPECT_NSEQ(window, AttributeValueAtMidpoint( + NSAccessibilityTopLevelUIElementAttribute)); EXPECT_NSEQ( - widget()->GetNativeWindow(), - AttributeValueAtMidpoint(NSAccessibilityTopLevelUIElementAttribute)); + base::SysUTF8ToNSString(TestWidgetDelegate::kAccessibleWindowTitle), + [window accessibilityAttributeValue:NSAccessibilityTitleAttribute]); } // Tests for accessibility attributes on a views::Textfield. @@ -375,16 +439,9 @@ boolValue]); // NSAccessibilityTitleAttribute. - EXPECT_NSEQ(kTestTitle, - AttributeValueAtMidpoint(NSAccessibilityTitleAttribute)); - - // NSAccessibilityValueAttribute. - EXPECT_NSEQ(kTestStringValue, - AttributeValueAtMidpoint(NSAccessibilityValueAttribute)); - - // NSAccessibilityRoleAttribute. - EXPECT_NSEQ(NSAccessibilityTextFieldRole, - AttributeValueAtMidpoint(NSAccessibilityRoleAttribute)); + EXPECT_NSEQ(NSAccessibilityTextFieldRole, AXRole()); + EXPECT_NSEQ(kTestTitle, AXTitle()); + EXPECT_NSEQ(kTestStringValue, AXValue()); // NSAccessibilitySubroleAttribute and // NSAccessibilityRoleDescriptionAttribute. @@ -431,10 +488,8 @@ NSAccessibilityInsertionPointLineNumberAttribute) intValue]); // NSAccessibilityNumberOfCharactersAttribute. - EXPECT_EQ( - kTestStringValue.length, - [AttributeValueAtMidpoint(NSAccessibilityNumberOfCharactersAttribute) - unsignedIntegerValue]); + EXPECT_EQ(kTestStringValue.length, + [AXNumberOfCharacters() unsignedIntegerValue]); // NSAccessibilityPlaceholderAttribute. EXPECT_NSEQ( @@ -443,54 +498,41 @@ // NSAccessibilitySelectedTextAttribute and // NSAccessibilitySelectedTextRangeAttribute. - EXPECT_NSEQ(@"", - AttributeValueAtMidpoint(NSAccessibilitySelectedTextAttribute)); + EXPECT_NSEQ(@"", AXSelectedText()); // The cursor will be at the end of the textfield, so the selection range will // span 0 characters and be located at the index after the last character. EXPECT_EQ(gfx::Range(kTestStringValue.length, kTestStringValue.length), - gfx::Range([AttributeValueAtMidpoint( - NSAccessibilitySelectedTextRangeAttribute) rangeValue])); + gfx::Range([AXSelectedTextRange() rangeValue])); // Select some text in the middle of the textfield. const gfx::Range forward_range(2, 6); const NSRange ns_range = forward_range.ToNSRange(); textfield->SelectRange(forward_range); - EXPECT_NSEQ([kTestStringValue substringWithRange:ns_range], - AttributeValueAtMidpoint(NSAccessibilitySelectedTextAttribute)); + EXPECT_NSEQ([kTestStringValue substringWithRange:ns_range], AXSelectedText()); EXPECT_EQ(textfield->GetSelectedText(), - base::SysNSStringToUTF16(AttributeValueAtMidpoint( - NSAccessibilitySelectedTextAttribute))); - EXPECT_EQ(forward_range, - gfx::Range([AttributeValueAtMidpoint( - NSAccessibilitySelectedTextRangeAttribute) rangeValue])); + base::SysNSStringToUTF16(AXSelectedText())); + EXPECT_EQ(forward_range, gfx::Range([AXSelectedTextRange() rangeValue])); const gfx::Range reversed_range(6, 2); textfield->SelectRange(reversed_range); // NSRange has no direction, so these are unchanged from the forward range. - EXPECT_NSEQ([kTestStringValue substringWithRange:ns_range], - AttributeValueAtMidpoint(NSAccessibilitySelectedTextAttribute)); + EXPECT_NSEQ([kTestStringValue substringWithRange:ns_range], AXSelectedText()); EXPECT_EQ(textfield->GetSelectedText(), - base::SysNSStringToUTF16(AttributeValueAtMidpoint( - NSAccessibilitySelectedTextAttribute))); - EXPECT_EQ(forward_range, - gfx::Range([AttributeValueAtMidpoint( - NSAccessibilitySelectedTextRangeAttribute) rangeValue])); + base::SysNSStringToUTF16(AXSelectedText())); + EXPECT_EQ(forward_range, gfx::Range([AXSelectedTextRange() rangeValue])); // NSAccessibilityVisibleCharacterRangeAttribute. EXPECT_EQ(gfx::Range(0, kTestStringValue.length), - gfx::Range([AttributeValueAtMidpoint( - NSAccessibilityVisibleCharacterRangeAttribute) rangeValue])); + gfx::Range([AXVisibleCharacterRange() rangeValue])); // Test an RTL string. textfield->SetText(base::SysNSStringToUTF16(kTestRTLStringValue)); textfield->SelectRange(forward_range); EXPECT_EQ(textfield->GetSelectedText(), - base::SysNSStringToUTF16(AttributeValueAtMidpoint( - NSAccessibilitySelectedTextAttribute))); + base::SysNSStringToUTF16(AXSelectedText())); textfield->SelectRange(reversed_range); EXPECT_EQ(textfield->GetSelectedText(), - base::SysNSStringToUTF16(AttributeValueAtMidpoint( - NSAccessibilitySelectedTextAttribute))); + base::SysNSStringToUTF16(AXSelectedText())); } // Test writing accessibility attributes via an accessibility client for normal @@ -503,8 +545,7 @@ // Make sure the accessibility object tested is the correct one. id ax_node = A11yElementAtMidpoint(); EXPECT_TRUE(ax_node); - EXPECT_NSEQ(NSAccessibilityGroupRole, - AttributeValueAtMidpoint(NSAccessibilityRoleAttribute)); + EXPECT_NSEQ(NSAccessibilityGroupRole, AXRole()); // Make sure |view| is focusable, then focus/unfocus it. view->SetFocusBehavior(View::FocusBehavior::ALWAYS); @@ -530,17 +571,14 @@ EXPECT_TRUE(ax_node); // Make sure it's the correct accessibility object. - id value = - [ax_node accessibilityAttributeValue:NSAccessibilityValueAttribute]; - EXPECT_NSEQ(kTestStringValue, value); + EXPECT_NSEQ(kTestStringValue, AXValue()); // Write a new NSAccessibilityValueAttribute. EXPECT_TRUE( [ax_node accessibilityIsAttributeSettable:NSAccessibilityValueAttribute]); [ax_node accessibilitySetValue:kTestPlaceholderText forAttribute:NSAccessibilityValueAttribute]; - EXPECT_NSEQ(kTestPlaceholderText, - AttributeValueAtMidpoint(NSAccessibilityValueAttribute)); + EXPECT_NSEQ(kTestPlaceholderText, AXValue()); EXPECT_EQ(base::SysNSStringToUTF16(kTestPlaceholderText), textfield->text()); // Test a read-only textfield. @@ -549,8 +587,7 @@ [ax_node accessibilityIsAttributeSettable:NSAccessibilityValueAttribute]); [ax_node accessibilitySetValue:kTestStringValue forAttribute:NSAccessibilityValueAttribute]; - EXPECT_NSEQ(kTestPlaceholderText, - AttributeValueAtMidpoint(NSAccessibilityValueAttribute)); + EXPECT_NSEQ(kTestPlaceholderText, AXValue()); EXPECT_EQ(base::SysNSStringToUTF16(kTestPlaceholderText), textfield->text()); textfield->SetReadOnly(false); @@ -563,8 +600,7 @@ [kTestStringValue stringByAppendingString:kTestPlaceholderText]; [ax_node accessibilitySetValue:kTestStringValue forAttribute:NSAccessibilitySelectedTextAttribute]; - EXPECT_NSEQ(new_string, - AttributeValueAtMidpoint(NSAccessibilityValueAttribute)); + EXPECT_NSEQ(new_string, AXValue()); EXPECT_EQ(base::SysNSStringToUTF16(new_string), textfield->text()); // Replace entire selection. @@ -572,8 +608,7 @@ textfield->SelectRange(test_range); [ax_node accessibilitySetValue:kTestStringValue forAttribute:NSAccessibilitySelectedTextAttribute]; - EXPECT_NSEQ(kTestStringValue, - AttributeValueAtMidpoint(NSAccessibilityValueAttribute)); + EXPECT_NSEQ(kTestStringValue, AXValue()); EXPECT_EQ(base::SysNSStringToUTF16(kTestStringValue), textfield->text()); // Make sure the cursor is at the end of the Textfield. EXPECT_EQ(gfx::Range([kTestStringValue length]), @@ -590,8 +625,7 @@ textfield->SelectRange(test_range); [ax_node accessibilitySetValue:base::SysUTF16ToNSString(replacement) forAttribute:NSAccessibilitySelectedTextAttribute]; - EXPECT_NSEQ(new_string, - AttributeValueAtMidpoint(NSAccessibilityValueAttribute)); + EXPECT_NSEQ(new_string, AXValue()); EXPECT_EQ(base::SysNSStringToUTF16(new_string), textfield->text()); // Make sure the cursor is at the end of the replacement. EXPECT_EQ(gfx::Range(front.length() + replacement.length()), @@ -645,30 +679,17 @@ EXPECT_TRUE([ax_node respondsToSelector:sel]); } - NSNumber* line = - [ax_node accessibilityAttributeValue: - NSAccessibilityLineForIndexParameterizedAttribute - forParameter:@5]; + NSNumber* line = AXLineForIndex(@5); EXPECT_TRUE(line); EXPECT_EQ(0, [line intValue]); EXPECT_NSEQ([NSValue valueWithRange:NSMakeRange(0, kTestStringLength)], - [ax_node accessibilityAttributeValue: - NSAccessibilityRangeForLineParameterizedAttribute - forParameter:line]); + AXRangeForLine(line)); // The substring "est st" of kTestStringValue. NSValue* test_range = [NSValue valueWithRange:NSMakeRange(1, 6)]; - EXPECT_NSEQ(@"est st", - [ax_node accessibilityAttributeValue: - NSAccessibilityStringForRangeParameterizedAttribute - forParameter:test_range]); - EXPECT_NSEQ( - @"est st", - [[ax_node - accessibilityAttributeValue: - NSAccessibilityAttributedStringForRangeParameterizedAttribute - forParameter:test_range] string]); + EXPECT_NSEQ(@"est st", AXStringForRange(test_range)); + EXPECT_NSEQ(@"est st", [AXAttributedStringForRange(test_range) string]); // Not implemented yet. Update these tests when they are. EXPECT_NSEQ(nil, @@ -705,8 +726,7 @@ view->SetSize(GetWidgetBounds().size()); id ax_node = A11yElementAtMidpoint(); - EXPECT_NSEQ(NSAccessibilityButtonRole, - AttributeValueAtMidpoint(NSAccessibilityRoleAttribute)); + EXPECT_NSEQ(NSAccessibilityButtonRole, AXRole()); EXPECT_TRUE([[ax_node accessibilityActionNames] containsObject:NSAccessibilityPressAction]); @@ -769,35 +789,35 @@ // Explicit checks done without comparing to NSTextField. EXPECT_TRUE( [ax_node accessibilityIsAttributeSettable:NSAccessibilityValueAttribute]); - EXPECT_NSEQ(NSAccessibilityTextFieldRole, [ax_node AXRole]); + EXPECT_NSEQ(NSAccessibilityTextFieldRole, AXRole()); NSString* kShownValue = @"•" @"••••••••••••••••"; // Sanity check. EXPECT_EQ(kTestStringLength, static_cast<int>([kShownValue length])); - EXPECT_NSEQ(kShownValue, [ax_node AXValue]); + EXPECT_NSEQ(kShownValue, AXValue()); // Cursor currently at the end of input. - EXPECT_NSEQ(@"", [ax_node AXSelectedText]); + EXPECT_NSEQ(@"", AXSelectedText()); EXPECT_NSEQ([NSValue valueWithRange:NSMakeRange(kTestStringLength, 0)], - [ax_node AXSelectedTextRange]); + AXSelectedTextRange()); - EXPECT_EQ(kTestStringLength, [[ax_node AXNumberOfCharacters] intValue]); + EXPECT_EQ(kTestStringLength, [AXNumberOfCharacters() intValue]); EXPECT_NSEQ(([NSValue valueWithRange:{0, kTestStringLength}]), - [ax_node AXVisibleCharacterRange]); - EXPECT_EQ(0, [[ax_node AXInsertionPointLineNumber] intValue]); + AXVisibleCharacterRange()); + EXPECT_EQ(0, [AXInsertionPointLineNumber() intValue]); // Test replacing text. textfield->SetText(base::ASCIIToUTF16("123")); - EXPECT_NSEQ(@"•••", [ax_node AXValue]); - EXPECT_EQ(3, [[ax_node AXNumberOfCharacters] intValue]); + EXPECT_NSEQ(@"•••", AXValue()); + EXPECT_EQ(3, [AXNumberOfCharacters() intValue]); textfield->SelectRange(gfx::Range(2, 3)); // Selects "3". [ax_node accessibilitySetValue:@"ab" forAttribute:NSAccessibilitySelectedTextAttribute]; EXPECT_EQ(base::ASCIIToUTF16("12ab"), textfield->text()); - EXPECT_NSEQ(@"••••", [ax_node AXValue]); - EXPECT_EQ(4, [[ax_node AXNumberOfCharacters] intValue]); + EXPECT_NSEQ(@"••••", AXValue()); + EXPECT_EQ(4, [AXNumberOfCharacters() intValue]); } // Test text-specific attributes of Labels. @@ -811,20 +831,40 @@ id ax_node = A11yElementAtMidpoint(); EXPECT_TRUE(ax_node); - EXPECT_NSEQ(NSAccessibilityStaticTextRole, [ax_node AXRole]); - EXPECT_NSEQ(kTestStringValue, [ax_node AXValue]); + EXPECT_NSEQ(NSAccessibilityStaticTextRole, AXRole()); + EXPECT_NSEQ(kTestStringValue, AXValue()); + + // Title and description for StaticTextRole should always be empty. + EXPECT_NSEQ(@"", AXTitle()); + + // The description is "The purpose of the element, not including the role.". + // BrowserAccessibility returns an empty string instead of nil. Either should + // be OK. + EXPECT_EQ(nil, AXDescription()); // No selection by default. TODO(tapted): Test selection when views::Label // uses RenderTextHarfBuzz on Mac. See http://crbug.com/454835. // For now, this tests that the codepaths are valid for views::Label. - EXPECT_NSEQ(@"", [ax_node AXSelectedText]); + EXPECT_NSEQ(@"", AXSelectedText()); EXPECT_NSEQ([NSValue valueWithRange:NSMakeRange(0, 0)], - [ax_node AXSelectedTextRange]); + AXSelectedTextRange()); - EXPECT_EQ(kTestStringLength, [[ax_node AXNumberOfCharacters] intValue]); + EXPECT_EQ(kTestStringLength, [AXNumberOfCharacters() intValue]); EXPECT_NSEQ(([NSValue valueWithRange:{0, kTestStringLength}]), - [ax_node AXVisibleCharacterRange]); - EXPECT_EQ(0, [[ax_node AXInsertionPointLineNumber] intValue]); + AXVisibleCharacterRange()); + EXPECT_EQ(0, [AXInsertionPointLineNumber() intValue]); + + // Test parameterized attributes for Static Text. + NSNumber* line = AXLineForIndex(@5); + EXPECT_TRUE(line); + EXPECT_EQ(0, [line intValue]); + EXPECT_NSEQ([NSValue valueWithRange:NSMakeRange(0, kTestStringLength)], + AXRangeForLine(line)); + NSValue* test_range = [NSValue valueWithRange:NSMakeRange(1, 6)]; + EXPECT_NSEQ(@"est st", AXStringForRange(test_range)); + EXPECT_NSEQ(@"est st", [AXAttributedStringForRange(test_range) string]); + + // TODO(tapted): Add a test for multiline Labels (currently not supported). } class TestComboboxModel : public ui::ComboboxModel { @@ -851,12 +891,12 @@ id ax_node = A11yElementAtMidpoint(); EXPECT_TRUE(ax_node); - EXPECT_NSEQ(NSAccessibilityPopUpButtonRole, [ax_node AXRole]); + EXPECT_NSEQ(NSAccessibilityPopUpButtonRole, AXRole()); // The initial value should be the first item in the menu. - EXPECT_NSEQ(kTestStringValue, [ax_node AXValue]); + EXPECT_NSEQ(kTestStringValue, AXValue()); combobox->SetSelectedIndex(1); - EXPECT_NSEQ(@"Second Item", [ax_node AXValue]); + EXPECT_NSEQ(@"Second Item", AXValue()); // Expect to see both a press action and a show menu action. This matches // Cocoa behavior.
diff --git a/ui/views/widget/native_widget_mac_unittest.mm b/ui/views/widget/native_widget_mac_unittest.mm index bae7382..50a6655 100644 --- a/ui/views/widget/native_widget_mac_unittest.mm +++ b/ui/views/widget/native_widget_mac_unittest.mm
@@ -664,7 +664,7 @@ NSPoint midpoint = NSMakePoint(NSMidX(nsrect), NSMidY(nsrect)); id hit = [widget->GetNativeWindow() accessibilityHitTest:midpoint]; - id title = [hit accessibilityAttributeValue:NSAccessibilityTitleAttribute]; + id title = [hit accessibilityAttributeValue:NSAccessibilityValueAttribute]; EXPECT_NSEQ(title, @"Green"); widget->CloseNow();
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc index 2ed8b230..11359d2 100644 --- a/ui/views/win/hwnd_message_handler.cc +++ b/ui/views/win/hwnd_message_handler.cc
@@ -14,6 +14,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/debug/alias.h" +#include "base/feature_list.h" #include "base/location.h" #include "base/macros.h" #include "base/message_loop/message_loop.h" @@ -239,6 +240,23 @@ return ui::ET_TOUCH_MOVED; } +int GetFlagsFromPointerMessage(UINT message, const POINTER_INFO& pointer_info) { + int flags = ui::EF_NONE; + if (pointer_info.pointerFlags & POINTER_FLAG_FIRSTBUTTON) + flags |= ui::EF_LEFT_MOUSE_BUTTON; + + if (pointer_info.pointerFlags & POINTER_FLAG_SECONDBUTTON) + flags |= ui::EF_RIGHT_MOUSE_BUTTON; + + if (message == WM_POINTERUP) { + if (pointer_info.ButtonChangeType == POINTER_CHANGE_SECONDBUTTON_UP) + flags |= ui::EF_RIGHT_MOUSE_BUTTON; + else + flags |= ui::EF_LEFT_MOUSE_BUTTON; + } + return flags; +} + const int kTouchDownContextResetTimeout = 500; // Windows does not flag synthesized mouse messages from touch in all cases. @@ -248,6 +266,9 @@ // location as the cursor. const int kSynthesizedMouseTouchMessagesTimeDifference = 500; +const base::Feature kDirectManipulationStylus{ + "DirectManipulationStylus", base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace // A scoping class that prevents a window from being able to redraw in response @@ -2752,6 +2773,132 @@ return 0; } +LRESULT HWNDMessageHandler::GenerateMouseEventFromPointerEvent( + UINT message, + UINT32 pointer_id, + const POINTER_INFO& pointer_info, + const gfx::Point& point, + const ui::PointerDetails& pointer_details) { + ui::EventType event_type = ui::ET_MOUSE_MOVED; + int flag = GetFlagsFromPointerMessage(message, pointer_info); + int changed_flag = ui::EF_NONE; + int click_count = 0; + switch (message) { + case WM_POINTERDOWN: + event_type = ui::ET_MOUSE_PRESSED; + if (pointer_info.ButtonChangeType == POINTER_CHANGE_FIRSTBUTTON_DOWN) + changed_flag = ui::EF_LEFT_MOUSE_BUTTON; + else + changed_flag = ui::EF_RIGHT_MOUSE_BUTTON; + click_count = 1; + break; + case WM_POINTERUP: + event_type = ui::ET_MOUSE_RELEASED; + if (pointer_info.ButtonChangeType == POINTER_CHANGE_FIRSTBUTTON_UP) + changed_flag = ui::EF_LEFT_MOUSE_BUTTON; + else + changed_flag = ui::EF_RIGHT_MOUSE_BUTTON; + id_generator_.ReleaseNumber(pointer_id); + click_count = 1; + break; + case WM_POINTERUPDATE: + event_type = ui::ET_MOUSE_DRAGGED; + if (flag == ui::EF_NONE) + event_type = ui::ET_MOUSE_MOVED; + break; + case WM_POINTERENTER: + event_type = ui::ET_MOUSE_ENTERED; + break; + case WM_POINTERLEAVE: + event_type = ui::ET_MOUSE_EXITED; + id_generator_.ReleaseNumber(pointer_id); + break; + default: + NOTREACHED(); + } + ui::MouseEvent event(event_type, point, point, ui::EventTimeForNow(), flag, + changed_flag, pointer_details); + event.SetClickCount(click_count); + + // There are cases where the code handling the message destroys the + // window, so use the weak ptr to check if destruction occured or not. + base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr()); + bool handled = delegate_->HandleMouseEvent(event); + if (ref) + SetMsgHandled(handled); + return 0; +} + +LRESULT HWNDMessageHandler::GenerateTouchEventFromPointerEvent( + UINT message, + UINT32 pointer_id, + const POINTER_INFO& pointer_info, + const gfx::Point& point, + const ui::PointerDetails& pointer_details) { + int flags = GetFlagsFromPointerMessage(message, pointer_info); + bool is_pointer_event = false; + ui::EventType event_type = ui::ET_TOUCH_MOVED; + switch (message) { + case WM_POINTERDOWN: + event_type = ui::ET_TOUCH_PRESSED; + break; + case WM_POINTERUP: + event_type = ui::ET_TOUCH_RELEASED; + id_generator_.ReleaseNumber(pointer_id); + break; + case WM_POINTERUPDATE: + if (pointer_info.pointerFlags & POINTER_FLAG_INCONTACT) { + event_type = ui::ET_TOUCH_MOVED; + } else { + event_type = ui::ET_POINTER_MOVED; + is_pointer_event = true; + } + break; + case WM_POINTERENTER: + event_type = ui::ET_POINTER_ENTERED; + is_pointer_event = true; + break; + case WM_POINTERLEAVE: + event_type = ui::ET_POINTER_EXITED; + id_generator_.ReleaseNumber(pointer_id); + is_pointer_event = true; + break; + default: + NOTREACHED(); + } + + bool handled = true; + const base::TimeTicks event_time = ui::EventTimeForNow(); + + // There are cases where the code handling the message destroys the + // window, so use the weak ptr to check if destruction occured or not. + base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr()); + + // Send PointerEvents when the pen is hovering in the range of tablet + // but not pressing the tablet since when contact is made with the digitizer + // a TOUCH_PRESSED is sent and TOUCH_MOVED is not a valid event outside + // of a TOUCH_PRESSED/TOUCH_RELEASED pair. + if (is_pointer_event) { + ui::PointerEvent event(event_type, point, point, 0, 0, pointer_details, + event_time); + event.latency()->AddLatencyNumberWithTimestamp( + ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0, event_time, 1); + handled = delegate_->HandlePointerEvent(&event); + } else { + int rotation_angle = static_cast<int>(pointer_details.twist) % 180; + if (rotation_angle < 0) + rotation_angle += 180; + ui::TouchEvent event(event_type, point, event_time, pointer_details, flags, + rotation_angle); + event.latency()->AddLatencyNumberWithTimestamp( + ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0, event_time, 1); + delegate_->HandleTouchEvent(event); + } + if (ref) + SetMsgHandled(handled); + return 0; +} + LRESULT HWNDMessageHandler::HandlePointerEventTypePen(UINT message, WPARAM w_param, LPARAM l_param) { @@ -2785,68 +2932,22 @@ POINT client_point = pointer_pen_info.pointerInfo.ptPixelLocationRaw; ScreenToClient(hwnd(), &client_point); gfx::Point point = gfx::Point(client_point.x, client_point.y); - ui::EventType event_type = ui::ET_MOUSE_MOVED; - int flag = 0; - int click_count = 0; - switch (message) { - case WM_POINTERDOWN: - event_type = ui::ET_MOUSE_PRESSED; - if (pointer_pen_info.pointerInfo.ButtonChangeType == - POINTER_CHANGE_SECONDBUTTON_DOWN) { - flag = ui::EF_RIGHT_MOUSE_BUTTON; - } else { - flag = ui::EF_LEFT_MOUSE_BUTTON; - } - click_count = 1; - break; - case WM_POINTERUP: - event_type = ui::ET_MOUSE_RELEASED; - if (pointer_pen_info.pointerInfo.ButtonChangeType == - POINTER_CHANGE_SECONDBUTTON_UP) { - flag = ui::EF_RIGHT_MOUSE_BUTTON; - } else { - flag = ui::EF_LEFT_MOUSE_BUTTON; - } - id_generator_.ReleaseNumber(pointer_id); - click_count = 1; - break; - case WM_POINTERUPDATE: - event_type = ui::ET_MOUSE_DRAGGED; - if (pointer_pen_info.pointerInfo.pointerFlags & - POINTER_FLAG_FIRSTBUTTON) { - flag = ui::EF_LEFT_MOUSE_BUTTON; - } else if (pointer_pen_info.pointerInfo.pointerFlags & - POINTER_FLAG_SECONDBUTTON) { - flag = ui::EF_RIGHT_MOUSE_BUTTON; - } else { - event_type = ui::ET_MOUSE_MOVED; - } - break; - case WM_POINTERENTER: - event_type = ui::ET_MOUSE_ENTERED; - break; - case WM_POINTERLEAVE: - event_type = ui::ET_MOUSE_EXITED; - id_generator_.ReleaseNumber(pointer_id); - break; - default: - NOTREACHED(); - } ui::PointerDetails pointer_details( input_type, mapped_pointer_id, /* radius_x */ 0.0f, /* radius_y */ 0.0f, pressure, tilt_x, tilt_y, /* tangential_pressure */ 0.0f, rotation); - ui::MouseEvent event(event_type, point, point, base::TimeTicks::Now(), flag, - flag, pointer_details); - event.SetClickCount(click_count); - // There are cases where the code handling the message destroys the - // window, so use the weak ptr to check if destruction occured or not. - base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr()); - bool handled = delegate_->HandleMouseEvent(event); + // If the flag is disabled, we send mouse events for all pen inputs. + static bool direct_manipulation_stylus = + base::FeatureList::IsEnabled(kDirectManipulationStylus); + if (!direct_manipulation_stylus) { + return GenerateMouseEventFromPointerEvent(message, pointer_id, + pointer_pen_info.pointerInfo, + point, pointer_details); + } - if (ref) - SetMsgHandled(handled); - return 0; + return GenerateTouchEventFromPointerEvent(message, pointer_id, + pointer_pen_info.pointerInfo, point, + pointer_details); } bool HWNDMessageHandler::IsSynthesizedMouseMessage(unsigned int message,
diff --git a/ui/views/win/hwnd_message_handler.h b/ui/views/win/hwnd_message_handler.h index 51f399a2..9bacb195 100644 --- a/ui/views/win/hwnd_message_handler.h +++ b/ui/views/win/hwnd_message_handler.h
@@ -543,6 +543,19 @@ WPARAM w_param, LPARAM l_param); + LRESULT GenerateMouseEventFromPointerEvent( + UINT message, + UINT32 pointer_id, + const POINTER_INFO& pointer_info, + const gfx::Point& point, + const ui::PointerDetails& pointer_details); + LRESULT GenerateTouchEventFromPointerEvent( + UINT message, + UINT32 pointer_id, + const POINTER_INFO& pointer_info, + const gfx::Point& point, + const ui::PointerDetails& pointer_details); + // Returns true if the mouse message passed in is an OS synthesized mouse // message. // |message| identifies the mouse message.
diff --git a/ui/views/win/hwnd_message_handler_delegate.h b/ui/views/win/hwnd_message_handler_delegate.h index 72d321394..2168aed 100644 --- a/ui/views/win/hwnd_message_handler_delegate.h +++ b/ui/views/win/hwnd_message_handler_delegate.h
@@ -188,6 +188,10 @@ // handled by the delegate. virtual bool HandleMouseEvent(const ui::MouseEvent& event) = 0; + // Called when a pointer event is received. Returns true if the event was + // handled by the delegate. + virtual bool HandlePointerEvent(ui::PointerEvent* event) = 0; + // Called when an untranslated key event is received (i.e. pre-IME // translation). virtual void HandleKeyEvent(ui::KeyEvent* event) = 0;
diff --git a/ui/wm/core/focus_controller.cc b/ui/wm/core/focus_controller.cc index 695be50..069e9f46 100644 --- a/ui/wm/core/focus_controller.cc +++ b/ui/wm/core/focus_controller.cc
@@ -206,16 +206,29 @@ // Activation change observers may change the focused window. If this happens // we must not adjust the focus below since this will clobber that change. aura::Window* last_focused_window = focused_window_; - if (!updating_activation_) + if (!updating_activation_) { + aura::WindowTracker focusable_window_tracker; + if (focusable) { + focusable_window_tracker.Add(focusable); + focusable = nullptr; + } SetActiveWindow(reason, window, activatable); + if (!focusable_window_tracker.windows().empty()) + focusable = focusable_window_tracker.Pop(); + } // If the window's ActivationChangeObserver shifted focus to a valid window, // we don't want to focus the window we thought would be focused by default. - bool activation_changed_focus = last_focused_window != focused_window_; - if (!updating_focus_ && (!activation_changed_focus || !focused_window_)) { - if (active_window_ && focusable) - DCHECK(active_window_->Contains(focusable)); - SetFocusedWindow(focusable); + if (!updating_focus_) { + const bool activation_changed_focus = + last_focused_window != focused_window_; + if (!activation_changed_focus || !focused_window_) { + if (active_window_ && focusable) + DCHECK(active_window_->Contains(focusable)); + SetFocusedWindow(focusable); + } + if (active_window_ && focused_window_) + DCHECK(active_window_->Contains(focused_window_)); } } @@ -340,8 +353,17 @@ if (!(active_window_ && active_window_->Contains(focused_window_))) SetFocusedWindow(next_activatable); } else if (window->Contains(focused_window_)) { - // Active window isn't changing, but focused window might be. - SetFocusedWindow(rules_->GetFocusableWindow(next)); + if (updating_activation_) { + // We're in the process of updating activation, most likely + // ActivationChangeObserver::OnWindowActivated() is changing something + // about the focused window (visibility perhaps). Temporarily set the + // focus to null, we'll set it to something better when activation + // completes. + SetFocusedWindow(nullptr); + } else { + // Active window isn't changing, but focused window might be. + SetFocusedWindow(rules_->GetFocusableWindow(next)); + } } }
diff --git a/ui/wm/core/focus_controller_unittest.cc b/ui/wm/core/focus_controller_unittest.cc index f4678ca..1c863010 100644 --- a/ui/wm/core/focus_controller_unittest.cc +++ b/ui/wm/core/focus_controller_unittest.cc
@@ -149,6 +149,39 @@ DISALLOW_COPY_AND_ASSIGN(RecordingActivationAndFocusChangeObserver); }; +// Hides a window when activation changes. +class HideOnLoseActivationChangeObserver : public ActivationChangeObserver { + public: + explicit HideOnLoseActivationChangeObserver(aura::Window* window_to_hide) + : root_(window_to_hide->GetRootWindow()), + window_to_hide_(window_to_hide) { + GetActivationClient(root_)->AddObserver(this); + } + + ~HideOnLoseActivationChangeObserver() override { + GetActivationClient(root_)->RemoveObserver(this); + } + + aura::Window* window_to_hide() { return window_to_hide_; } + + private: + // Overridden from ActivationChangeObserver: + void OnWindowActivated(ActivationReason reason, + aura::Window* gained_active, + aura::Window* lost_active) override { + if (window_to_hide_) { + aura::Window* window_to_hide = window_to_hide_; + window_to_hide_ = nullptr; + window_to_hide->Hide(); + } + } + + aura::Window* root_; + aura::Window* window_to_hide_; + + DISALLOW_COPY_AND_ASSIGN(HideOnLoseActivationChangeObserver); +}; + // ActivationChangeObserver that deletes the window losing activation. class DeleteOnLoseActivationChangeObserver : public ActivationChangeObserver, public WindowDeleter { @@ -465,6 +498,7 @@ virtual void ChangeFocusWhenNothingFocusedAndCaptured() {} virtual void DontPassDeletedWindow() {} virtual void StackWindowAtTopOnActivation() {} + virtual void HideFocusedWindowDuringActivationLoss() {} private: std::unique_ptr<FocusController> focus_controller_; @@ -865,6 +899,22 @@ EXPECT_EQ(window1.get(), GetActiveWindow()); } + // Verifies focus isn't left when during notification of an activation change + // the focused window is hidden. + void HideFocusedWindowDuringActivationLoss() override { + aura::Window* w11 = root_window()->GetChildById(11); + FocusWindow(w11); + EXPECT_EQ(11, GetFocusedWindowId()); + EXPECT_EQ(1, GetActiveWindowId()); + { + HideOnLoseActivationChangeObserver observer(w11); + ActivateWindowById(2); + EXPECT_EQ(nullptr, observer.window_to_hide()); + EXPECT_EQ(2, GetActiveWindowId()); + EXPECT_EQ(2, GetFocusedWindowId()); + } + } + private: DISALLOW_COPY_AND_ASSIGN(FocusControllerDirectTestBase); }; @@ -1311,6 +1361,9 @@ FOCUS_CONTROLLER_TEST(FocusControllerApiTest, StackWindowAtTopOnActivation); +FOCUS_CONTROLLER_TEST(FocusControllerApiTest, + HideFocusedWindowDuringActivationLoss); + // See description above TransientChildWindowActivationTest() for details. FOCUS_CONTROLLER_TEST(FocusControllerParentHideTest, TransientChildWindowActivationTest);
diff --git a/url/gurl.cc b/url/gurl.cc index 128652fe..45c45b10b 100644 --- a/url/gurl.cc +++ b/url/gurl.cc
@@ -374,6 +374,10 @@ return other; } +GURL GURL::GetWithoutFilename() const { + return Resolve("."); +} + bool GURL::IsStandard() const { return url::IsStandard(spec_.data(), parsed_.scheme); }
diff --git a/url/gurl.h b/url/gurl.h index 6f4536d..091ff68 100644 --- a/url/gurl.h +++ b/url/gurl.h
@@ -181,6 +181,15 @@ // will be the empty URL. GURL GetWithEmptyPath() const; + // A helper function to return a GURL without the filename, query values, and + // fragment. For example, + // GURL("https://www.foo.com/index.html?q=test").GetWithoutFilename().spec() + // will return "https://www.foo.com/". + // GURL("https://www.foo.com/bar/").GetWithoutFilename().spec() + // will return "https://www.foo.com/bar/". If the GURL is invalid or missing a + // scheme, authority or path, it will return an empty, invalid GURL. + GURL GetWithoutFilename() const; + // A helper function to return a GURL containing just the scheme, host, // and port from a URL. Equivalent to clearing any username and password, // replacing the path with a slash, and clearing everything after that. If
diff --git a/url/gurl_unittest.cc b/url/gurl_unittest.cc index 30db59eb..464d08a 100644 --- a/url/gurl_unittest.cc +++ b/url/gurl_unittest.cc
@@ -387,6 +387,52 @@ } } +TEST(GURLTest, GetWithoutFilename) { + struct TestCase { + const char* input; + const char* expected; + } cases[] = { + // Common Standard URLs. + {"https://www.google.com", "https://www.google.com/"}, + {"https://www.google.com/", "https://www.google.com/"}, + {"https://www.google.com/maps.htm", "https://www.google.com/"}, + {"https://www.google.com/maps/", "https://www.google.com/maps/"}, + {"https://www.google.com/index.html", "https://www.google.com/"}, + {"https://www.google.com/index.html?q=maps", "https://www.google.com/"}, + {"https://www.google.com/index.html#maps/", "https://www.google.com/"}, + {"https://foo:bar@www.google.com/maps.htm", "https://foo:bar@www.google.com/"}, + {"https://www.google.com/maps/au/index.html", "https://www.google.com/maps/au/"}, + {"https://www.google.com/maps/au/north", "https://www.google.com/maps/au/"}, + {"https://www.google.com/maps/au/north/", "https://www.google.com/maps/au/north/"}, + {"https://www.google.com/maps/au/index.html?q=maps#fragment/", "https://www.google.com/maps/au/"}, + {"http://www.google.com:8000/maps/au/index.html?q=maps#fragment/", "http://www.google.com:8000/maps/au/"}, + {"https://www.google.com/maps/au/north/?q=maps#fragment", "https://www.google.com/maps/au/north/"}, + {"https://www.google.com/maps/au/north?q=maps#fragment", "https://www.google.com/maps/au/"}, + // Less common standard URLs. + {"filesystem:http://www.google.com/temporary/bar.html?baz=22", "filesystem:http://www.google.com/temporary/"}, + {"file:///temporary/bar.html?baz=22","file:///temporary/"}, + {"ftp://foo/test/index.html", "ftp://foo/test/"}, + {"gopher://foo/test/index.html", "gopher://foo/test/"}, + {"ws://foo/test/index.html", "ws://foo/test/"}, + // Non-standard, hierarchical URLs. + {"chrome://foo/bar.html", "chrome://foo/"}, + {"httpa://foo/test/index.html", "httpa://foo/test/"}, + // Non-standard, non-hierarchical URLs. + {"blob:https://foo.bar/test/index.html", ""}, + {"about:blank", ""}, + {"data:foobar", ""}, + {"scheme:opaque_data", ""}, + // Invalid URLs. + {"foobar", ""}, + }; + + for (size_t i = 0; i < arraysize(cases); i++) { + GURL url(cases[i].input); + GURL without_filename = url.GetWithoutFilename(); + EXPECT_EQ(cases[i].expected, without_filename.spec()) << i; + } +} + TEST(GURLTest, Replacements) { // The URL canonicalizer replacement test will handle most of these case. // The most important thing to do here is to check that the proper