diff --git a/DEPS b/DEPS index 2af7275..695987ec3 100644 --- a/DEPS +++ b/DEPS
@@ -44,7 +44,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'fc61514c46eb8d3c3dfa2a154405d76af2ae873f', + 'v8_revision': '05751f9b95cae7ce26bdcc6b426fa89cdca448f1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other.
diff --git a/ash/system/network/network_list.cc b/ash/system/network/network_list.cc index f0f1a929..58bc5f6 100644 --- a/ash/system/network/network_list.cc +++ b/ash/system/network/network_list.cc
@@ -70,7 +70,7 @@ if (!policy_prohibites_unmanaged) return false; return !managed_configuration_handler->FindPolicyByGuidAndProfile( - network->guid(), network->profile_path()); + network->guid(), network->profile_path(), nullptr /* onc_source */); } } // namespace
diff --git a/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.cc b/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.cc index a9b751b..84e5146 100644 --- a/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.cc +++ b/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.cc
@@ -11,7 +11,7 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/sequenced_task_runner.h" -#include "base/threading/sequenced_worker_pool.h" +#include "base/task_scheduler/post_task.h" #include "chrome/browser/android/offline_pages/background_loader_offliner.h" #include "chrome/browser/android/offline_pages/background_scheduler_bridge.h" #include "chrome/browser/android/offline_pages/downloads/offline_page_notification_bridge.h" @@ -36,7 +36,6 @@ #include "components/offline_pages/core/offline_page_item.h" #include "components/offline_pages/core/offline_page_model.h" #include "content/public/browser/browser_context.h" -#include "content/public/browser/browser_thread.h" #include "jni/OfflinePageEvaluationBridge_jni.h" #include "jni/SavePageRequest_jni.h" @@ -132,8 +131,7 @@ std::unique_ptr<OfflinerPolicy> policy, std::unique_ptr<Offliner> offliner) { scoped_refptr<base::SequencedTaskRunner> background_task_runner = - content::BrowserThread::GetBlockingPool()->GetSequencedTaskRunner( - content::BrowserThread::GetBlockingPool()->GetSequenceToken()); + base::CreateSequencedTaskRunnerWithTraits(base::TaskTraits().MayBlock()); Profile* profile = Profile::FromBrowserContext(context); base::FilePath queue_store_path = profile->GetPath().Append(chrome::kOfflinePageRequestQueueDirname);
diff --git a/chrome/browser/chromeos/enrollment_dialog_view.cc b/chrome/browser/chromeos/enrollment_dialog_view.cc index 33f3af5a..0fdf43cd 100644 --- a/chrome/browser/chromeos/enrollment_dialog_view.cc +++ b/chrome/browser/chromeos/enrollment_dialog_view.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/ui/browser_navigator_params.h" #include "chrome/grit/generated_resources.h" +#include "chromeos/login/login_state.h" #include "chromeos/network/client_cert_util.h" #include "chromeos/network/managed_network_configuration_handler.h" #include "chromeos/network/network_event_log.h" @@ -251,6 +252,37 @@ NET_LOG_USER("Enrollment Complete", network_id); } +// Decides if the enrollment dialog is allowed in the current login state. +bool EnrollmentDialogAllowed(Profile* profile) { + // Enrollment dialog is currently not supported on the sign-in profile. + // This also applies to lock screen, + if (ProfileHelper::IsSigninProfile(profile)) + return false; + + chromeos::LoginState::LoggedInUserType user_type = + LoginState::Get()->GetLoggedInUserType(); + switch (user_type) { + case LoginState::LOGGED_IN_USER_NONE: + return false; + case LoginState::LOGGED_IN_USER_REGULAR: + return true; + case LoginState::LOGGED_IN_USER_OWNER: + return true; + case LoginState::LOGGED_IN_USER_GUEST: + return true; + case LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT: + return false; + case LoginState::LOGGED_IN_USER_SUPERVISED: + return true; + case LoginState::LOGGED_IN_USER_KIOSK_APP: + return false; + case LoginState::LOGGED_IN_USER_ARC_KIOSK_APP: + return false; + } + NOTREACHED(); + return false; +} + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -270,6 +302,8 @@ Browser* browser = chrome::FindBrowserWithWindow(owning_window); Profile* profile = browser ? browser->profile() : ProfileManager::GetPrimaryUserProfile(); + if (!EnrollmentDialogAllowed(profile)) + return false; std::string username_hash = ProfileHelper::GetUserIdHashFromProfile(profile); onc::ONCSource onc_source = onc::ONC_SOURCE_NONE; @@ -278,14 +312,11 @@ ->managed_network_configuration_handler() ->FindPolicyByGUID(username_hash, network_id, &onc_source); - // We skip certificate patterns for device policy ONC so that an unmanaged - // user can't get to the place where a cert is presented for them - // involuntarily. - if (!policy || onc_source == onc::ONC_SOURCE_DEVICE_POLICY) + if (!policy) return false; client_cert::ClientCertConfig cert_config; - OncToClientCertConfig(*policy, &cert_config); + OncToClientCertConfig(onc_source, *policy, &cert_config); if (cert_config.client_cert_type != onc::client_cert::kPattern) return false;
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index 06ecc1d9..91c4629 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -130,22 +130,15 @@ TestParameter(NOT_IN_GUEST_MODE, "imageOpenDownloads"), TestParameter(NOT_IN_GUEST_MODE, "imageOpenDrive"))); -#if defined(DISABLE_SLOW_FILESAPP_TESTS) || defined(OFFICIAL_BUILD) -#define MAYBE_CreateNewFolder DISABLED_CreateNewFolder -#else -#define MAYBE_CreateNewFolder CreateNewFolder -#endif +// Flaky: crbug.com/715963 WRAPPED_INSTANTIATE_TEST_CASE_P( - MAYBE_CreateNewFolder, + DISABLED_CreateNewFolder, FileManagerBrowserTest, - ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, - "createNewFolderAfterSelectFile"), - TestParameter(IN_GUEST_MODE, - "createNewFolderDownloads"), - TestParameter(NOT_IN_GUEST_MODE, - "createNewFolderDownloads"), - TestParameter(NOT_IN_GUEST_MODE, - "createNewFolderDrive"))); + ::testing::Values( + TestParameter(NOT_IN_GUEST_MODE, "createNewFolderAfterSelectFile"), + TestParameter(IN_GUEST_MODE, "createNewFolderDownloads"), + TestParameter(NOT_IN_GUEST_MODE, "createNewFolderDownloads"), + TestParameter(NOT_IN_GUEST_MODE, "createNewFolderDrive"))); // Fails on official build. http://crbug.com/429294 #if defined(DISABLE_SLOW_FILESAPP_TESTS) || defined(OFFICIAL_BUILD)
diff --git a/chrome/browser/policy/cloud/test_request_interceptor.cc b/chrome/browser/policy/cloud/test_request_interceptor.cc index 40e42f5..ea725628 100644 --- a/chrome/browser/policy/cloud/test_request_interceptor.cc +++ b/chrome/browser/policy/cloud/test_request_interceptor.cc
@@ -15,9 +15,8 @@ #include "base/macros.h" #include "base/run_loop.h" #include "base/sequenced_task_runner.h" -#include "base/threading/sequenced_worker_pool.h" +#include "base/task_scheduler/post_task.h" #include "base/threading/thread_task_runner_handle.h" -#include "content/public/browser/browser_thread.h" #include "net/base/net_errors.h" #include "net/base/upload_bytes_element_reader.h" #include "net/base/upload_data_stream.h" @@ -64,12 +63,13 @@ net::URLRequest* request, net::NetworkDelegate* network_delegate) { return new net::URLRequestMockHTTPJob( - request, - network_delegate, - file_path, - content::BrowserThread::GetBlockingPool() - ->GetTaskRunnerWithShutdownBehavior( - base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); + request, network_delegate, file_path, + base::CreateTaskRunnerWithTraits( + base::TaskTraits() + .MayBlock() + .WithPriority(base::TaskPriority::BACKGROUND) + .WithShutdownBehavior( + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN))); } // Parses the upload data in |request| into |request_msg|, and validates the
diff --git a/chrome/browser/supervised_user/supervised_user_site_list.cc b/chrome/browser/supervised_user/supervised_user_site_list.cc index 8b9253b2..9a7c7162 100644 --- a/chrome/browser/supervised_user/supervised_user_site_list.cc +++ b/chrome/browser/supervised_user/supervised_user_site_list.cc
@@ -11,10 +11,8 @@ #include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "base/strings/string_number_conversions.h" -#include "base/task_runner_util.h" -#include "base/threading/sequenced_worker_pool.h" +#include "base/task_scheduler/post_task.h" #include "base/values.h" -#include "content/public/browser/browser_thread.h" #include "url/gurl.h" const int kLegacyWhitelistFormatVersion = 2; @@ -91,14 +89,16 @@ const base::FilePath& large_icon_path, const base::FilePath& path, const LoadedCallback& callback) { - base::PostTaskAndReplyWithResult( - content::BrowserThread::GetBlockingPool() - ->GetTaskRunnerWithShutdownBehavior( - base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN) - .get(), - FROM_HERE, base::Bind(&ReadFileOnBlockingThread, path), - base::Bind(&SupervisedUserSiteList::OnJsonLoaded, id, title, - large_icon_path, path, base::TimeTicks::Now(), callback)); + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, + base::TaskTraits() + .MayBlock() + .WithPriority(base::TaskPriority::BACKGROUND) + .WithShutdownBehavior( + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN), + base::BindOnce(&ReadFileOnBlockingThread, path), + base::BindOnce(&SupervisedUserSiteList::OnJsonLoaded, id, title, + large_icon_path, path, base::TimeTicks::Now(), callback)); } SupervisedUserSiteList::SupervisedUserSiteList(
diff --git a/chrome/common/extensions/api/notifications.idl b/chrome/common/extensions/api/notifications.idl index d3cc1ac..1827388 100644 --- a/chrome/common/extensions/api/notifications.idl +++ b/chrome/common/extensions/api/notifications.idl
@@ -10,9 +10,11 @@ basic, // icon, title, message, expandedMessage, image, up to two buttons + [deprecated="The image is not visible for Mac OS X users."] image, - // icon, title, message, items, up to two buttons + // icon, title, message, items, up to two buttons. Users on Mac OS X only + // see the first item. list, // icon, title, message, progress, up to two buttons @@ -44,6 +46,7 @@ dictionary NotificationButton { DOMString title; + [deprecated="Button icons not visible for Mac OS X users."] DOMString? iconUrl; [nodoc] NotificationBitmap? iconBitmap; }; @@ -64,9 +67,10 @@ // A URL to the app icon mask. URLs have the same restrictions as // $(ref:notifications.NotificationOptions.iconUrl iconUrl). - // + // // The app icon mask should be in alpha channel, as only the alpha channel // of the image will be considered. + [deprecated="The app icon mask is not visible for Mac OS X users."] DOMString? appIconMaskUrl; [nodoc] NotificationBitmap? appIconMaskBitmap; @@ -98,12 +102,14 @@ [nodoc] DOMString? expandedMessage; // A URL to the image thumbnail for image-type notifications. - // URLs have the same restrictions as + // URLs have the same restrictions as // $(ref:notifications.NotificationOptions.iconUrl iconUrl). + [deprecated="The image is not visible for Mac OS X users."] DOMString? imageUrl; [nodoc] NotificationBitmap? imageBitmap; - // Items for multi-item notifications. + // Items for multi-item notifications. Users on Mac OS X only see the first + // item. NotificationItem[]? items; // Current progress ranges from 0 to 100.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index fd7c3df..e69c13f 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -395,7 +395,6 @@ "../browser/ui/views/accessibility/navigation_accessibility_uitest_win.cc", "../browser/ui/webui/options/language_dictionary_interactive_uitest.cc", "../browser/ui/webui/options/language_options_interactive_uitest.cc", - "//ui/base/clipboard/clipboard_android_unittest.cc", "//ui/base/clipboard/clipboard_unittest.cc", "base/always_on_top_window_killer_win.cc", "base/always_on_top_window_killer_win.h",
diff --git a/chromeos/cert_loader.cc b/chromeos/cert_loader.cc index 4e4131ba..0b9a638 100644 --- a/chromeos/cert_loader.cc +++ b/chromeos/cert_loader.cc
@@ -9,8 +9,9 @@ #include "base/bind.h" #include "base/location.h" +#include "base/memory/ptr_util.h" #include "base/strings/string_number_conversions.h" -#include "base/task_runner_util.h" +#include "base/task_scheduler/post_task.h" #include "base/threading/worker_pool.h" #include "crypto/nss_util.h" #include "crypto/scoped_nss_types.h" @@ -20,7 +21,56 @@ namespace chromeos { -static CertLoader* g_cert_loader = NULL; +namespace { + +// Checks if |certificate| is on the given |slot|. +bool IsCertificateOnSlot(const net::X509Certificate* certificate, + PK11SlotInfo* slot) { + crypto::ScopedPK11SlotList slots_for_cert( + PK11_GetAllSlotsForCert(certificate->os_cert_handle(), nullptr)); + if (!slots_for_cert) + return false; + + for (PK11SlotListElement* slot_element = + PK11_GetFirstSafe(slots_for_cert.get()); + slot_element; slot_element = PK11_GetNextSafe(slots_for_cert.get(), + slot_element, PR_FALSE)) { + if (slot_element->slot == slot) { + // All previously visited elements have been freed by PK11_GetNextSafe, + // but we're not calling that for the last one, so free it explicitly. + // The slots_for_cert list itself will be freed because ScopedPK11SlotList + // is a unique_ptr. + PK11_FreeSlotListElement(slots_for_cert.get(), slot_element); + return true; + } + } + return false; +} + +// Goes through all certificates in |all_certs| and copies those certificates +// which are on |system_slot| to a new list. +std::unique_ptr<net::CertificateList> FilterSystemTokenCertificates( + const net::CertificateList* all_certs, + crypto::ScopedPK11Slot system_slot) { + VLOG(1) << "FilterSystemTokenCertificates"; + std::unique_ptr<net::CertificateList> system_certs = + base::MakeUnique<net::CertificateList>(); + if (!system_slot) + return system_certs; + + // Extract certificates which are in the system token into the + // |system_certs_| sublist. + for (const auto& cert : *all_certs) { + if (IsCertificateOnSlot(cert.get(), system_slot.get())) { + system_certs->push_back(cert); + } + } + return system_certs; +} + +} // namespace + +static CertLoader* g_cert_loader = nullptr; static bool g_force_hardware_backed_for_test = false; // static @@ -33,7 +83,7 @@ void CertLoader::Shutdown() { CHECK(g_cert_loader); delete g_cert_loader; - g_cert_loader = NULL; + g_cert_loader = nullptr; } // static @@ -51,10 +101,9 @@ : certificates_loaded_(false), certificates_update_required_(false), certificates_update_running_(false), - database_(NULL), - cert_list_(new net::CertificateList), - weak_factory_(this) { -} + database_(nullptr), + all_certs_(base::MakeUnique<net::CertificateList>()), + weak_factory_(this) {} CertLoader::~CertLoader() { net::CertDatabase::GetInstance()->RemoveObserver(this); @@ -116,8 +165,8 @@ DCHECK(slot_id); CERTCertificateStr* cert_handle = cert.os_cert_handle(); - SECKEYPrivateKey *priv_key = - PK11_FindKeyByAnyCert(cert_handle, NULL /* wincx */); + SECKEYPrivateKey* priv_key = + PK11_FindKeyByAnyCert(cert_handle, nullptr /* wincx */); if (!priv_key) return std::string(); @@ -136,7 +185,7 @@ } void CertLoader::LoadCertificates() { - CHECK(thread_checker_.CalledOnValidThread()); + DCHECK(thread_checker_.CalledOnValidThread()); VLOG(1) << "LoadCertificates: " << certificates_update_running_; if (certificates_update_running_) { @@ -148,17 +197,38 @@ certificates_update_required_ = false; database_->ListCerts( - base::Bind(&CertLoader::UpdateCertificates, weak_factory_.GetWeakPtr())); + base::Bind(&CertLoader::CertificatesLoaded, weak_factory_.GetWeakPtr())); +} + +void CertLoader::CertificatesLoaded( + std::unique_ptr<net::CertificateList> all_certs) { + DCHECK(thread_checker_.CalledOnValidThread()); + VLOG(1) << "CertificatesLoaded: " << all_certs->size(); + + crypto::ScopedPK11Slot system_slot = database_->GetSystemSlot(); + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, + base::TaskTraits() + .WithShutdownBehavior( + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) + .MayBlock(), + base::BindOnce(&FilterSystemTokenCertificates, + base::Unretained(all_certs.get()), std::move(system_slot)), + base::BindOnce(&CertLoader::UpdateCertificates, + weak_factory_.GetWeakPtr(), std::move(all_certs))); } void CertLoader::UpdateCertificates( - std::unique_ptr<net::CertificateList> cert_list) { - CHECK(thread_checker_.CalledOnValidThread()); + std::unique_ptr<net::CertificateList> all_certs, + std::unique_ptr<net::CertificateList> system_certs) { + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(certificates_update_running_); - VLOG(1) << "UpdateCertificates: " << cert_list->size(); + VLOG(1) << "UpdateCertificates: " << all_certs->size() << " (" + << system_certs->size() << " on system slot)"; // Ignore any existing certificates. - cert_list_ = std::move(cert_list); + all_certs_ = std::move(all_certs); + system_certs_ = std::move(system_certs); bool initial_load = !certificates_loaded_; certificates_loaded_ = true; @@ -171,7 +241,7 @@ void CertLoader::NotifyCertificatesLoaded(bool initial_load) { for (auto& observer : observers_) - observer.OnCertificatesLoaded(*cert_list_, initial_load); + observer.OnCertificatesLoaded(*all_certs_, initial_load); } void CertLoader::OnCertDBChanged() {
diff --git a/chromeos/cert_loader.h b/chromeos/cert_loader.h index 7243c6d..7faedbf7 100644 --- a/chromeos/cert_loader.h +++ b/chromeos/cert_loader.h
@@ -35,10 +35,10 @@ public: class Observer { public: - // Called when the certificates, passed for convenience as |cert_list|, + // Called when the certificates, passed for convenience as |all_certs|, // have completed loading. |initial_load| is true the first time this // is called. - virtual void OnCertificatesLoaded(const net::CertificateList& cert_list, + virtual void OnCertificatesLoaded(const net::CertificateList& all_certs, bool initial_load) = 0; protected: @@ -83,8 +83,19 @@ bool certificates_loaded() const { return certificates_loaded_; } - // This will be empty until certificates_loaded() is true. - const net::CertificateList& cert_list() const { return *cert_list_; } + // Returns all certificates. This will be empty until certificates_loaded() is + // true. + const net::CertificateList& all_certs() const { + DCHECK(thread_checker_.CalledOnValidThread()); + return *all_certs_; + } + + // Returns certificates from the system token. This will be empty until + // certificates_loaded() is true. + const net::CertificateList& system_certs() const { + DCHECK(thread_checker_.CalledOnValidThread()); + return *system_certs_; + } // Called in tests if |IsCertificateHardwareBacked()| should always return // true. @@ -98,8 +109,12 @@ // progress, will start a reload once the current task is finished. void LoadCertificates(); + // Called when the underlying NSS database finished loading certificates. + void CertificatesLoaded(std::unique_ptr<net::CertificateList> all_certs); + // Called if a certificate load task is finished. - void UpdateCertificates(std::unique_ptr<net::CertificateList> cert_list); + void UpdateCertificates(std::unique_ptr<net::CertificateList> all_certs, + std::unique_ptr<net::CertificateList> system_certs); void NotifyCertificatesLoaded(bool initial_load); @@ -117,8 +132,12 @@ // should be loaded. net::NSSCertDatabase* database_; - // Cached Certificates loaded from the database. - std::unique_ptr<net::CertificateList> cert_list_; + // Cached certificates loaded from the database. + std::unique_ptr<net::CertificateList> all_certs_; + + // Cached certificates from system token. Currently this is a sublist of + // |all_certs_|. + std::unique_ptr<net::CertificateList> system_certs_; base::ThreadChecker thread_checker_;
diff --git a/chromeos/cert_loader_unittest.cc b/chromeos/cert_loader_unittest.cc index 6056f76..405cf29d 100644 --- a/chromeos/cert_loader_unittest.cc +++ b/chromeos/cert_loader_unittest.cc
@@ -13,6 +13,7 @@ #include "base/files/file_util.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/test/scoped_task_scheduler.h" #include "crypto/scoped_nss_types.h" #include "crypto/scoped_test_nss_db.h" #include "net/cert/nss_cert_database_chromeos.h" @@ -45,7 +46,8 @@ std::move(private_slot)) {} ~TestNSSCertDatabase() override {} - void NotifyOfCertAdded(const net::X509Certificate* cert) { + // Make this method visible in the public interface. + void NotifyObserversCertDBChanged() { NSSCertDatabaseChromeOS::NotifyObserversCertDBChanged(); } }; @@ -54,7 +56,9 @@ public CertLoader::Observer { public: CertLoaderTest() - : cert_loader_(nullptr), certificates_loaded_events_count_(0U) {} + : cert_loader_(nullptr), + scoped_task_scheduler_(&message_loop_), + certificates_loaded_events_count_(0U) {} ~CertLoaderTest() override {} @@ -80,6 +84,17 @@ GetAndResetCertificatesLoadedEventsCount(); } + // Starts the cert loader with a primary cert database which has access to the + // system token. + void StartCertLoaderWithPrimaryDBAndSystemToken() { + CreateCertDatabase(&primary_db_, &primary_certdb_); + AddSystemToken(primary_certdb_.get()); + cert_loader_->StartWithNSSDB(primary_certdb_.get()); + + base::RunLoop().RunUntilIdle(); + GetAndResetCertificatesLoadedEventsCount(); + } + // CertLoader::Observer: // The test keeps count of times the observer method was called. void OnCertificatesLoaded(const net::CertificateList& cert_list, @@ -125,17 +140,27 @@ ASSERT_TRUE(failed.empty()); } + // Import a client cert and key into a PKCS11 slot. Then notify + // |database_to_notify| (which is presumably using that slot) that new + // certificates are available. scoped_refptr<net::X509Certificate> ImportClientCertAndKey( - TestNSSCertDatabase* database) { + TestNSSCertDatabase* database_to_notify, + PK11SlotInfo* slot_to_use) { // Import a client cert signed by that CA. scoped_refptr<net::X509Certificate> client_cert( net::ImportClientCertAndKeyFromFile(net::GetTestCertsDirectory(), "client_1.pem", "client_1.pk8", - database->GetPrivateSlot().get())); - database->NotifyOfCertAdded(client_cert.get()); + slot_to_use)); + database_to_notify->NotifyObserversCertDBChanged(); return client_cert; } + // Import a client cert into |database|'s private slot. + scoped_refptr<net::X509Certificate> ImportClientCertAndKey( + TestNSSCertDatabase* database) { + return ImportClientCertAndKey(database, database->GetPrivateSlot().get()); + } + CertLoader* cert_loader_; // The user is primary as the one whose certificates CertLoader handles, it @@ -144,9 +169,20 @@ crypto::ScopedTestNSSDB primary_db_; std::unique_ptr<TestNSSCertDatabase> primary_certdb_; + // Additional NSS DB simulating the system token. + crypto::ScopedTestNSSDB system_db_; + base::MessageLoop message_loop_; private: + // Adds the PKCS11 slot from |system_db_| to |certdb| as system slot. + void AddSystemToken(TestNSSCertDatabase* certdb) { + ASSERT_TRUE(system_db_.is_open()); + certdb->SetSystemSlot( + crypto::ScopedPK11Slot(PK11_ReferenceSlot(system_db_.slot()))); + } + + base::test::ScopedTaskScheduler scoped_task_scheduler_; size_t certificates_loaded_events_count_; }; @@ -161,7 +197,7 @@ EXPECT_FALSE(cert_loader_->certificates_loaded()); EXPECT_TRUE(cert_loader_->CertificatesLoading()); - EXPECT_TRUE(cert_loader_->cert_list().empty()); + EXPECT_TRUE(cert_loader_->all_certs().empty()); ASSERT_EQ(0U, GetAndResetCertificatesLoadedEventsCount()); base::RunLoop().RunUntilIdle(); @@ -171,7 +207,7 @@ EXPECT_FALSE(cert_loader_->CertificatesLoading()); // Default CA cert roots should get loaded. - EXPECT_FALSE(cert_loader_->cert_list().empty()); + EXPECT_FALSE(cert_loader_->all_certs().empty()); } TEST_F(CertLoaderTest, CertLoaderUpdatesCertListOnNewCert) { @@ -183,7 +219,7 @@ // Certs are loaded asynchronously, so the new cert should not yet be in the // cert list. EXPECT_FALSE( - IsCertInCertificateList(certs[0].get(), cert_loader_->cert_list())); + IsCertInCertificateList(certs[0].get(), cert_loader_->all_certs())); ASSERT_EQ(0U, GetAndResetCertificatesLoadedEventsCount()); base::RunLoop().RunUntilIdle(); @@ -191,7 +227,7 @@ // The certificate list should be updated now, as the message loop's been run. EXPECT_TRUE( - IsCertInCertificateList(certs[0].get(), cert_loader_->cert_list())); + IsCertInCertificateList(certs[0].get(), cert_loader_->all_certs())); EXPECT_FALSE(cert_loader_->IsCertificateHardwareBacked(certs[0].get())); } @@ -209,7 +245,7 @@ base::RunLoop().RunUntilIdle(); EXPECT_FALSE( - IsCertInCertificateList(certs[0].get(), cert_loader_->cert_list())); + IsCertInCertificateList(certs[0].get(), cert_loader_->all_certs())); } TEST_F(CertLoaderTest, ClientLoaderUpdateOnNewClientCert) { @@ -222,7 +258,24 @@ base::RunLoop().RunUntilIdle(); EXPECT_EQ(1U, GetAndResetCertificatesLoadedEventsCount()); - EXPECT_TRUE(IsCertInCertificateList(cert.get(), cert_loader_->cert_list())); + EXPECT_TRUE(IsCertInCertificateList(cert.get(), cert_loader_->all_certs())); +} + +TEST_F(CertLoaderTest, ClientLoaderUpdateOnNewClientCertInSystemToken) { + StartCertLoaderWithPrimaryDBAndSystemToken(); + + EXPECT_TRUE(cert_loader_->system_certs().empty()); + scoped_refptr<net::X509Certificate> cert(ImportClientCertAndKey( + primary_certdb_.get(), primary_certdb_->GetSystemSlot().get())); + + ASSERT_EQ(0U, GetAndResetCertificatesLoadedEventsCount()); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1U, GetAndResetCertificatesLoadedEventsCount()); + + EXPECT_TRUE(IsCertInCertificateList(cert.get(), cert_loader_->all_certs())); + EXPECT_EQ(1U, cert_loader_->system_certs().size()); + EXPECT_TRUE( + IsCertInCertificateList(cert.get(), cert_loader_->system_certs())); } TEST_F(CertLoaderTest, CertLoaderNoUpdateOnNewClientCertInSecondaryDb) { @@ -237,7 +290,7 @@ base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(IsCertInCertificateList(cert.get(), cert_loader_->cert_list())); + EXPECT_FALSE(IsCertInCertificateList(cert.get(), cert_loader_->all_certs())); } TEST_F(CertLoaderTest, UpdatedOnCertRemoval) { @@ -249,7 +302,7 @@ base::RunLoop().RunUntilIdle(); ASSERT_EQ(1U, GetAndResetCertificatesLoadedEventsCount()); - ASSERT_TRUE(IsCertInCertificateList(cert.get(), cert_loader_->cert_list())); + ASSERT_TRUE(IsCertInCertificateList(cert.get(), cert_loader_->all_certs())); primary_certdb_->DeleteCertAndKey(cert.get()); @@ -257,7 +310,7 @@ base::RunLoop().RunUntilIdle(); EXPECT_EQ(1U, GetAndResetCertificatesLoadedEventsCount()); - ASSERT_FALSE(IsCertInCertificateList(cert.get(), cert_loader_->cert_list())); + ASSERT_FALSE(IsCertInCertificateList(cert.get(), cert_loader_->all_certs())); } TEST_F(CertLoaderTest, UpdatedOnCACertTrustChange) { @@ -269,7 +322,7 @@ base::RunLoop().RunUntilIdle(); ASSERT_EQ(1U, GetAndResetCertificatesLoadedEventsCount()); ASSERT_TRUE( - IsCertInCertificateList(certs[0].get(), cert_loader_->cert_list())); + IsCertInCertificateList(certs[0].get(), cert_loader_->all_certs())); // The value that should have been set by |ImportCACert|. ASSERT_EQ(net::NSSCertDatabase::TRUST_DEFAULT,
diff --git a/chromeos/chromeos_paths.cc b/chromeos/chromeos_paths.cc index 53177d2..e5c12b9 100644 --- a/chromeos/chromeos_paths.cc +++ b/chromeos/chromeos_paths.cc
@@ -32,8 +32,8 @@ const base::FilePath::CharType kMachineHardwareInfoFileName[] = FILE_PATH_LITERAL("/tmp/machine-info"); -const base::FilePath::CharType kVpdFileName[] = - FILE_PATH_LITERAL("/var/log/vpd_2.0.txt"); +const base::FilePath::CharType kVpdFileName[] = FILE_PATH_LITERAL( + "/mnt/stateful_partition/unencrypted/cache/vpd/filtered.txt"); const base::FilePath::CharType kUptimeFileName[] = FILE_PATH_LITERAL("/proc/uptime");
diff --git a/chromeos/network/auto_connect_handler.cc b/chromeos/network/auto_connect_handler.cc index 69d84a5..885068dc 100644 --- a/chromeos/network/auto_connect_handler.cc +++ b/chromeos/network/auto_connect_handler.cc
@@ -241,7 +241,7 @@ const bool network_is_policy_managed = !network->profile_path().empty() && !network->guid().empty() && managed_configuration_handler_->FindPolicyByGuidAndProfile( - network->guid(), network->profile_path()); + network->guid(), network->profile_path(), nullptr /* onc_source */); if (network_is_policy_managed) continue;
diff --git a/chromeos/network/client_cert_resolver.cc b/chromeos/network/client_cert_resolver.cc index 788e5ee9..74cb136 100644 --- a/chromeos/network/client_cert_resolver.cc +++ b/chromeos/network/client_cert_resolver.cc
@@ -13,6 +13,7 @@ #include "base/bind.h" #include "base/location.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/task_scheduler/post_task.h" @@ -191,25 +192,35 @@ // Searches for matches between |networks| and |certs| and writes matches to // |matches|. Because this calls NSS functions and is potentially slow, it must // be run on a worker thread. -void FindCertificateMatches(const net::CertificateList& certs, - std::vector<NetworkAndCertPattern>* networks, - base::Time now, - NetworkCertMatches* matches) { - std::vector<CertAndIssuer> client_certs( - CreateSortedCertAndIssuerList(certs, now)); +std::unique_ptr<NetworkCertMatches> FindCertificateMatches( + const net::CertificateList& all_certs, + const net::CertificateList& system_certs, + std::vector<NetworkAndCertPattern>* networks, + base::Time now) { + std::unique_ptr<NetworkCertMatches> matches = + base::MakeUnique<NetworkCertMatches>(); + + std::vector<CertAndIssuer> all_client_certs( + CreateSortedCertAndIssuerList(all_certs, now)); + std::vector<CertAndIssuer> system_client_certs( + CreateSortedCertAndIssuerList(system_certs, now)); for (std::vector<NetworkAndCertPattern>::const_iterator it = networks->begin(); it != networks->end(); ++it) { - std::vector<CertAndIssuer>::iterator cert_it = - std::find_if(client_certs.begin(), - client_certs.end(), - MatchCertWithPattern(it->cert_config.pattern)); + // Use only certs from the system token if the source of the client cert + // pattern is device policy. + std::vector<CertAndIssuer>* client_certs = + it->cert_config.onc_source == ::onc::ONC_SOURCE_DEVICE_POLICY + ? &system_client_certs + : &all_client_certs; + auto cert_it = std::find_if(client_certs->begin(), client_certs->end(), + MatchCertWithPattern(it->cert_config.pattern)); std::string pkcs11_id; int slot_id = -1; std::string identity; - if (cert_it == client_certs.end()) { + if (cert_it == client_certs->end()) { VLOG(1) << "Couldn't find a matching client cert for network " << it->service_path; // Leave |pkcs11_id| empty to indicate that no cert was found for this @@ -256,6 +267,7 @@ it->service_path, it->cert_config.location, pkcs11_id, slot_id, identity)); } + return matches; } void LogError(const std::string& service_path, @@ -325,15 +337,23 @@ // static bool ClientCertResolver::ResolveCertificatePatternSync( const client_cert::ConfigType client_cert_type, - const CertificatePattern& pattern, + const client_cert::ClientCertConfig& client_cert_config, base::DictionaryValue* shill_properties) { - // Prepare and sort the list of known client certs. - std::vector<CertAndIssuer> client_certs(CreateSortedCertAndIssuerList( - CertLoader::Get()->cert_list(), base::Time::Now())); + // Prepare and sort the list of known client certs. Use only certs from the + // system token if the source of the client cert pattern is device policy. + std::vector<CertAndIssuer> client_certs; + if (client_cert_config.onc_source == ::onc::ONC_SOURCE_DEVICE_POLICY) { + client_certs = CreateSortedCertAndIssuerList( + CertLoader::Get()->system_certs(), base::Time::Now()); + } else { + client_certs = CreateSortedCertAndIssuerList(CertLoader::Get()->all_certs(), + base::Time::Now()); + } // Search for a certificate matching the pattern. - std::vector<CertAndIssuer>::iterator cert_it = std::find_if( - client_certs.begin(), client_certs.end(), MatchCertWithPattern(pattern)); + std::vector<CertAndIssuer>::iterator cert_it = + std::find_if(client_certs.begin(), client_certs.end(), + MatchCertWithPattern(client_cert_config.pattern)); if (cert_it == client_certs.end()) { VLOG(1) << "Couldn't find a matching client cert"; @@ -452,9 +472,10 @@ if (network->profile_path().empty()) continue; + onc::ONCSource onc_source = onc::ONC_SOURCE_NONE; const base::DictionaryValue* policy = managed_network_config_handler_->FindPolicyByGuidAndProfile( - network->guid(), network->profile_path()); + network->guid(), network->profile_path(), &onc_source); if (!policy) { VLOG(1) << "The policy for network " << network->path() << " with GUID " @@ -466,7 +487,7 @@ VLOG(2) << "Inspecting network " << network->path(); client_cert::ClientCertConfig cert_config; - OncToClientCertConfig(*policy, &cert_config); + OncToClientCertConfig(onc_source, *policy, &cert_config); // Skip networks that don't have a ClientCertPattern. if (cert_config.client_cert_type != ::onc::client_cert::kPattern) @@ -493,16 +514,17 @@ VLOG(2) << "Start task for resolving client cert patterns."; resolve_task_running_ = true; - NetworkCertMatches* matches = new NetworkCertMatches; - base::PostTaskWithTraitsAndReply( - FROM_HERE, base::TaskTraits() - .WithShutdownBehavior( - base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) - .MayBlock(), - base::Bind(&FindCertificateMatches, CertLoader::Get()->cert_list(), - base::Owned(networks_to_resolve.release()), Now(), matches), + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, + base::TaskTraits() + .WithShutdownBehavior( + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) + .MayBlock(), + base::Bind(&FindCertificateMatches, CertLoader::Get()->all_certs(), + CertLoader::Get()->system_certs(), + base::Owned(networks_to_resolve.release()), Now()), base::Bind(&ClientCertResolver::ConfigureCertificates, - weak_ptr_factory_.GetWeakPtr(), base::Owned(matches))); + weak_ptr_factory_.GetWeakPtr())); } void ClientCertResolver::ResolvePendingNetworks() { @@ -523,7 +545,8 @@ ResolveNetworks(networks_to_resolve); } -void ClientCertResolver::ConfigureCertificates(NetworkCertMatches* matches) { +void ClientCertResolver::ConfigureCertificates( + std::unique_ptr<NetworkCertMatches> matches) { for (NetworkCertMatches::const_iterator it = matches->begin(); it != matches->end(); ++it) { VLOG(1) << "Configuring certificate of network " << it->service_path;
diff --git a/chromeos/network/client_cert_resolver.h b/chromeos/network/client_cert_resolver.h index 63d6d89..669109c46 100644 --- a/chromeos/network/client_cert_resolver.h +++ b/chromeos/network/client_cert_resolver.h
@@ -79,7 +79,7 @@ // expiration. static bool ResolveCertificatePatternSync( const client_cert::ConfigType client_cert_type, - const CertificatePattern& pattern, + const client_cert::ClientCertConfig& client_cert_config, base::DictionaryValue* shill_properties); private: @@ -105,7 +105,8 @@ // |matches| contains networks for which a matching certificate was found. // Configures these networks. - void ConfigureCertificates(std::vector<NetworkAndMatchingCert>* matches); + void ConfigureCertificates( + std::unique_ptr<std::vector<NetworkAndMatchingCert>> matches); // Trigger a ResolveRequestCompleted event on all observers. void NotifyResolveRequestCompleted();
diff --git a/chromeos/network/client_cert_resolver_unittest.cc b/chromeos/network/client_cert_resolver_unittest.cc index 8caac7a..0657648 100644 --- a/chromeos/network/client_cert_resolver_unittest.cc +++ b/chromeos/network/client_cert_resolver_unittest.cc
@@ -53,16 +53,12 @@ class ClientCertResolverTest : public testing::Test, public ClientCertResolver::Observer { public: - ClientCertResolverTest() - : network_properties_changed_count_(0), - service_test_(nullptr), - profile_test_(nullptr), - cert_loader_(nullptr), - scoped_task_scheduler_(&message_loop_) {} + ClientCertResolverTest() : scoped_task_scheduler_(&message_loop_) {} ~ClientCertResolverTest() override {} void SetUp() override { ASSERT_TRUE(test_nssdb_.is_open()); + ASSERT_TRUE(test_system_nssdb_.is_open()); // Use the same DB for public and private slot. test_nsscertdb_.reset(new net::NSSCertDatabaseChromeOS( @@ -86,10 +82,12 @@ } void TearDown() override { - client_cert_resolver_->RemoveObserver(this); + if (client_cert_resolver_) + client_cert_resolver_->RemoveObserver(this); client_cert_resolver_.reset(); test_clock_.reset(); - network_state_handler_->Shutdown(); + if (network_state_handler_) + network_state_handler_->Shutdown(); managed_config_handler_.reset(); network_config_handler_.reset(); network_profile_handler_.reset(); @@ -137,6 +135,16 @@ ASSERT_TRUE(test_client_cert_.get()); } + void SetupTestCertInSystemToken(const std::string& prefix) { + test_nsscertdb_->SetSystemSlot( + crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_system_nssdb_.slot()))); + + test_client_cert_ = net::ImportClientCertAndKeyFromFile( + net::GetTestCertsDirectory(), prefix + ".pem", prefix + ".pk8", + test_system_nssdb_.slot()); + ASSERT_TRUE(test_client_cert_.get()); + } + void SetupNetworkHandlers() { network_state_handler_ = NetworkStateHandler::InitializeForTest(); network_profile_handler_.reset(new NetworkProfileHandler()); @@ -184,7 +192,7 @@ // Sets up a policy with a certificate pattern that matches any client cert // with a certain Issuer CN. It will match the test client cert. - void SetupPolicyMatchingIssuerCN() { + void SetupPolicyMatchingIssuerCN(onc::ONCSource onc_source) { const char* kTestPolicy = "[ { \"GUID\": \"wifi_stub\"," " \"Name\": \"wifi_stub\"," @@ -213,15 +221,40 @@ base::ListValue* policy = nullptr; ASSERT_TRUE(policy_value->GetAsList(&policy)); + std::string user_hash = + onc_source == onc::ONC_SOURCE_USER_POLICY ? kUserHash : ""; managed_config_handler_->SetPolicy( - onc::ONC_SOURCE_USER_POLICY, kUserHash, *policy, + onc_source, user_hash, *policy, base::DictionaryValue() /* no global network config */); } + void SetupCertificateConfigMatchingIssuerCN( + onc::ONCSource onc_source, + client_cert::ClientCertConfig* client_cert_config) { + const char* kTestOncPattern = + "{" + " \"Issuer\": {" + " \"CommonName\": \"B CA\"" + " }" + "}"; + std::string error; + std::unique_ptr<base::Value> onc_pattern_value = + base::JSONReader::ReadAndReturnError( + kTestOncPattern, base::JSON_ALLOW_TRAILING_COMMAS, nullptr, &error); + ASSERT_TRUE(onc_pattern_value) << error; + + base::DictionaryValue* onc_pattern_dict; + onc_pattern_value->GetAsDictionary(&onc_pattern_dict); + + client_cert_config->onc_source = onc_source; + client_cert_config->pattern.ReadFromONCDictionary(*onc_pattern_dict); + } + // Sets up a policy with a certificate pattern that matches any client cert // that is signed by the test CA cert (stored in |test_ca_cert_pem_|). In // particular it will match the test client cert. - void SetupPolicyMatchingIssuerPEM(const std::string& identity) { + void SetupPolicyMatchingIssuerPEM(onc::ONCSource onc_source, + const std::string& identity) { const char* kTestPolicyTemplate = "[ { \"GUID\": \"wifi_stub\"," " \"Name\": \"wifi_stub\"," @@ -251,10 +284,10 @@ base::ListValue* policy = nullptr; ASSERT_TRUE(policy_value->GetAsList(&policy)); + std::string user_hash = + onc_source == onc::ONC_SOURCE_USER_POLICY ? kUserHash : ""; managed_config_handler_->SetPolicy( - onc::ONC_SOURCE_USER_POLICY, - kUserHash, - *policy, + onc_source, user_hash, *policy, base::DictionaryValue() /* no global network config */); } @@ -273,10 +306,11 @@ properties->GetStringWithoutPathExpansion(prop_name, prop_value); } - int network_properties_changed_count_; + int network_properties_changed_count_ = 0; std::string test_cert_id_; std::unique_ptr<base::SimpleTestClock> test_clock_; std::unique_ptr<ClientCertResolver> client_cert_resolver_; + CertLoader* cert_loader_ = nullptr; private: // ClientCertResolver::Observer: @@ -285,9 +319,8 @@ ++network_properties_changed_count_; } - ShillServiceClient::TestInterface* service_test_; - ShillProfileClient::TestInterface* profile_test_; - CertLoader* cert_loader_; + ShillServiceClient::TestInterface* service_test_ = nullptr; + ShillProfileClient::TestInterface* profile_test_ = nullptr; std::unique_ptr<NetworkStateHandler> network_state_handler_; std::unique_ptr<NetworkProfileHandler> network_profile_handler_; std::unique_ptr<NetworkConfigurationHandler> network_config_handler_; @@ -298,6 +331,7 @@ scoped_refptr<net::X509Certificate> test_client_cert_; std::string test_ca_cert_pem_; crypto::ScopedTestNSSDB test_nssdb_; + crypto::ScopedTestNSSDB test_system_nssdb_; std::unique_ptr<net::NSSCertDatabaseChromeOS> test_nsscertdb_; DISALLOW_COPY_AND_ASSIGN(ClientCertResolverTest); @@ -310,7 +344,7 @@ base::RunLoop().RunUntilIdle(); network_properties_changed_count_ = 0; SetupNetworkHandlers(); - SetupPolicyMatchingIssuerPEM(""); + SetupPolicyMatchingIssuerPEM(onc::ONC_SOURCE_USER_POLICY, ""); base::RunLoop().RunUntilIdle(); // Verify that no client certificate was configured. @@ -327,7 +361,7 @@ base::RunLoop().RunUntilIdle(); SetupNetworkHandlers(); - SetupPolicyMatchingIssuerCN(); + SetupPolicyMatchingIssuerCN(onc::ONC_SOURCE_USER_POLICY); base::RunLoop().RunUntilIdle(); network_properties_changed_count_ = 0; @@ -348,7 +382,7 @@ base::RunLoop().RunUntilIdle(); SetupNetworkHandlers(); - SetupPolicyMatchingIssuerPEM(""); + SetupPolicyMatchingIssuerPEM(onc::ONC_SOURCE_USER_POLICY, ""); base::RunLoop().RunUntilIdle(); network_properties_changed_count_ = 0; @@ -373,7 +407,7 @@ // Policy application will trigger the ClientCertResolver. network_properties_changed_count_ = 0; - SetupPolicyMatchingIssuerPEM(""); + SetupPolicyMatchingIssuerPEM(onc::ONC_SOURCE_USER_POLICY, ""); base::RunLoop().RunUntilIdle(); // Verify that the resolver positively matched the pattern in the policy with @@ -390,7 +424,7 @@ base::RunLoop().RunUntilIdle(); SetupNetworkHandlers(); - SetupPolicyMatchingIssuerPEM(""); + SetupPolicyMatchingIssuerPEM(onc::ONC_SOURCE_USER_POLICY, ""); base::RunLoop().RunUntilIdle(); StartCertLoader(); @@ -414,13 +448,130 @@ EXPECT_EQ(std::string(), pkcs11_id); } +TEST_F(ClientCertResolverTest, UserPolicyUsesSystemToken) { + SetupTestCertInSystemToken("client_1"); + SetupWifi(); + base::RunLoop().RunUntilIdle(); + + SetupNetworkHandlers(); + SetupPolicyMatchingIssuerCN(onc::ONC_SOURCE_USER_POLICY); + base::RunLoop().RunUntilIdle(); + + StartCertLoader(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1U, cert_loader_->system_certs().size()); + + // Verify that the resolver positively matched the pattern in the policy with + // the test client cert and configured the network. + std::string pkcs11_id; + GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id); + EXPECT_EQ(test_cert_id_, pkcs11_id); +} + +TEST_F(ClientCertResolverTest, UserPolicyUsesSystemTokenSync) { + SetupTestCertInSystemToken("client_1"); + StartCertLoader(); + base::RunLoop().RunUntilIdle(); + + client_cert::ClientCertConfig client_cert_config; + SetupCertificateConfigMatchingIssuerCN(onc::ONC_SOURCE_USER_POLICY, + &client_cert_config); + + base::DictionaryValue shill_properties; + ClientCertResolver::ResolveCertificatePatternSync( + client_cert::CONFIG_TYPE_EAP, client_cert_config, &shill_properties); + std::string pkcs11_id; + shill_properties.GetStringWithoutPathExpansion(shill::kEapCertIdProperty, + &pkcs11_id); + EXPECT_EQ(test_cert_id_, pkcs11_id); +} + +TEST_F(ClientCertResolverTest, DevicePolicyUsesSystemToken) { + SetupTestCertInSystemToken("client_1"); + SetupWifi(); + base::RunLoop().RunUntilIdle(); + + SetupNetworkHandlers(); + SetupPolicyMatchingIssuerCN(onc::ONC_SOURCE_USER_POLICY); + base::RunLoop().RunUntilIdle(); + + StartCertLoader(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1U, cert_loader_->system_certs().size()); + + // Verify that the resolver positively matched the pattern in the policy with + // the test client cert and configured the network. + std::string pkcs11_id; + GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id); + EXPECT_EQ(test_cert_id_, pkcs11_id); +} + +TEST_F(ClientCertResolverTest, DevicePolicyUsesSystemTokenSync) { + SetupTestCertInSystemToken("client_1"); + StartCertLoader(); + base::RunLoop().RunUntilIdle(); + + client_cert::ClientCertConfig client_cert_config; + SetupCertificateConfigMatchingIssuerCN(onc::ONC_SOURCE_DEVICE_POLICY, + &client_cert_config); + + base::DictionaryValue shill_properties; + ClientCertResolver::ResolveCertificatePatternSync( + client_cert::CONFIG_TYPE_EAP, client_cert_config, &shill_properties); + std::string pkcs11_id; + shill_properties.GetStringWithoutPathExpansion(shill::kEapCertIdProperty, + &pkcs11_id); + EXPECT_EQ(test_cert_id_, pkcs11_id); +} + +TEST_F(ClientCertResolverTest, DevicePolicyDoesNotUseUserToken) { + SetupTestCerts("client_1", false /* do not import the issuer */); + SetupWifi(); + base::RunLoop().RunUntilIdle(); + + SetupNetworkHandlers(); + SetupPolicyMatchingIssuerCN(onc::ONC_SOURCE_DEVICE_POLICY); + base::RunLoop().RunUntilIdle(); + + network_properties_changed_count_ = 0; + StartCertLoader(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(0U, cert_loader_->system_certs().size()); + + // Verify that no client certificate was configured. + std::string pkcs11_id; + GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id); + EXPECT_EQ(std::string(), pkcs11_id); + EXPECT_EQ(1, network_properties_changed_count_); + EXPECT_FALSE(client_cert_resolver_->IsAnyResolveTaskRunning()); +} + +TEST_F(ClientCertResolverTest, DevicePolicyDoesNotUseUserTokenSync) { + SetupTestCerts("client_1", false /* do not import the issuer */); + StartCertLoader(); + base::RunLoop().RunUntilIdle(); + + client_cert::ClientCertConfig client_cert_config; + SetupCertificateConfigMatchingIssuerCN(onc::ONC_SOURCE_DEVICE_POLICY, + &client_cert_config); + + base::DictionaryValue shill_properties; + ClientCertResolver::ResolveCertificatePatternSync( + client_cert::CONFIG_TYPE_EAP, client_cert_config, &shill_properties); + std::string pkcs11_id; + shill_properties.GetStringWithoutPathExpansion(shill::kEapCertIdProperty, + &pkcs11_id); + EXPECT_EQ(std::string(), pkcs11_id); +} + TEST_F(ClientCertResolverTest, PopulateIdentityFromCert) { SetupTestCerts("client_3", true /* import issuer */); SetupWifi(); base::RunLoop().RunUntilIdle(); SetupNetworkHandlers(); - SetupPolicyMatchingIssuerPEM("${CERT_SAN_EMAIL}"); + SetupPolicyMatchingIssuerPEM(onc::ONC_SOURCE_USER_POLICY, + "${CERT_SAN_EMAIL}"); base::RunLoop().RunUntilIdle(); network_properties_changed_count_ = 0; @@ -437,7 +588,8 @@ // Verify that after changing the ONC policy to request a variant of the // Microsoft Universal Principal Name field instead, the correct value is // substituted into the shill service entry. - SetupPolicyMatchingIssuerPEM("upn-${CERT_SAN_UPN}-suffix"); + SetupPolicyMatchingIssuerPEM(onc::ONC_SOURCE_USER_POLICY, + "upn-${CERT_SAN_UPN}-suffix"); base::RunLoop().RunUntilIdle(); GetServiceProperty(shill::kEapIdentityProperty, &identity);
diff --git a/chromeos/network/client_cert_util.cc b/chromeos/network/client_cert_util.cc index 361664f..735ee2ca 100644 --- a/chromeos/network/client_cert_util.cc +++ b/chromeos/network/client_cert_util.cc
@@ -39,8 +39,11 @@ } void GetClientCertTypeAndPattern( + onc::ONCSource onc_source, const base::DictionaryValue& dict_with_client_cert, ClientCertConfig* cert_config) { + cert_config->onc_source = onc_source; + dict_with_client_cert.GetStringWithoutPathExpansion( ::onc::eap::kIdentity, &cert_config->policy_identity); @@ -266,7 +269,8 @@ ClientCertConfig::ClientCertConfig(const ClientCertConfig& other) = default; -void OncToClientCertConfig(const base::DictionaryValue& network_config, +void OncToClientCertConfig(::onc::ONCSource onc_source, + const base::DictionaryValue& network_config, ClientCertConfig* cert_config) { using namespace ::onc; @@ -317,8 +321,10 @@ cert_config->location = CONFIG_TYPE_EAP; } - if (dict_with_client_cert) - GetClientCertTypeAndPattern(*dict_with_client_cert, cert_config); + if (dict_with_client_cert) { + GetClientCertTypeAndPattern(onc_source, *dict_with_client_cert, + cert_config); + } } bool IsCertificateConfigured(const ConfigType cert_config_type,
diff --git a/chromeos/network/client_cert_util.h b/chromeos/network/client_cert_util.h index e687e06..baef5a09 100644 --- a/chromeos/network/client_cert_util.h +++ b/chromeos/network/client_cert_util.h
@@ -11,6 +11,7 @@ #include "base/memory/ref_counted.h" #include "chromeos/chromeos_export.h" #include "chromeos/network/certificate_pattern.h" +#include "components/onc/onc_constants.h" namespace base { class DictionaryValue; @@ -50,6 +51,9 @@ // The value of kIdentity, to enable substitutions. std::string policy_identity; + + // source of this ClientCertConfig. + ::onc::ONCSource onc_source; }; // Returns true only if any fields set in this pattern match exactly with @@ -99,6 +103,7 @@ // Determines the type of the CertificatePattern configuration, i.e. is it a // pattern within an EAP, IPsec or OpenVPN configuration. CHROMEOS_EXPORT void OncToClientCertConfig( + ::onc::ONCSource onc_source, const base::DictionaryValue& network_config, ClientCertConfig* cert_config);
diff --git a/chromeos/network/managed_network_configuration_handler.h b/chromeos/network/managed_network_configuration_handler.h index 448ac0f..a813efe2 100644 --- a/chromeos/network/managed_network_configuration_handler.h +++ b/chromeos/network/managed_network_configuration_handler.h
@@ -156,10 +156,12 @@ const std::string& userhash) const = 0; // Returns the policy with |guid| for profile |profile_path|. If such - // doesn't exist, returns NULL. + // doesn't exist, returns nullptr. Sets |onc_source| accordingly if it is not + // nullptr. virtual const base::DictionaryValue* FindPolicyByGuidAndProfile( const std::string& guid, - const std::string& profile_path) const = 0; + const std::string& profile_path, + ::onc::ONCSource* onc_source) const = 0; private: DISALLOW_ASSIGN(ManagedNetworkConfigurationHandler);
diff --git a/chromeos/network/managed_network_configuration_handler_impl.cc b/chromeos/network/managed_network_configuration_handler_impl.cc index f9b80551..1fc9374 100644 --- a/chromeos/network/managed_network_configuration_handler_impl.cc +++ b/chromeos/network/managed_network_configuration_handler_impl.cc
@@ -730,7 +730,8 @@ const base::DictionaryValue* ManagedNetworkConfigurationHandlerImpl::FindPolicyByGuidAndProfile( const std::string& guid, - const std::string& profile_path) const { + const std::string& profile_path, + ::onc::ONCSource* onc_source) const { const NetworkProfile* profile = network_profile_handler_->GetProfileForPath(profile_path); if (!profile) { @@ -742,7 +743,13 @@ if (!policies) return NULL; - return GetByGUID(policies->per_network_config, guid); + const base::DictionaryValue* policy = + GetByGUID(policies->per_network_config, guid); + if (policy && onc_source) { + *onc_source = (profile->userhash.empty() ? ::onc::ONC_SOURCE_DEVICE_POLICY + : ::onc::ONC_SOURCE_USER_POLICY); + } + return policy; } const ManagedNetworkConfigurationHandlerImpl::Policies*
diff --git a/chromeos/network/managed_network_configuration_handler_impl.h b/chromeos/network/managed_network_configuration_handler_impl.h index 3a45d74..2aee0d3 100644 --- a/chromeos/network/managed_network_configuration_handler_impl.h +++ b/chromeos/network/managed_network_configuration_handler_impl.h
@@ -95,7 +95,8 @@ const base::DictionaryValue* FindPolicyByGuidAndProfile( const std::string& guid, - const std::string& profile_path) const override; + const std::string& profile_path, + onc::ONCSource* onc_source) const override; // NetworkProfileObserver overrides void OnProfileAdded(const NetworkProfile& profile) override; @@ -155,7 +156,11 @@ const std::string& service_path, std::unique_ptr<base::DictionaryValue> shill_properties); + // Returns the Policies for the given |userhash|, or the device policies if + // |userhash| is empty. const Policies* GetPoliciesForUser(const std::string& userhash) const; + // Returns the Policies for the given network |profile|. These could be either + // user or device policies. const Policies* GetPoliciesForProfile(const NetworkProfile& profile) const; void OnPolicyAppliedToNetwork(const std::string& service_path,
diff --git a/chromeos/network/mock_managed_network_configuration_handler.h b/chromeos/network/mock_managed_network_configuration_handler.h index e8938951..038509f6 100644 --- a/chromeos/network/mock_managed_network_configuration_handler.h +++ b/chromeos/network/mock_managed_network_configuration_handler.h
@@ -70,10 +70,11 @@ const GuidToPolicyMap*(const std::string& userhash)); MOCK_CONST_METHOD1(GetGlobalConfigFromPolicy, const base::DictionaryValue*(const std::string& userhash)); - MOCK_CONST_METHOD2( + MOCK_CONST_METHOD3( FindPolicyByGuidAndProfile, const base::DictionaryValue*(const std::string& guid, - const std::string& profile_path)); + const std::string& profile_path, + ::onc::ONCSource* onc_source)); private: DISALLOW_COPY_AND_ASSIGN(MockManagedNetworkConfigurationHandler);
diff --git a/chromeos/network/network_cert_migrator.cc b/chromeos/network/network_cert_migrator.cc index 20ea816d..332e38d 100644 --- a/chromeos/network/network_cert_migrator.cc +++ b/chromeos/network/network_cert_migrator.cc
@@ -187,7 +187,7 @@ // certificates. VLOG(2) << "Start certificate migration of network configurations."; scoped_refptr<MigrationTask> helper(new MigrationTask( - CertLoader::Get()->cert_list(), weak_ptr_factory_.GetWeakPtr())); + CertLoader::Get()->all_certs(), weak_ptr_factory_.GetWeakPtr())); NetworkStateHandler::NetworkStateList networks; network_state_handler_->GetNetworkListByType( NetworkTypePattern::Default(),
diff --git a/chromeos/network/network_cert_migrator_unittest.cc b/chromeos/network/network_cert_migrator_unittest.cc index d57a4ae..cab86e62 100644 --- a/chromeos/network/network_cert_migrator_unittest.cc +++ b/chromeos/network/network_cert_migrator_unittest.cc
@@ -12,6 +12,7 @@ #include "base/macros.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" +#include "base/test/scoped_task_scheduler.h" #include "chromeos/cert_loader.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill_profile_client.h" @@ -39,7 +40,8 @@ class NetworkCertMigratorTest : public testing::Test { public: - NetworkCertMigratorTest() : service_test_(nullptr) {} + NetworkCertMigratorTest() + : service_test_(nullptr), scoped_task_scheduler_(&message_loop_) {} ~NetworkCertMigratorTest() override {} void SetUp() override { @@ -190,6 +192,7 @@ base::MessageLoop message_loop_; private: + base::test::ScopedTaskScheduler scoped_task_scheduler_; std::unique_ptr<NetworkStateHandler> network_state_handler_; std::unique_ptr<NetworkCertMigrator> network_cert_migrator_; crypto::ScopedTestNSSDB test_nssdb_;
diff --git a/chromeos/network/network_connection_handler.cc b/chromeos/network/network_connection_handler.cc index 2542fd4..69483bf 100644 --- a/chromeos/network/network_connection_handler.cc +++ b/chromeos/network/network_connection_handler.cc
@@ -458,8 +458,10 @@ std::string profile; service_properties.GetStringWithoutPathExpansion(shill::kProfileProperty, &profile); - const base::DictionaryValue* user_policy = - managed_configuration_handler_->FindPolicyByGuidAndProfile(guid, profile); + ::onc::ONCSource onc_source = onc::ONC_SOURCE_NONE; + const base::DictionaryValue* policy = + managed_configuration_handler_->FindPolicyByGuidAndProfile(guid, profile, + &onc_source); if (IsNetworkProhibitedByPolicy(type, guid, profile)) { ErrorCallbackForPendingRequest(service_path, kErrorUnmanagedNetwork); @@ -467,8 +469,10 @@ } client_cert::ClientCertConfig cert_config_from_policy; - if (user_policy) - client_cert::OncToClientCertConfig(*user_policy, &cert_config_from_policy); + if (policy) { + client_cert::OncToClientCertConfig(onc_source, *policy, + &cert_config_from_policy); + } client_cert::ConfigType client_cert_type = client_cert::CONFIG_TYPE_NONE; if (type == shill::kTypeVPN) { @@ -517,9 +521,7 @@ if (cert_config_from_policy.client_cert_type == onc::client_cert::kPattern) { if (!ClientCertResolver::ResolveCertificatePatternSync( - client_cert_type, - cert_config_from_policy.pattern, - &config_properties)) { + client_cert_type, cert_config_from_policy, &config_properties)) { ErrorCallbackForPendingRequest(service_path, kErrorCertificateRequired); return; } @@ -594,7 +596,7 @@ return false; } return !managed_configuration_handler_->FindPolicyByGuidAndProfile( - guid, profile_path); + guid, profile_path, nullptr /* onc_source */); } void NetworkConnectionHandler::QueueConnectRequest(
diff --git a/chromeos/network/network_connection_handler_unittest.cc b/chromeos/network/network_connection_handler_unittest.cc index 30919f3..683d09d6 100644 --- a/chromeos/network/network_connection_handler_unittest.cc +++ b/chromeos/network/network_connection_handler_unittest.cc
@@ -15,6 +15,7 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" +#include "base/test/scoped_task_scheduler.h" #include "chromeos/cert_loader.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/network/managed_network_configuration_handler_impl.h" @@ -116,7 +117,7 @@ class NetworkConnectionHandlerTest : public NetworkStateTest { public: - NetworkConnectionHandlerTest() {} + NetworkConnectionHandlerTest() : scoped_task_scheduler_(&message_loop_) {} ~NetworkConnectionHandlerTest() override {} @@ -297,6 +298,8 @@ std::unique_ptr<FakeTetherDelegate> fake_tether_delegate_; private: + base::test::ScopedTaskScheduler scoped_task_scheduler_; + DISALLOW_COPY_AND_ASSIGN(NetworkConnectionHandlerTest); };
diff --git a/chromeos/network/onc/onc_validator.cc b/chromeos/network/onc/onc_validator.cc index f596bec..5842134e 100644 --- a/chromeos/network/onc/onc_validator.cc +++ b/chromeos/network/onc/onc_validator.cc
@@ -301,9 +301,6 @@ std::string cert_type; result->GetStringWithoutPathExpansion(kClientCertType, &cert_type); - if (IsCertPatternInDevicePolicy(cert_type)) - return false; - bool all_required_exist = true; if (cert_type == kPattern) @@ -508,17 +505,6 @@ return true; } -bool Validator::IsCertPatternInDevicePolicy(const std::string& cert_type) { - if (cert_type == ::onc::client_cert::kPattern && - onc_source_ == ::onc::ONC_SOURCE_DEVICE_POLICY) { - error_or_warning_found_ = true; - LOG(ERROR) << MessageHeader() << "Client certificate patterns are " - << "prohibited in ONC device policies."; - return true; - } - return false; -} - bool Validator::IsGlobalNetworkConfigInUserImport( const base::DictionaryValue& onc_object) { if (onc_source_ == ::onc::ONC_SOURCE_USER_IMPORT &&
diff --git a/chromeos/network/onc/onc_validator.h b/chromeos/network/onc/onc_validator.h index 3109590f..0610a6bf 100644 --- a/chromeos/network/onc/onc_validator.h +++ b/chromeos/network/onc/onc_validator.h
@@ -207,10 +207,6 @@ const std::string& kGUID, std::set<std::string> *guids); - // Prohibit certificate patterns for device policy ONC so that an unmanaged - // user won't have a certificate presented for them involuntarily. - bool IsCertPatternInDevicePolicy(const std::string& cert_type); - // Prohibit global network configuration in user ONC imports. bool IsGlobalNetworkConfigInUserImport( const base::DictionaryValue& onc_object);
diff --git a/chromeos/network/onc/onc_validator_unittest.cc b/chromeos/network/onc/onc_validator_unittest.cc index 92b3c87..4102a0c 100644 --- a/chromeos/network/onc/onc_validator_unittest.cc +++ b/chromeos/network/onc/onc_validator_unittest.cc
@@ -544,11 +544,6 @@ &kNetworkConfigurationSignature, true), ExpectBothNotValid("", "")), - std::make_pair(OncParams("network-with-client-cert-pattern", - &kNetworkConfigurationSignature, - true, - ::onc::ONC_SOURCE_DEVICE_POLICY), - ExpectBothNotValid("", "")), std::make_pair(OncParams("openvpn-invalid-verify-x509-type", &kNetworkConfigurationSignature, false),
diff --git a/chromeos/system/statistics_provider.cc b/chromeos/system/statistics_provider.cc index c7144df..adfd9c8 100644 --- a/chromeos/system/statistics_provider.cc +++ b/chromeos/system/statistics_provider.cc
@@ -57,7 +57,8 @@ // File to get ECHO coupon info from, and key/value delimiters of // the file. -const char kEchoCouponFile[] = "/var/cache/echo/vpd_echo.txt"; +const char kEchoCouponFile[] = + "/mnt/stateful_partition/unencrypted/cache/vpd/echo/vpd_echo.txt"; const char kEchoCouponEq[] = "="; const char kEchoCouponDelim[] = "\n";
diff --git a/chromeos/test/data/network/invalid_settings_with_repairs.json b/chromeos/test/data/network/invalid_settings_with_repairs.json index df1abaf..c6e0e5c0 100644 --- a/chromeos/test/data/network/invalid_settings_with_repairs.json +++ b/chromeos/test/data/network/invalid_settings_with_repairs.json
@@ -308,28 +308,6 @@ "RoutingPrefix": 123 } ], }, - "network-with-client-cert-pattern": { - "GUID": "guid", - "Type": "WiFi", - "Name": "name", - "WiFi": { - "SSID": "ssid", - "Security": "WPA-EAP", - "EAP": { - "Outer": "EAP-TLS", - "Identity": "abc ${LOGIN_ID}@my.domain.com", - "ClientCertType": "Pattern", - "ClientCertPattern": { - "IssuerCARef": [ - "{58ac1967-a0e7-49e9-be68-123abc}" - ], - "EnrollmentURI": [ - "chrome-extension://delkjfjibodjclmdijflfnimdmgdagfk/generate-cert.html" - ] - } - } - } - }, "ipsec-with-psk-and-cacert": { "AuthenticationType": "PSK", "IKEVersion": 1,
diff --git a/components/password_manager/core/browser/password_reuse_detector.cc b/components/password_manager/core/browser/password_reuse_detector.cc index dd9b2a9..4ebe2d3 100644 --- a/components/password_manager/core/browser/password_reuse_detector.cc +++ b/components/password_manager/core/browser/password_reuse_detector.cc
@@ -79,6 +79,11 @@ } } +void PasswordReuseDetector::SaveSyncPasswordHash( + const base::string16& password) { + // TODO(crbug.com/657041) Implement saving of sync password hash. +} + void PasswordReuseDetector::AddPassword(const autofill::PasswordForm& form) { if (form.password_value.size() < kMinPasswordLengthToCheck) return;
diff --git a/components/password_manager/core/browser/password_reuse_detector.h b/components/password_manager/core/browser/password_reuse_detector.h index 967c941a..e9766c8 100644 --- a/components/password_manager/core/browser/password_reuse_detector.h +++ b/components/password_manager/core/browser/password_reuse_detector.h
@@ -51,6 +51,9 @@ const std::string& domain, PasswordReuseDetectorConsumer* consumer); + // Saves a hash of |password| for password reuse checking. + void SaveSyncPasswordHash(const base::string16& password); + private: using passwords_iterator = std::map<base::string16, std::set<std::string>,
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc index 3597674..ba13db6 100644 --- a/components/password_manager/core/browser/password_store.cc +++ b/components/password_manager/core/browser/password_store.cc
@@ -317,6 +317,11 @@ ScheduleTask(base::Bind(&PasswordStore::CheckReuseImpl, this, base::Passed(&check_reuse_request), input, domain)); } + +void PasswordStore::SaveSyncPasswordHash(const base::string16& password) { + ScheduleTask( + base::Bind(&PasswordStore::SaveSyncPasswordHashImpl, this, password)); +} #endif PasswordStore::~PasswordStore() { @@ -399,6 +404,11 @@ if (reuse_detector_) reuse_detector_->CheckReuse(input, domain, request.get()); } + +void PasswordStore::SaveSyncPasswordHashImpl(const base::string16& password) { + if (reuse_detector_) + reuse_detector_->SaveSyncPasswordHash(password); +} #endif void PasswordStore::Schedule(
diff --git a/components/password_manager/core/browser/password_store.h b/components/password_manager/core/browser/password_store.h index 0a0b915..c578023 100644 --- a/components/password_manager/core/browser/password_store.h +++ b/components/password_manager/core/browser/password_store.h
@@ -241,6 +241,9 @@ virtual void CheckReuse(const base::string16& input, const std::string& domain, PasswordReuseDetectorConsumer* consumer); + + // Saves a hash of |password| for password reuse checking. + void SaveSyncPasswordHash(const base::string16& password); #endif protected: @@ -402,6 +405,9 @@ void CheckReuseImpl(std::unique_ptr<CheckReuseRequest> request, const base::string16& input, const std::string& domain); + + // Synchronous implementation of SaveSyncPasswordHash(). + void SaveSyncPasswordHashImpl(const base::string16& password); #endif // TaskRunner for tasks that run on the main thread (usually the UI thread).
diff --git a/components/sync_wifi/wifi_config_delegate_chromeos_unittest.cc b/components/sync_wifi/wifi_config_delegate_chromeos_unittest.cc index 1f142a1..882a839 100644 --- a/components/sync_wifi/wifi_config_delegate_chromeos_unittest.cc +++ b/components/sync_wifi/wifi_config_delegate_chromeos_unittest.cc
@@ -109,7 +109,8 @@ } const base::DictionaryValue* FindPolicyByGuidAndProfile( const std::string& guid, - const std::string& profile_path) const override { + const std::string& profile_path, + ::onc::ONCSource* onc_source) const override { NOTIMPLEMENTED(); return nullptr; }
diff --git a/storage/browser/fileapi/file_system_dir_url_request_job_unittest.cc b/storage/browser/fileapi/file_system_dir_url_request_job_unittest.cc index 0ec091e..03b27dd 100644 --- a/storage/browser/fileapi/file_system_dir_url_request_job_unittest.cc +++ b/storage/browser/fileapi/file_system_dir_url_request_job_unittest.cc
@@ -22,6 +22,7 @@ #include "net/base/net_errors.h" #include "net/base/request_priority.h" #include "net/http/http_request_headers.h" +#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_test_util.h" @@ -179,8 +180,9 @@ url.GetOrigin().host(), file_system_context)); empty_context_.set_job_factory(job_factory_.get()); - request_ = empty_context_.CreateRequest( - url, net::DEFAULT_PRIORITY, delegate_.get()); + request_ = empty_context_.CreateRequest(url, net::DEFAULT_PRIORITY, + delegate_.get(), + TRAFFIC_ANNOTATION_FOR_TESTS); request_->Start(); ASSERT_TRUE(request_->is_pending()); // verify that we're starting async if (run_to_completion)
diff --git a/storage/browser/fileapi/file_system_url_request_job_unittest.cc b/storage/browser/fileapi/file_system_url_request_job_unittest.cc index 75507a7..bdb9c59 100644 --- a/storage/browser/fileapi/file_system_url_request_job_unittest.cc +++ b/storage/browser/fileapi/file_system_url_request_job_unittest.cc
@@ -28,6 +28,7 @@ #include "net/base/request_priority.h" #include "net/http/http_byte_range.h" #include "net/http/http_request_headers.h" +#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_test_util.h" @@ -194,8 +195,9 @@ url.GetOrigin().host(), file_system_context)); empty_context_.set_job_factory(job_factory_.get()); - request_ = empty_context_.CreateRequest( - url, net::DEFAULT_PRIORITY, delegate_.get()); + request_ = empty_context_.CreateRequest(url, net::DEFAULT_PRIORITY, + delegate_.get(), + TRAFFIC_ANNOTATION_FOR_TESTS); if (headers) request_->SetExtraRequestHeaders(*headers);
diff --git a/storage/browser/fileapi/file_writer_delegate_unittest.cc b/storage/browser/fileapi/file_writer_delegate_unittest.cc index 9733b4b..d0524f39 100644 --- a/storage/browser/fileapi/file_writer_delegate_unittest.cc +++ b/storage/browser/fileapi/file_writer_delegate_unittest.cc
@@ -20,6 +20,7 @@ #include "net/base/io_buffer.h" #include "net/base/request_priority.h" #include "net/http/http_response_headers.h" +#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_job.h" @@ -148,8 +149,9 @@ int64_t allowed_growth) { file_writer_delegate_.reset( CreateWriterDelegate(test_file_path, offset, allowed_growth)); - request_ = empty_context_.CreateRequest( - blob_url, net::DEFAULT_PRIORITY, file_writer_delegate_.get()); + request_ = empty_context_.CreateRequest(blob_url, net::DEFAULT_PRIORITY, + file_writer_delegate_.get(), + TRAFFIC_ANNOTATION_FOR_TESTS); } // This should be alive until the very end of this instance. @@ -379,8 +381,9 @@ // Credate another FileWriterDelegate for concurrent write. file_writer_delegate2.reset( CreateWriterDelegate("test2", 0, std::numeric_limits<int64_t>::max())); - request2 = empty_context_.CreateRequest( - kBlobURL2, net::DEFAULT_PRIORITY, file_writer_delegate2.get()); + request2 = empty_context_.CreateRequest(kBlobURL2, net::DEFAULT_PRIORITY, + file_writer_delegate2.get(), + TRAFFIC_ANNOTATION_FOR_TESTS); Result result, result2; ASSERT_EQ(0, usage());
diff --git a/third_party/WebKit/LayoutTests/external/wpt/WebIDL/current-realm-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/WebIDL/current-realm-expected.txt index 9c345bc..6c26cec5 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/WebIDL/current-realm-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/WebIDL/current-realm-expected.txt
@@ -27,7 +27,7 @@ PASS cloneRange PASS getContext 2d PASS getContext webgl -FAIL createImageData assert_false: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 should not be from top-level Realm expected false got true +FAIL createImageData Failed to execute 'createImageData' on 'CanvasRenderingContext2D': The provided value is not of type '(Uint8ClampedArray or Uint16Array or Float32Array)' FAIL getImageData assert_false: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 should not be from top-level Realm expected false got true PASS FontFace's load() Harness: the test ran to completion.
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 4f0b0e4..552dddd 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
@@ -597,7 +597,6 @@ getter height getter width method constructor - method createImageData method getColorSettings interface InstallEvent : ExtendableEvent method constructor
diff --git a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createPutGetImageData-colorManaged.html b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createPutGetImageData-colorManaged.html new file mode 100644 index 0000000..78494cb --- /dev/null +++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createPutGetImageData-colorManaged.html
@@ -0,0 +1,129 @@ +<!DOCTYPE html> +<body> +<script src="../../../../../resources/testharness.js"></script> +<script src="../../../../../resources/testharnessreport.js"></script> +<script> + +var xWidth = xHeight = 10; + +function checkImageData(canvasColorSettings, imageData) { + var imageDataColorSettings = imageData.getColorSettings(); + //console.log(canvasColorSettings); + console.log(imageDataColorSettings); + + assert_equals(canvasColorSettings.colorSpace, imageDataColorSettings.colorSpace); + if (canvasColorSettings.pixelFormat == "8-8-8-8") { + //console.log("8-8-8-8 -> "); + assert_equals("uint8", imageDataColorSettings.storageFormat); + assert_equals(imageData.data.length, 4 * xWidth * xHeight); + } else { + //console.log("float16 -> "); + assert_equals("float32", imageDataColorSettings.storageFormat); + assert_equals(imageData.dataUnion.length, 4 * xWidth * xHeight); + } +} + +// Test createImageData when the canvas is color managed +var helperImageData = new ImageData(xWidth, xHeight); +function runTestCreateImageData(canvasColorSettings) { + var aCanvas = document.createElement("canvas"); + aCanvas.width = xWidth; + aCanvas.height = xHeight; + var ctx = aCanvas.getContext('2d', canvasColorSettings); + var imageData = ctx.createImageData(xWidth, xHeight); + checkImageData(canvasColorSettings, imageData); + + imageData = ctx.createImageData(helperImageData); + checkImageData(canvasColorSettings, imageData); +} + +var testScenariosCreateImageData = [ + ["Test color managed cretateImageData: {srgb, 8-8-8-8} -> {srgb, uint8}", {colorSpace: "srgb", pixelFormat: "8-8-8-8"}], + ["Test color managed cretateImageData: {srgb, float16} -> {srgb, float32}", {colorSpace: "srgb", pixelFormat: "float16"}], + ["Test color managed cretateImageData: {rec2020, float16} -> {rec2020, float32}", {colorSpace: "rec2020", pixelFormat: "float16"}], + ["Test color managed cretateImageData: {p3, float16} -> {p3, float32}", {colorSpace: "p3", pixelFormat: "float16"}], +]; + +//generate_tests(runTestCreateImageData, testScenariosCreateImageData); + +// Test getImageData when the canvas is color managed +function runTestGetImageData(canvasColorSettings) { + var aCanvas = document.createElement("canvas"); + aCanvas.width = xWidth; + aCanvas.height = xHeight; + var ctx = aCanvas.getContext('2d', canvasColorSettings); + var imageData = ctx.getImageData(0, 0, xWidth, xHeight); + checkImageData(canvasColorSettings, imageData); +} + +var testScenariosGetImageData = [ +// ["Test color managed getImageData: {srgb, 8-8-8-8} -> {srgb, uint8}", {colorSpace: "srgb", pixelFormat: "8-8-8-8"}], + ["Test color managed getImageData: {srgb, float16} -> {srgb, float32}", {colorSpace: "srgb", pixelFormat: "float16"}], +// ["Test color managed getImageData: {rec2020, float16} -> {rec2020, float32}", {colorSpace: "rec2020", pixelFormat: "float16"}], +// ["Test color managed getImageData: {p3, float16} -> {p3, float32}", {colorSpace: "p3", pixelFormat: "float16"}], +]; + +generate_tests(runTestGetImageData, testScenariosGetImageData); + +// Test putImageData when the canvas is color managed. +// This test passes if differen possible calls do not crash. To avoid hard +// coded expected results that need to get synced after related Skia updates, +// the output correcteness is verified as a unit test. Please see: +// CanvasRenderingContext2DTest::ColorManagedGetPutImageData + +var dataU8 = new Uint8ClampedArray(4 * xWidth * xHeight); +var dataU16 = new Uint16Array(4 * xWidth * xHeight); +var dataF32 = new Float32Array(4 * xWidth * xHeight); +function prepareDataArrays() { + for (i = 0; i < 4 * xWidth * xHeight; i++) { + dataU8[i] = (i % 4 == 3) ? 255 : i % 256; + dataU16[i] = dataU8[i] * 257; + dataF32[i] = dataU8[i] / 255.0; + } +} + +var testScenariosPutImageData = []; +function prepareTestScenariosPutImageData() { + var colorSpaces = ["srgb", "p3", "rec2020"]; + var imageDataStorageFormats = ["uint8", "uint16", "float32"]; + var canvasPixelFormats = ["8-8-8-8", "float16"]; + + for (i = 0; i < colorSpaces.length; i++) + for (j = 0; j < imageDataStorageFormats.length; j++) + for (k = 0; k < colorSpaces.length; k++) + for (l = 0; l < canvasPixelFormats.length; l++) { + testTitle = "Test color managed putImageData: ".concat( + "{", colorSpaces[i], ", ", imageDataStorageFormats[j], "} -> {", colorSpaces[k], + ", ", canvasPixelFormats[l], "}"); + imageDataColorSettings = + {colorSpace: colorSpaces[i], storageFormat: imageDataStorageFormats[j]}; + canvasColorSettings = + {colorSpace: colorSpaces[k], pixelFormat: canvasPixelFormats[l]}; + testScenariosPutImageData.push([testTitle, imageDataColorSettings, canvasColorSettings]); + } +} + +function createAndPutImageData(data, imageDataColorSettings, canvasColorSettings) { + // create color managed canvas + var aCanvas = document.createElement("canvas"); + aCanvas.width = xWidth; + aCanvas.height = xHeight; + var ctx = aCanvas.getContext('2d', canvasColorSettings); + // create color managed ImageData + var imageData = ctx.createImageData(data, xWidth, xHeight, imageDataColorSettings); + // put image data into canvas. test succeeds if this does not crash. + ctx.putImageData(imageData, 0, 0); +} + +function runTestPutImageData(imageDataColorSettings, canvasColorSettings) { + createAndPutImageData(dataU8, imageDataColorSettings, canvasColorSettings); + createAndPutImageData(dataU16, imageDataColorSettings, canvasColorSettings); + createAndPutImageData(dataF32, imageDataColorSettings, canvasColorSettings); +} + +prepareDataArrays(); +prepareTestScenariosPutImageData(); +//generate_tests(runTestPutImageData, testScenariosPutImageData); + +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/color-space/imageData-colorSpace.html b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/imageData-colorSpace.html similarity index 88% rename from third_party/WebKit/LayoutTests/fast/canvas/color-space/imageData-colorSpace.html rename to third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/imageData-colorSpace.html index 2d5d56d..549462cd 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/color-space/imageData-colorSpace.html +++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/imageData-colorSpace.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <body> -<script src="../../../resources/testharness.js"></script> -<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../../../resources/testharness.js"></script> +<script src="../../../../../resources/testharnessreport.js"></script> <script> var dataU8 = new Uint8ClampedArray([255, 192, 128, 64]); @@ -23,24 +23,25 @@ } function runTest(colorSettings, expectedColorSettings) { - experimental = new ImageData(1,1); + var canvas = document.createElement("canvas"); + var ctx = canvas.getContext("2d"); - imageData = experimental.createImageData(1, 1, colorSettings); + imageData = ctx.createImageData(1, 1, colorSettings); checkDataTypeAgainstStorageFormat(imageData.dataUnion, colorSettings.storageFormat); assert_array_equals(imageData.dataUnion, [0, 0, 0, 0]); checkColorSettings(imageData.getColorSettings(), expectedColorSettings.colorSpace, expectedColorSettings.storageFormat); - imageData = experimental.createImageData(dataU8, 1, 1, colorSettings); + imageData = ctx.createImageData(dataU8, 1, 1, colorSettings); assert_equals(Object.prototype.toString.call(imageData.dataUnion), "[object Uint8ClampedArray]"); assert_array_equals(imageData.dataUnion, dataU8); checkColorSettings(imageData.getColorSettings(), expectedColorSettings.colorSpace, "uint8"); - imageData = experimental.createImageData(dataU16, 1, 1, colorSettings); + imageData = ctx.createImageData(dataU16, 1, 1, colorSettings); assert_equals(Object.prototype.toString.call(imageData.dataUnion), "[object Uint16Array]"); assert_array_equals(imageData.dataUnion, dataU16); checkColorSettings(imageData.getColorSettings(), expectedColorSettings.colorSpace, "uint16"); - imageData = experimental.createImageData(dataF32, 1, 1, colorSettings); + imageData = ctx.createImageData(dataF32, 1, 1, colorSettings); assert_equals(Object.prototype.toString.call(imageData.dataUnion), "[object Float32Array]"); assert_array_equals(imageData.dataUnion, dataF32); checkColorSettings(imageData.getColorSettings(), expectedColorSettings.colorSpace, "float32");
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 ec4f603..8280e05 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
@@ -596,7 +596,6 @@ getter height getter width method constructor - method createImageData method getColorSettings interface InstallEvent : ExtendableEvent method constructor
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 0b22d590..b8097e42 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
@@ -620,7 +620,6 @@ [Worker] getter height [Worker] getter width [Worker] method constructor -[Worker] method createImageData [Worker] method getColorSettings [Worker] interface MessageChannel [Worker] attribute @@toStringTag
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 653b94c..0e745ff 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
@@ -3799,7 +3799,6 @@ getter height getter width method constructor - method createImageData method getColorSettings interface InputDeviceCapabilities attribute @@toStringTag
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 c661271f1..ffce2e4 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
@@ -615,7 +615,6 @@ [Worker] getter height [Worker] getter width [Worker] method constructor -[Worker] method createImageData [Worker] method getColorSettings [Worker] interface MessageChannel [Worker] attribute @@toStringTag
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 4f0b0e4..552dddd 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
@@ -597,7 +597,6 @@ getter height getter width method constructor - method createImageData method getColorSettings interface InstallEvent : ExtendableEvent method constructor
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 7f49c3b5..f5485e1f 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
@@ -620,7 +620,6 @@ [Worker] getter height [Worker] getter width [Worker] method constructor -[Worker] method createImageData [Worker] method getColorSettings [Worker] interface MessageChannel [Worker] attribute @@toStringTag
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 a0a196f..7b8356f 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -3799,7 +3799,6 @@ getter height getter width method constructor - method createImageData method getColorSettings interface InputDeviceCapabilities attribute @@toStringTag
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 9709dba..ce13cfa 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
@@ -615,7 +615,6 @@ [Worker] getter height [Worker] getter width [Worker] method constructor -[Worker] method createImageData [Worker] method getColorSettings [Worker] interface MessageChannel [Worker] attribute @@toStringTag
diff --git a/third_party/WebKit/PerformanceTests/TestData/append-child-measure-time.html b/third_party/WebKit/PerformanceTests/TestData/append-child-measure-time.html new file mode 100644 index 0000000..99491ef --- /dev/null +++ b/third_party/WebKit/PerformanceTests/TestData/append-child-measure-time.html
@@ -0,0 +1,36 @@ +<!DOCTYPE html> +<html> +<body> + <div id="holder"> + </div> +<script src="../resources/runner.js"></script> +</script> +<script> +var holderElement = document.getElementById("holder"); + +PerfTestRunner.measureTime({ + description: "Measures performance of layout when adding many child elements.", + + setup: function() { + while (holderElement.firstChild) { + holderElement.removeChild(holderElement.firstChild); + } + }, + + run: function() { + for (var i = 0; i < 50; ++i) { + var element = document.createElement("div"); + element.title = 'dummy'; + element.innerText = "FOO"; + holderElement.appendChild(element); + PerfTestRunner.forceLayout(); + } + }, + warmUpCount: 3, + iterationCount: 10, + tracingCategories: 'blink', + traceEventsToMeasure: ['FrameView::layout', 'UpdateLayoutTree'] +}); +</script> +</body> +</html>
diff --git a/third_party/WebKit/PerformanceTests/TestData/color-changes-measure-frame-time.html b/third_party/WebKit/PerformanceTests/TestData/color-changes-measure-frame-time.html new file mode 100644 index 0000000..a55b247 --- /dev/null +++ b/third_party/WebKit/PerformanceTests/TestData/color-changes-measure-frame-time.html
@@ -0,0 +1,84 @@ +<!DOCTYPE html> +<body> +<script src="../resources/runner.js"></script> +<style> + span { + padding: 1px; + } + .changeColor { + background-color: green; + } +</style> +<script> +// This test measures the lifecycle update performance of changing background +// colors in large trees. + +function buildTree(parent, depth, arity, tagNameCallback, createElementCallback) { + for (var child = 0; child < arity; child++) { + var element = document.createElement(tagNameCallback(depth)); + parent.appendChild(element); + createElementCallback(element, depth); + if (depth > 1) + buildTree(element, depth - 1, arity, tagNameCallback, createElementCallback); + } +} + +// Build a tall tree that is skinny. A middle layer of +// the tree should have the changeColor class. +buildTree(document.body, 15, 2, + function(depth) { + // Use divs at upper levels to avoid too much layout time. + return depth > 9 ? 'div' : 'span'; + }, + function(element, depth) { + element.style.backgroundColor = 'green'; + if (depth == 5) + element.setAttribute('class', 'changeColor'); + } +); + +// Build a short tree that is fat. A middle layer of +// the tree should have the changeColor class. +buildTree(document.body, 6, 7, + function(depth) { + // Use divs at upper levels to avoid too much layout time. + return depth > 4 ? 'div' : 'span'; + }, + function(element, depth) { + element.style.backgroundColor = 'orange'; + if (depth == 3) + element.setAttribute('class', 'changeColor'); + } +); + +var runCount = 0; +var elementsToChange = document.getElementsByClassName('changeColor'); +var colors = [ + "rgb(128, 18, 237)", + "rgb(191, 1, 191)", + "rgb(237, 18, 128)", + "rgb(255, 64, 64)", + "rgb(237, 127, 18)", + "rgb(191, 191, 1)", + "rgb(128, 237, 18)", + "rgb(64, 255, 64)", + "rgb(18, 237, 127)", + "rgb(1, 191, 191)", + "rgb(18, 128, 237)", + "rgb(64, 64, 255)" +]; + +PerfTestRunner.measureFrameTime({ + run: function() { + runCount++; + var newColor = colors[runCount % colors.length]; + for (var index = 0; index < elementsToChange.length; index++) + elementsToChange[index].style.backgroundColor = newColor; + }, + warmUpCount: 3, + iterationCount: 10, + tracingCategories: 'blink', + traceEventsToMeasure: ['FrameView::prePaint', 'FrameView::paintTree'] +}); +</script> +</body>
diff --git a/third_party/WebKit/PerformanceTests/resources/runner.js b/third_party/WebKit/PerformanceTests/resources/runner.js index 22a5e8e..7ce98b7 100644 --- a/third_party/WebKit/PerformanceTests/resources/runner.js +++ b/third_party/WebKit/PerformanceTests/resources/runner.js
@@ -157,8 +157,16 @@ PerfTestRunner.log("Running " + iterationCount + " times"); if (test.doNotIgnoreInitialRun) completedIterations++; - if (runner) + + if (runner && test.tracingCategories && window.testRunner && + window.testRunner.supportTracing) { + window.testRunner.traceEventsToMeasure = test.traceEventsToMeasure; + window.testRunner.startTracing(test.tracingCategories, function() { + scheduleNextRun(scheduler, runner); + }); + } else if (runner) { scheduleNextRun(scheduler, runner); + } } function scheduleNextRun(scheduler, runner) { @@ -225,8 +233,17 @@ logInDocument("Got an exception while finalizing the test with name=" + exception.name + ", message=" + exception.message); } - if (window.testRunner) - testRunner.notifyDone(); + if (window.testRunner) { + if (currentTest.traceEventsToMeasure && + testRunner.supportTracing) { + testRunner.stopTracingAndMeasure( + currentTest.traceEventsToMeasure, function() { + testRunner.notifyDone(); + }); + } else { + testRunner.notifyDone(); + } + } } PerfTestRunner.prepareToMeasureValuesAsync = function (test) { @@ -248,6 +265,25 @@ finish(); } + function addRunTestStartMarker() { + if (!window.testRunner || !window.testRunner.supportTracing) + return; + if (completedIterations < 0) + console.time('blink_perf.runTest.warmup'); + else + console.time('blink_perf.runTest'); + } + + function addRunTestEndMarker() { + if (!window.testRunner || !window.testRunner.supportTracing) + return; + if (completedIterations < 0) + console.timeEnd('blink_perf.runTest.warmup'); + else + console.timeEnd('blink_perf.runTest'); + } + + PerfTestRunner.measureFrameTime = function (test) { PerfTestRunner.unit = "ms"; PerfTestRunner.bufferedLog = true; @@ -261,9 +297,12 @@ var lastFrameTime = -1; function measureFrameTimeOnce() { + if (lastFrameTime != -1) + addRunTestEndMarker(); var now = PerfTestRunner.now(); var result = lastFrameTime == -1 ? -1 : now - lastFrameTime; lastFrameTime = now; + addRunTestStartMarker(); var returnValue = currentTest.run(); if (returnValue - 0 === returnValue) { @@ -290,7 +329,9 @@ PerfTestRunner.gc(); var start = PerfTestRunner.now(); + addRunTestStartMarker(); var returnValue = currentTest.run(); + addRunTestEndMarker(); var end = PerfTestRunner.now(); if (returnValue - 0 === returnValue) {
diff --git a/third_party/WebKit/Source/core/dom/TaskRunnerHelper.cpp b/third_party/WebKit/Source/core/dom/TaskRunnerHelper.cpp index 631c5de..30c377d 100644 --- a/third_party/WebKit/Source/core/dom/TaskRunnerHelper.cpp +++ b/third_party/WebKit/Source/core/dom/TaskRunnerHelper.cpp
@@ -31,24 +31,24 @@ // TODO(nhiroki): Throttle them again after we're convinced that it's safe // or provide a mechanism that web pages can opt-out it if throttling is not // desirable. + case TaskType::kDOMManipulation: case TaskType::kDatabaseAccess: + case TaskType::kFileReading: + case TaskType::kHistoryTraversal: + case TaskType::kPerformanceTimeline: + case TaskType::kPostedMessage: + case TaskType::kRemoteEvent: + case TaskType::kSensor: + case TaskType::kUnshippedPortMessage: + case TaskType::kWebSocket: return frame ? frame->FrameScheduler()->SuspendableTaskRunner() : Platform::Current()->CurrentThread()->GetWebTaskRunner(); - case TaskType::kDOMManipulation: case TaskType::kUserInteraction: - case TaskType::kHistoryTraversal: case TaskType::kEmbed: case TaskType::kMediaElementEvent: case TaskType::kCanvasBlobSerialization: - case TaskType::kRemoteEvent: - case TaskType::kWebSocket: case TaskType::kMicrotask: - case TaskType::kPostedMessage: - case TaskType::kUnshippedPortMessage: - case TaskType::kFileReading: case TaskType::kPresentation: - case TaskType::kSensor: - case TaskType::kPerformanceTimeline: case TaskType::kWebGL: case TaskType::kUnspecedTimer: case TaskType::kMiscPlatformAPI:
diff --git a/third_party/WebKit/Source/core/html/ImageData.cpp b/third_party/WebKit/Source/core/html/ImageData.cpp index b42e161b..71f62d5 100644 --- a/third_party/WebKit/Source/core/html/ImageData.cpp +++ b/third_party/WebKit/Source/core/html/ImageData.cpp
@@ -276,11 +276,15 @@ return new ImageData(IntSize(width, height), data.View()); } -ImageData* ImageData::createImageData( +ImageData* ImageData::CreateImageData( unsigned width, unsigned height, const ImageDataColorSettings& color_settings, ExceptionState& exception_state) { + if (!RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() || + !RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) + return nullptr; + if (!ImageData::ValidateConstructorArguments( kParamWidth | kParamHeight, nullptr, width, height, nullptr, &color_settings, &exception_state)) @@ -297,12 +301,17 @@ return new ImageData(IntSize(width, height), buffer_view, &color_settings); } -ImageData* ImageData::createImageData(ImageDataArray& data, +ImageData* ImageData::CreateImageData(ImageDataArray& data, unsigned width, unsigned height, ImageDataColorSettings& color_settings, ExceptionState& exception_state) { + if (!RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() || + !RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) + return nullptr; + DOMArrayBufferView* buffer_view = nullptr; + // When pixels data is provided, we need to override the storage format of // ImageDataColorSettings with the one that matches the data type of the // pixels. @@ -574,6 +583,16 @@ return nullptr; } +DOMArrayBufferBase* ImageData::BufferBase() const { + if (data_) + return data_->BufferBase(); + if (data_u16_) + return data_u16_->BufferBase(); + if (data_f32_) + return data_f32_->BufferBase(); + return nullptr; +} + // For ImageData, the color space is only specified by color settings. // It cannot have a SkColorSpace. This doesn't mean anything. Fix this. sk_sp<SkColorSpace> ImageData::GetSkColorSpace() {
diff --git a/third_party/WebKit/Source/core/html/ImageData.h b/third_party/WebKit/Source/core/html/ImageData.h index be0b419ef..c270c6e 100644 --- a/third_party/WebKit/Source/core/html/ImageData.h +++ b/third_party/WebKit/Source/core/html/ImageData.h
@@ -90,15 +90,15 @@ unsigned height, ExceptionState&); - ImageData* createImageData(unsigned width, - unsigned height, - const ImageDataColorSettings&, - ExceptionState&); - ImageData* createImageData(ImageDataArray&, - unsigned width, - unsigned height, - ImageDataColorSettings&, - ExceptionState&); + static ImageData* CreateImageData(unsigned width, + unsigned height, + const ImageDataColorSettings&, + ExceptionState&); + static ImageData* CreateImageData(ImageDataArray&, + unsigned width, + unsigned height, + ImageDataColorSettings&, + ExceptionState&); void getColorSettings(ImageDataColorSettings& result) { result = color_settings_; @@ -131,6 +131,8 @@ const ImageDataArray& dataUnion() const { return data_union_; } void dataUnion(ImageDataArray& result) { result = data_union_; }; + DOMArrayBufferBase* BufferBase() const; + sk_sp<SkColorSpace> GetSkColorSpace(); bool ImageDataInCanvasColorSettings(const CanvasColorSpace&, const CanvasPixelFormat&,
diff --git a/third_party/WebKit/Source/core/html/ImageData.idl b/third_party/WebKit/Source/core/html/ImageData.idl index e29e039c..173ecfa 100644 --- a/third_party/WebKit/Source/core/html/ImageData.idl +++ b/third_party/WebKit/Source/core/html/ImageData.idl
@@ -37,16 +37,6 @@ Exposed=(Window,Worker), RaisesException=Constructor, ] interface ImageData { - - // The following createImageData functions are used instead of the regular constructors - // as currently Blink IDL does not allow to put custom constructors behind a flag - // (crbug.com/672978). These must be replaced with regular constructor declaration - // as specified in the proposal before shipping. - // https://github.com/WICG/canvas-color-space/blob/master/CanvasColorSpaceProposal.md - - [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] ImageData createImageData(unsigned long sw, unsigned long sh, ImageDataColorSettings imageDataColorSettings); - [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] ImageData createImageData(ImageDataArray data, unsigned long sw, unsigned long sh, ImageDataColorSettings imageDataColorSettings); - [RuntimeEnabled=ExperimentalCanvasFeatures] ImageDataColorSettings getColorSettings(); readonly attribute unsigned long width;
diff --git a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp index 6c418628..9caf61a 100644 --- a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp +++ b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp
@@ -38,8 +38,11 @@ namespace blink { BaseRenderingContext2D::BaseRenderingContext2D() - : clip_antialiasing_(kNotAntiAliased) { + : clip_antialiasing_(kNotAntiAliased), color_management_enabled_(false) { state_stack_.push_back(CanvasRenderingContext2DState::Create()); + color_management_enabled_ = + RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() && + RuntimeEnabledFeatures::colorCorrectRenderingEnabled(); } BaseRenderingContext2D::~BaseRenderingContext2D() {} @@ -1508,10 +1511,26 @@ return true; } +ImageDataColorSettings +BaseRenderingContext2D::GetColorSettingsAsImageDataColorSettings() const { + ImageDataColorSettings color_settings; + color_settings.setColorSpace(ColorSpaceAsString()); + if (PixelFormat() == kF16CanvasPixelFormat) + color_settings.setStorageFormat(kFloat32ArrayStorageFormatName); + return color_settings; +} + ImageData* BaseRenderingContext2D::createImageData( ImageData* image_data, ExceptionState& exception_state) const { - ImageData* result = ImageData::Create(image_data->Size()); + ImageData* result = nullptr; + if (color_management_enabled_) { + ImageDataColorSettings color_settings = + GetColorSettingsAsImageDataColorSettings(); + result = ImageData::Create(image_data->Size(), &color_settings); + } else { + result = ImageData::Create(image_data->Size()); + } if (!result) exception_state.ThrowRangeError("Out of memory at ImageData creation"); return result; @@ -1529,13 +1548,49 @@ } IntSize size(abs(sw), abs(sh)); + ImageData* result = nullptr; + if (color_management_enabled_) { + ImageDataColorSettings color_settings = + GetColorSettingsAsImageDataColorSettings(); + result = ImageData::Create(size, &color_settings); + } else { + result = ImageData::Create(size); + } - ImageData* result = ImageData::Create(size); if (!result) exception_state.ThrowRangeError("Out of memory at ImageData creation"); return result; } +ImageData* BaseRenderingContext2D::createImageData( + unsigned width, + unsigned height, + ImageDataColorSettings& color_settings, + ExceptionState& exception_state) const { + return ImageData::CreateImageData(width, height, color_settings, + exception_state); +} + +ImageData* BaseRenderingContext2D::createImageData( + ImageDataArray& data_array, + unsigned width, + unsigned height, + ExceptionState& exception_state) const { + ImageDataColorSettings color_settings; + return ImageData::CreateImageData(data_array, width, height, color_settings, + exception_state); +} + +ImageData* BaseRenderingContext2D::createImageData( + ImageDataArray& data_array, + unsigned width, + unsigned height, + ImageDataColorSettings& color_settings, + ExceptionState& exception_state) const { + return ImageData::CreateImageData(data_array, width, height, color_settings, + exception_state); +} + ImageData* BaseRenderingContext2D::getImageData( int sx, int sy, @@ -1598,8 +1653,14 @@ IntRect image_data_rect(sx, sy, sw, sh); ImageBuffer* buffer = GetImageBuffer(); + ImageDataColorSettings color_settings = + GetColorSettingsAsImageDataColorSettings(); if (!buffer || isContextLost()) { - ImageData* result = ImageData::Create(image_data_rect.Size()); + ImageData* result = nullptr; + if (color_management_enabled_) + result = ImageData::Create(image_data_rect.Size(), &color_settings); + else + result = ImageData::Create(image_data_rect.Size()); if (!result) exception_state.ThrowRangeError("Out of memory at ImageData creation"); return result; @@ -1613,11 +1674,22 @@ NeedsFinalizeFrame(); - DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(contents); - return ImageData::Create( - image_data_rect.Size(), - NotShared<DOMUint8ClampedArray>(DOMUint8ClampedArray::Create( - array_buffer, 0, array_buffer->ByteLength()))); + if (!color_management_enabled_) { + DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(contents); + return ImageData::Create( + image_data_rect.Size(), + NotShared<DOMUint8ClampedArray>(DOMUint8ClampedArray::Create( + array_buffer, 0, array_buffer->ByteLength()))); + } + + ImageDataStorageFormat storage_format = + ImageData::GetImageDataStorageFormat(color_settings.storageFormat()); + DOMArrayBufferView* array_buffer_view = + ImageData::ConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat( + contents, PixelFormat(), storage_format); + return ImageData::Create(image_data_rect.Size(), + NotShared<DOMArrayBufferView>(array_buffer_view), + &color_settings); } void BaseRenderingContext2D::putImageData(ImageData* data, @@ -1639,14 +1711,15 @@ if (!WTF::CheckMul(dirty_width, dirty_height).IsValid<int>()) { return; } - usage_counters_.num_put_image_data_calls++; usage_counters_.area_put_image_data_calls += dirty_width * dirty_height; - if (data->data()->BufferBase()->IsNeutered()) { + + if (data->BufferBase()->IsNeutered()) { exception_state.ThrowDOMException(kInvalidStateError, "The source data has been neutered."); return; } + ImageBuffer* buffer = GetImageBuffer(); if (!buffer) return; @@ -1696,10 +1769,22 @@ CheckOverdraw(dest_rect, 0, CanvasRenderingContext2DState::kNoImage, kUntransformedUnclippedFill); - buffer->PutByteArray(kUnmultiplied, data->data()->Data(), - IntSize(data->width(), data->height()), source_rect, - IntPoint(dest_offset)); + if (color_management_enabled_) { + unsigned data_length = data->width() * data->height() * 4; + if (PixelFormat() == kF16CanvasPixelFormat) + data_length *= 2; + std::unique_ptr<uint8_t[]> converted_pixels(new uint8_t[data_length]); + data->ImageDataInCanvasColorSettings(ColorSpace(), PixelFormat(), + converted_pixels); + buffer->PutByteArray(kUnmultiplied, converted_pixels.get(), + IntSize(data->width(), data->height()), source_rect, + IntPoint(dest_offset)); + } else { + buffer->PutByteArray(kUnmultiplied, data->data()->Data(), + IntSize(data->width(), data->height()), source_rect, + IntPoint(dest_offset)); + } DidDraw(dest_rect); }
diff --git a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.h b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.h index be6a723..7d9d7c5 100644 --- a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.h +++ b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.h
@@ -187,6 +187,20 @@ ImageData* createImageData(ImageData*, ExceptionState&) const; ImageData* createImageData(int width, int height, ExceptionState&) const; + ImageData* createImageData(unsigned, + unsigned, + ImageDataColorSettings&, + ExceptionState&) const; + ImageData* createImageData(ImageDataArray&, + unsigned, + unsigned, + ExceptionState&) const; + ImageData* createImageData(ImageDataArray&, + unsigned, + unsigned, + ImageDataColorSettings&, + ExceptionState&) const; + ImageData* getImageData(int sx, int sy, int sw, int sh, ExceptionState&); void putImageData(ImageData*, int dx, int dy, ExceptionState&); void putImageData(ImageData*, @@ -238,6 +252,16 @@ virtual void WillDrawImage(CanvasImageSource*) const {} + virtual CanvasColorSpace ColorSpace() const { + return kLegacyCanvasColorSpace; + }; + virtual String ColorSpaceAsString() const { + return kLegacyCanvasColorSpaceName; + } + virtual CanvasPixelFormat PixelFormat() const { + return kRGBA8CanvasPixelFormat; + } + void RestoreMatrixClipStack(PaintCanvas*) const; DECLARE_VIRTUAL_TRACE(); @@ -372,6 +396,10 @@ void ClearCanvas(); bool RectContainsTransformedRect(const FloatRect&, const SkIRect&) const; + + ImageDataColorSettings GetColorSettingsAsImageDataColorSettings() const; + + bool color_management_enabled_; }; template <typename DrawFunc, typename ContainsFunc>
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp index 7110a2f5..4ef70aea 100644 --- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp +++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp
@@ -279,6 +279,18 @@ canvas()->WillDrawImageTo2DContext(source); } +CanvasColorSpace CanvasRenderingContext2D::ColorSpace() const { + return color_params().color_space(); +} + +String CanvasRenderingContext2D::ColorSpaceAsString() const { + return CanvasRenderingContext::ColorSpaceAsString(); +} + +CanvasPixelFormat CanvasRenderingContext2D::PixelFormat() const { + return color_params().pixel_format(); +} + ColorBehavior CanvasRenderingContext2D::DrawImageColorBehavior() const { return CanvasRenderingContext::ColorBehaviorForMediaDrawnToCanvas(); }
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.h b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.h index 8782be3..70ecb783 100644 --- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.h +++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.h
@@ -243,6 +243,11 @@ CanvasRenderingContext::ContextType GetContextType() const override { return CanvasRenderingContext::kContext2d; } + + CanvasColorSpace ColorSpace() const override; + String ColorSpaceAsString() const override; + CanvasPixelFormat PixelFormat() const override; + bool Is2d() const override { return true; } bool IsComposited() const override; bool IsAccelerated() const override;
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.idl b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.idl index fcd7a1dc2..bb229a9 100644 --- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.idl +++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.idl
@@ -129,6 +129,10 @@ [RaisesException] ImageData getImageData(long sx, long sy, long sw, long sh); [RaisesException] void putImageData(ImageData imagedata, long dx, long dy); [RaisesException] void putImageData(ImageData imagedata, long dx, long dy, long dirtyX, long dirtyY, long dirtyWidth, long dirtyHeight); + + // https://github.com/WICG/canvas-color-space/blob/master/CanvasColorSpaceProposal.md + [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] ImageData createImageData(unsigned long sw, unsigned long sh, ImageDataColorSettings imageDataColorSettings); + [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] ImageData createImageData(ImageDataArray data, unsigned long sw, unsigned long sh, optional ImageDataColorSettings imageDataColorSettings); // Context state // Should be merged with WebGL counterpart in CanvasRenderingContext, once no-longer experimental
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp index cfc096c7..3489a30 100644 --- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp +++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
@@ -37,6 +37,7 @@ #include "third_party/skia/include/core/SkColorSpaceXform.h" #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkSurface.h" +#include "third_party/skia/include/core/SkSwizzle.h" using ::testing::Mock; @@ -1342,6 +1343,291 @@ color_correct_rendering_default_mode_runtime_flag); } +bool ConvertPixelsToColorSpaceAndPixelFormatForTest( + DOMArrayBufferView* data_array, + CanvasColorSpace src_color_space, + CanvasColorSpace dst_color_space, + CanvasPixelFormat dst_pixel_format, + std::unique_ptr<uint8_t[]>& converted_pixels) { + // Setting SkColorSpaceXform::apply parameters + SkColorSpaceXform::ColorFormat src_color_format = + SkColorSpaceXform::kRGBA_8888_ColorFormat; + + unsigned data_length = data_array->byteLength() / data_array->TypeSize(); + unsigned num_pixels = data_length / 4; + DOMUint8ClampedArray* u8_array = nullptr; + DOMUint16Array* u16_array = nullptr; + DOMFloat32Array* f32_array = nullptr; + void* src_data = nullptr; + + switch (data_array->GetType()) { + case ArrayBufferView::ViewType::kTypeUint8Clamped: + u8_array = const_cast<DOMUint8ClampedArray*>( + static_cast<const DOMUint8ClampedArray*>(data_array)); + src_data = static_cast<void*>(u8_array->Data()); + break; + + case ArrayBufferView::ViewType::kTypeUint16: + u16_array = const_cast<DOMUint16Array*>( + static_cast<const DOMUint16Array*>(data_array)); + src_color_format = + SkColorSpaceXform::ColorFormat::kRGBA_U16_BE_ColorFormat; + src_data = static_cast<void*>(u16_array->Data()); + break; + + case ArrayBufferView::ViewType::kTypeFloat32: + f32_array = const_cast<DOMFloat32Array*>( + static_cast<const DOMFloat32Array*>(data_array)); + src_color_format = SkColorSpaceXform::kRGBA_F32_ColorFormat; + src_data = static_cast<void*>(f32_array->Data()); + break; + default: + NOTREACHED(); + return false; + } + + SkColorSpaceXform::ColorFormat dst_color_format = + SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat; + if (dst_pixel_format == kF16CanvasPixelFormat) + dst_color_format = SkColorSpaceXform::ColorFormat::kRGBA_F32_ColorFormat; + + sk_sp<SkColorSpace> src_sk_color_space = nullptr; + if (u8_array) { + src_sk_color_space = ImageData::GetSkColorSpaceForTest( + src_color_space, kRGBA8CanvasPixelFormat); + } else { + src_sk_color_space = ImageData::GetSkColorSpaceForTest( + src_color_space, kF16CanvasPixelFormat); + } + + sk_sp<SkColorSpace> dst_sk_color_space = + ImageData::GetSkColorSpaceForTest(dst_color_space, dst_pixel_format); + + // When the input dataArray is in Uint16, we normally should convert the + // values from Little Endian to Big Endian before passing the buffer to + // SkColorSpaceXform::apply. However, in this test scenario we are creating + // the Uin16 dataArray by multiplying a Uint8Clamped array members by 257, + // hence the Big Endian and Little Endian representations are the same. + + std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New( + src_sk_color_space.get(), dst_sk_color_space.get()); + + if (!xform->apply(dst_color_format, converted_pixels.get(), src_color_format, + src_data, num_pixels, kUnpremul_SkAlphaType)) + return false; + return true; +} + +// The color settings of the surface of the canvas always remaines loyal to the +// first created context 2D. Therefore, we have to test different canvas color +// space settings for CanvasRenderingContext2D::putImageData() in different +// tests. +enum class CanvasColorSpaceSettings : uint8_t { + CANVAS_SRGB = 0, + CANVAS_LINEARSRGB = 1, + CANVAS_REC2020 = 2, + CANVAS_P3 = 3, + + LAST = CANVAS_P3 +}; + +// This test verifies the correct behavior of putImageData member function in +// color managed mode. +void TestPutImageDataOnCanvasWithColorSpaceSettings( + HTMLCanvasElement& canvas_element, + CanvasColorSpaceSettings canvas_colorspace_setting, + float color_tolerance) { + bool experimental_canvas_features_runtime_flag = + RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled(); + bool color_correct_rendering_runtime_flag = + RuntimeEnabledFeatures::colorCorrectRenderingEnabled(); + RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled(true); + RuntimeEnabledFeatures::setColorCorrectRenderingEnabled(true); + + bool test_passed = true; + unsigned num_image_data_color_spaces = 3; + CanvasColorSpace image_data_color_spaces[] = { + kSRGBCanvasColorSpace, kRec2020CanvasColorSpace, kP3CanvasColorSpace, + }; + + unsigned num_image_data_storage_formats = 3; + ImageDataStorageFormat image_data_storage_formats[] = { + kUint8ClampedArrayStorageFormat, kUint16ArrayStorageFormat, + kFloat32ArrayStorageFormat, + }; + + CanvasColorSpace canvas_color_spaces[] = { + kSRGBCanvasColorSpace, kSRGBCanvasColorSpace, kRec2020CanvasColorSpace, + kP3CanvasColorSpace, + }; + + String canvas_color_space_names[] = { + kSRGBCanvasColorSpaceName, kSRGBCanvasColorSpaceName, + kRec2020CanvasColorSpaceName, kP3CanvasColorSpaceName}; + + CanvasPixelFormat canvas_pixel_formats[] = { + kRGBA8CanvasPixelFormat, kF16CanvasPixelFormat, kF16CanvasPixelFormat, + kF16CanvasPixelFormat, + }; + + String canvas_pixel_format_names[] = { + kRGBA8CanvasPixelFormatName, kF16CanvasPixelFormatName, + kF16CanvasPixelFormatName, kF16CanvasPixelFormatName}; + + // Source pixels in RGBA32 + uint8_t u8_pixels[] = {255, 0, 0, 255, // Red + 0, 0, 0, 0, // Transparent + 255, 192, 128, 64, // Decreasing values + 93, 117, 205, 11}; // Random values + unsigned data_length = 16; + + uint16_t* u16_pixels = new uint16_t[data_length]; + for (unsigned i = 0; i < data_length; i++) + u16_pixels[i] = u8_pixels[i] * 257; + + float* f32_pixels = new float[data_length]; + for (unsigned i = 0; i < data_length; i++) + f32_pixels[i] = u8_pixels[i] / 255.0; + + DOMArrayBufferView* data_array = nullptr; + + DOMUint8ClampedArray* data_u8 = + DOMUint8ClampedArray::Create(u8_pixels, data_length); + DCHECK(data_u8); + EXPECT_EQ(data_length, data_u8->length()); + DOMUint16Array* data_u16 = DOMUint16Array::Create(u16_pixels, data_length); + DCHECK(data_u16); + EXPECT_EQ(data_length, data_u16->length()); + DOMFloat32Array* data_f32 = DOMFloat32Array::Create(f32_pixels, data_length); + DCHECK(data_f32); + EXPECT_EQ(data_length, data_f32->length()); + + ImageData* image_data = nullptr; + ImageDataColorSettings color_settings; + + // At most four bytes are needed for Float32 output per color component. + std::unique_ptr<uint8_t[]> pixels_converted_manually( + new uint8_t[data_length * 4]()); + + // Loop through different possible combinations of image data color space and + // storage formats and create the respective test image data objects. + for (unsigned i = 0; i < num_image_data_color_spaces; i++) { + color_settings.setColorSpace( + ImageData::CanvasColorSpaceName(image_data_color_spaces[i])); + + for (unsigned j = 0; j < num_image_data_storage_formats; j++) { + switch (image_data_storage_formats[j]) { + case kUint8ClampedArrayStorageFormat: + data_array = static_cast<DOMArrayBufferView*>(data_u8); + color_settings.setStorageFormat(kUint8ClampedArrayStorageFormatName); + break; + case kUint16ArrayStorageFormat: + data_array = static_cast<DOMArrayBufferView*>(data_u16); + color_settings.setStorageFormat(kUint16ArrayStorageFormatName); + break; + case kFloat32ArrayStorageFormat: + data_array = static_cast<DOMArrayBufferView*>(data_f32); + color_settings.setStorageFormat(kFloat32ArrayStorageFormatName); + break; + default: + NOTREACHED(); + } + + image_data = + ImageData::CreateForTest(IntSize(2, 2), data_array, &color_settings); + + unsigned k = (unsigned)(canvas_colorspace_setting); + // Convert the original data used to create ImageData to the + // canvas color space and canvas pixel format. + EXPECT_TRUE(ConvertPixelsToColorSpaceAndPixelFormatForTest( + data_array, image_data_color_spaces[i], canvas_color_spaces[k], + canvas_pixel_formats[k], pixels_converted_manually)); + + // Create a canvas and call putImageData and getImageData to make sure + // the conversion is done correctly. + CanvasContextCreationAttributes attributes; + attributes.setAlpha(true); + attributes.setColorSpace(canvas_color_space_names[k]); + attributes.setPixelFormat(canvas_pixel_format_names[k]); + CanvasRenderingContext2D* context = + static_cast<CanvasRenderingContext2D*>( + canvas_element.GetCanvasRenderingContext("2d", attributes)); + NonThrowableExceptionState exception_state; + context->putImageData(image_data, 0, 0, exception_state); + + void* pixels_from_get_image_data = nullptr; + if (canvas_pixel_formats[k] == kRGBA8CanvasPixelFormat) { + pixels_from_get_image_data = + context->getImageData(0, 0, 2, 2, exception_state)->data()->Data(); + // Swizzle if needed + if (kN32_SkColorType == kBGRA_8888_SkColorType) { + SkSwapRB(static_cast<uint32_t*>(pixels_from_get_image_data), + static_cast<uint32_t*>(pixels_from_get_image_data), + data_length / 4); + } + + unsigned char* cpixels1 = + static_cast<unsigned char*>(pixels_converted_manually.get()); + unsigned char* cpixels2 = + static_cast<unsigned char*>(pixels_from_get_image_data); + for (unsigned m = 0; m < data_length; m++) { + if (abs(cpixels1[m] - cpixels2[m]) > color_tolerance) + test_passed = false; + } + } else { + pixels_from_get_image_data = + context->getImageData(0, 0, 2, 2, exception_state) + ->dataUnion() + .getAsFloat32Array() + .View() + ->Data(); + float* fpixels1 = nullptr; + float* fpixels2 = nullptr; + void* vpointer = pixels_converted_manually.get(); + fpixels1 = static_cast<float*>(vpointer); + fpixels2 = static_cast<float*>(pixels_from_get_image_data); + for (unsigned m = 0; m < data_length; m++) { + if (fpixels1[m] < 0) + fpixels1[m] = 0; + if (fabs(fpixels1[m] - fpixels2[m]) > color_tolerance) { + test_passed = false; + } + } + + ASSERT_TRUE(test_passed); + } + } + } + delete[] u16_pixels; + delete[] f32_pixels; + + RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled( + experimental_canvas_features_runtime_flag); + RuntimeEnabledFeatures::setColorCorrectRenderingEnabled( + color_correct_rendering_runtime_flag); +} + +TEST_F(CanvasRenderingContext2DTest, ColorManagedPutImageDataOnSRGBCanvas) { + TestPutImageDataOnCanvasWithColorSpaceSettings( + CanvasElement(), CanvasColorSpaceSettings::CANVAS_SRGB, 0); +} + +TEST_F(CanvasRenderingContext2DTest, + ColorManagedPutImageDataOnLinearSRGBCanvas) { + TestPutImageDataOnCanvasWithColorSpaceSettings( + CanvasElement(), CanvasColorSpaceSettings::CANVAS_LINEARSRGB, 0.15); +} + +TEST_F(CanvasRenderingContext2DTest, ColorManagedPutImageDataOnRec2020Canvas) { + TestPutImageDataOnCanvasWithColorSpaceSettings( + CanvasElement(), CanvasColorSpaceSettings::CANVAS_REC2020, 0.1); +} + +TEST_F(CanvasRenderingContext2DTest, ColorManagedPutImageDataOnP3Canvas) { + TestPutImageDataOnCanvasWithColorSpaceSettings( + CanvasElement(), CanvasColorSpaceSettings::CANVAS_P3, 0.1); +} + void OverrideScriptEnabled(Settings& settings) { // Simulate that we allow scripts, so that HTMLCanvasElement uses // LayoutHTMLCanvas.
diff --git a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp index a3f2088e..667d8b10 100644 --- a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp +++ b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp
@@ -245,6 +245,18 @@ return this->GetImageBuffer(); } +CanvasColorSpace OffscreenCanvasRenderingContext2D::ColorSpace() const { + return color_params().color_space(); +} + +String OffscreenCanvasRenderingContext2D::ColorSpaceAsString() const { + return CanvasRenderingContext::ColorSpaceAsString(); +} + +CanvasPixelFormat OffscreenCanvasRenderingContext2D::PixelFormat() const { + return color_params().pixel_format(); +} + bool OffscreenCanvasRenderingContext2D::IsAccelerated() const { return image_buffer_ && image_buffer_->IsAccelerated(); }
diff --git a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h index ede146f..c515145 100644 --- a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h +++ b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h
@@ -113,6 +113,10 @@ bool IsPaintable() const final; RefPtr<StaticBitmapImage> TransferToStaticBitmapImage(); + + CanvasColorSpace ColorSpace() const override; + String ColorSpaceAsString() const override; + CanvasPixelFormat PixelFormat() const override; }; // TODO(fserb): remove this.
diff --git a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.idl b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.idl index 016eb1d..e2a0113 100644 --- a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.idl +++ b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.idl
@@ -76,6 +76,12 @@ [RaisesException] ImageData getImageData(long sx, long sy, long sw, long sh); [RaisesException] void putImageData(ImageData imagedata, long dx, long dy); [RaisesException] void putImageData(ImageData imagedata, long dx, long dy, long dirtyX, long dirtyY, long dirtyWidth, long dirtyHeight); + + // If OffscreenCanva ships before color managed canvas, this method must remain behind flag. + // https://github.com/WICG/canvas-color-space/blob/master/CanvasColorSpaceProposal.md + [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] ImageData createImageData(unsigned long sw, unsigned long sh, ImageDataColorSettings imageDataColorSettings); + [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] ImageData createImageData(ImageDataArray data, unsigned long sw, unsigned long sh, ImageDataColorSettings imageDataColorSettings); + // Line caps/joins attribute unrestricted double lineWidth; // (default 1)
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 index bc001d9..991341f 100644 --- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 +++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
@@ -289,7 +289,7 @@ }, { name: "CSSSelectorsFocusWithin", - status: "experimental", + status: "stable", }, { name: "CSSSnapSize",
diff --git a/third_party/WebKit/Source/platform/graphics/CanvasColorParams.cpp b/third_party/WebKit/Source/platform/graphics/CanvasColorParams.cpp index 80edcb1..a99b4744 100644 --- a/third_party/WebKit/Source/platform/graphics/CanvasColorParams.cpp +++ b/third_party/WebKit/Source/platform/graphics/CanvasColorParams.cpp
@@ -19,9 +19,21 @@ } sk_sp<SkColorSpace> CanvasColorParams::GetSkColorSpaceForSkSurfaces() const { - if (color_space_ == kLegacyCanvasColorSpace) - return nullptr; - return GetGfxColorSpace().ToSkColorSpace(); + switch (color_space_) { + case kLegacyCanvasColorSpace: + return nullptr; + case kSRGBCanvasColorSpace: + if (pixel_format_ == kF16CanvasPixelFormat) + return SkColorSpace::MakeSRGBLinear(); + return SkColorSpace::MakeSRGB(); + case kRec2020CanvasColorSpace: + return SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, + SkColorSpace::kRec2020_Gamut); + case kP3CanvasColorSpace: + return SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, + SkColorSpace::kDCIP3_D65_Gamut); + } + return nullptr; } SkColorType CanvasColorParams::GetSkColorType() const {
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp index 0f6039a9..23e4a518 100644 --- a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp +++ b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
@@ -390,51 +390,21 @@ WTF::ArrayBufferContents result(std::move(data), alloc_size_in_bytes, WTF::ArrayBufferContents::kNotShared); - // Skia does not support unpremultiplied read with an F16 to 8888 conversion - bool use_f16_workaround = - surface_->color_params().GetSkColorType() == kRGBA_F16_SkColorType; - - SkAlphaType alpha_type = (multiplied == kPremultiplied || use_f16_workaround) + SkAlphaType alpha_type = (multiplied == kPremultiplied) ? kPremul_SkAlphaType : kUnpremul_SkAlphaType; - // The workaround path use a canvas draw under the hood, which can only - // use N32 at this time. SkColorType color_type = - use_f16_workaround ? kN32_SkColorType : kRGBA_8888_SkColorType; + (surface_->color_params().GetSkColorType() == kRGBA_F16_SkColorType) + ? kRGBA_F16_SkColorType + : kRGBA_8888_SkColorType; - // Only use sRGB when the surface has a color space. Converting untagged - // pixels to a particular color space is not well-defined in Skia. - sk_sp<SkColorSpace> color_space = - surface_->color_params().GetSkColorSpaceForSkSurfaces(); - - SkImageInfo info = SkImageInfo::Make(rect.Width(), rect.Height(), color_type, - alpha_type, std::move(color_space)); + SkImageInfo info = SkImageInfo::Make( + rect.Width(), rect.Height(), color_type, alpha_type, + surface_->color_params().GetSkColorSpaceForSkSurfaces()); snapshot->readPixels(info, result.Data(), bytes_per_pixel * rect.Width(), rect.X(), rect.Y()); gpu_readback_invoked_in_current_frame_ = true; - - if (use_f16_workaround) { - uint32_t* pixel = (uint32_t*)result.Data(); - size_t pixel_count = alloc_size_in_bytes / sizeof(uint32_t); - // TODO(skbug.com/5853): make readPixels support RGBA output so that we no - // longer - // have to do this. - if (kN32_SkColorType == kBGRA_8888_SkColorType) { - // Convert BGRA to RGBA if necessary on this platform. - SkSwapRB(pixel, pixel, pixel_count); - } - // TODO(skbug.com/5853): We should really be doing the unpremultiply in - // linear space - // and skia should provide that service. - if (multiplied == kUnmultiplied) { - for (; pixel_count; --pixel_count) { - *pixel = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(*pixel); - ++pixel; - } - } - } - result.Transfer(contents); return true; }
diff --git a/tools/perf/benchmarks/blink_perf.js b/tools/perf/benchmarks/blink_perf.js index 465e1ff..bb764cf 100644 --- a/tools/perf/benchmarks/blink_perf.js +++ b/tools/perf/benchmarks/blink_perf.js
@@ -12,6 +12,24 @@ this.isDone = true; }; +testRunner.supportTracing = true; + +// If this is true, blink_perf tests is put on paused waiting for tracing to +// be started. |scheduleTestRun| should be invoked after tracing is started +// to continue blink perf test. +testRunner.isWaitingForTracingStart = false; + +testRunner.startTracing = function(tracingCategories, scheduleTestRun) { + this.tracingCategories = tracingCategories; + this.scheduleTestRun = scheduleTestRun; + this.isWaitingForTracingStart = true; +} + +testRunner.stopTracingAndMeasure = function(traceEventsToMeasure, callback) { + testRunner.traceEventsToMeasure = traceEventsToMeasure; + callback(); +} + window.GCController = {}; GCController.collect = function() {
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py index 64a55a45..c30bcbcf 100644 --- a/tools/perf/benchmarks/blink_perf.py +++ b/tools/perf/benchmarks/blink_perf.py
@@ -12,8 +12,14 @@ from telemetry.page import legacy_page_test from telemetry.page import shared_page_state from telemetry import story +from telemetry.timeline import bounds +from telemetry.timeline import model as model_module +from telemetry.timeline import tracing_config + from telemetry.value import list_of_scalar_values from telemetry.value import scalar +from telemetry.value import trace + from benchmarks import pywebsocket_server from measurements import timeline_controller @@ -73,6 +79,56 @@ return ps +def _ComputeTraceEventsThreadTimeForBlinkPerf( + renderer_thread, trace_events_to_measure): + """ Compute the CPU duration for each of |trace_events_to_measure| during + blink_perf test. + + Args: + renderer_thread: the renderer thread which run blink_perf test. + trace_events_to_measure: a list of string names of trace events to measure + CPU duration for. + + Returns: + a dictionary in which each key is a trace event' name (from + |trace_events_to_measure| list), and value is a list of numbers that + represents to total cpu time of that trace events in each blink_perf test. + """ + trace_cpu_time_metrics = {} + + # Collect the bounds of "blink_perf.runTest" events. + test_runs_bounds = [] + for event in renderer_thread.async_slices: + if event.name == "blink_perf.runTest": + test_runs_bounds.append(bounds.Bounds.CreateFromEvent(event)) + test_runs_bounds.sort(key=lambda b: b.min) + + for t in trace_events_to_measure: + trace_cpu_time_metrics[t] = [0.0] * len(test_runs_bounds) + + for event_name in trace_events_to_measure: + curr_test_runs_bound_index = 0 + for event in renderer_thread.IterAllSlicesOfName(event_name): + while (curr_test_runs_bound_index < len(test_runs_bounds) and + event.start > test_runs_bounds[curr_test_runs_bound_index].max): + curr_test_runs_bound_index += 1 + if curr_test_runs_bound_index >= len(test_runs_bounds): + break + curr_test_bound = test_runs_bounds[curr_test_runs_bound_index] + intersect_wall_time = bounds.Bounds.GetOverlapBetweenBounds( + curr_test_bound, bounds.Bounds.CreateFromEvent(event)) + if event.thread_duration and event.duration: + intersect_cpu_time = ( + intersect_wall_time * event.thread_duration / event.duration) + else: + intersect_cpu_time = intersect_wall_time + trace_cpu_time_metrics[event_name][curr_test_runs_bound_index] += ( + intersect_cpu_time) + + return trace_cpu_time_metrics + + + class _BlinkPerfMeasurement(legacy_page_test.LegacyPageTest): """Tuns a blink performance test and reports the results.""" @@ -98,8 +154,53 @@ if 'content-shell' in options.browser_type: options.AppendExtraBrowserArgs('--expose-internals-for-testing') + def _ContinueTestRunWithTracing(self, tab): + tracing_categories = tab.EvaluateJavaScript( + 'testRunner.tracingCategories') + config = tracing_config.TracingConfig() + config.enable_chrome_trace = True + config.chrome_trace_config.category_filter.AddFilterString( + 'blink.console') # This is always required for js land trace event + config.chrome_trace_config.category_filter.AddFilterString( + tracing_categories) + tab.browser.platform.tracing_controller.StartTracing(config) + tab.EvaluateJavaScript('testRunner.scheduleTestRun()') + tab.WaitForJavaScriptCondition('testRunner.isDone') + return tab.browser.platform.tracing_controller.StopTracing() + + + def PrintAndCollectTraceEventMetrics(self, trace_cpu_time_metrics, results): + unit = 'ms' + print + for trace_event_name, cpu_times in trace_cpu_time_metrics.iteritems(): + print 'CPU times of trace event "%s":' % trace_event_name + cpu_times_string = ', '.join(['{0:.10f}'.format(t) for t in cpu_times]) + print 'values %s %s' % (cpu_times_string, unit) + avg = 0.0 + if cpu_times: + avg = sum(cpu_times)/len(cpu_times) + print 'avg', '{0:.10f}'.format(avg), unit + results.AddValue(list_of_scalar_values.ListOfScalarValues( + results.current_page, name=trace_event_name, units=unit, + values=cpu_times)) + print + print '\n' + def ValidateAndMeasurePage(self, page, tab, results): - tab.WaitForJavaScriptCondition('testRunner.isDone', timeout=600) + tab.WaitForJavaScriptCondition( + 'testRunner.isDone || testRunner.isWaitingForTracingStart', timeout=600) + trace_cpu_time_metrics = {} + if tab.EvaluateJavaScript('testRunner.isWaitingForTracingStart'): + trace_data = self._ContinueTestRunWithTracing(tab) + trace_value = trace.TraceValue(page, trace_data) + results.AddValue(trace_value) + + trace_events_to_measure = tab.EvaluateJavaScript( + 'window.testRunner.traceEventsToMeasure') + model = model_module.TimelineModel(trace_data) + renderer_thread = model.GetRendererThreadFromTabId(tab.id) + trace_cpu_time_metrics = _ComputeTraceEventsThreadTimeForBlinkPerf( + renderer_thread, trace_events_to_measure) log = tab.EvaluateJavaScript('document.getElementById("log").innerHTML') @@ -120,6 +221,8 @@ print log + self.PrintAndCollectTraceEventMetrics(trace_cpu_time_metrics, results) + # TODO(wangxianzhu): Convert the paint benchmarks to use the new blink_perf # tracing once it's ready.
diff --git a/tools/perf/benchmarks/blink_perf_unittest.py b/tools/perf/benchmarks/blink_perf_unittest.py new file mode 100644 index 0000000..26be0772 --- /dev/null +++ b/tools/perf/benchmarks/blink_perf_unittest.py
@@ -0,0 +1,183 @@ +# 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 unittest + +from telemetry import decorators +from telemetry import story +from telemetry.page import page as page_module +from telemetry.testing import options_for_unittests +from telemetry.testing import page_test_test_case +from telemetry.timeline import async_slice +from telemetry.timeline import model as model_module + + +from benchmarks import blink_perf + + +class BlinkPerfTest(page_test_test_case.PageTestTestCase): + _BLINK_PERF_TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), + '..', '..', '..', 'third_party', 'WebKit', 'PerformanceTests', + 'TestData') + + _BLINK_PERF_RESOURCES_DIR = os.path.join(os.path.dirname(__file__), + '..', '..', '..', 'third_party', 'WebKit', 'PerformanceTests', + 'resources') + def setUp(self): + self._options = options_for_unittests.GetCopy() + # pylint: disable=protected-access + self._measurement = blink_perf._BlinkPerfMeasurement() + # pylint: enable=protected-access + + def _CreateStorySetForTestFile(self, test_file_name): + story_set = story.StorySet(base_dir=self._BLINK_PERF_TEST_DATA_DIR, + serving_dirs={self._BLINK_PERF_TEST_DATA_DIR, + self._BLINK_PERF_RESOURCES_DIR}) + page = page_module.Page('file://' + test_file_name, story_set, + base_dir=story_set.base_dir) + story_set.AddStory(page) + return story_set + + @decorators.Disabled('win') # crbug.com/715822 + def testBlinkPerfTracingMetricsForMeasureTime(self): + results = self.RunMeasurement(measurement=self._measurement, + ps=self._CreateStorySetForTestFile('append-child-measure-time.html'), + options=self._options) + self.assertFalse(results.failures) + self.assertEquals(len(results.FindAllTraceValues()), 1) + + frame_view_layouts = results.FindAllPageSpecificValuesNamed( + 'FrameView::layout') + self.assertEquals(len(frame_view_layouts), 1) + self.assertGreater(frame_view_layouts[0].GetRepresentativeNumber, 0.1) + + update_layout_trees = results.FindAllPageSpecificValuesNamed( + 'UpdateLayoutTree') + self.assertEquals(len(update_layout_trees), 1) + self.assertGreater(update_layout_trees[0].GetRepresentativeNumber, 0.1) + + @decorators.Disabled('android') # crbug.com/715685 + def testBlinkPerfTracingMetricsForMeasureFrameTime(self): + results = self.RunMeasurement(measurement=self._measurement, + ps=self._CreateStorySetForTestFile( + 'color-changes-measure-frame-time.html'), + options=self._options) + self.assertFalse(results.failures) + self.assertEquals(len(results.FindAllTraceValues()), 1) + + frame_view_prepaints = results.FindAllPageSpecificValuesNamed( + 'FrameView::prePaint') + self.assertEquals(len(frame_view_prepaints), 1) + self.assertGreater(frame_view_prepaints[0].GetRepresentativeNumber, 0.1) + + frame_view_painttrees = results.FindAllPageSpecificValuesNamed( + 'FrameView::paintTree') + self.assertEquals(len(frame_view_painttrees), 1) + self.assertGreater(frame_view_painttrees[0].GetRepresentativeNumber, 0.1) + + +# pylint: disable=protected-access +# This is needed for testing _ComputeTraceEventsThreadTimeForBlinkPerf method. +class ComputeTraceEventsMetricsForBlinkPerfTest(unittest.TestCase): + + def _AddBlinkTestSlice(self, renderer_thread, start, end): + s = async_slice.AsyncSlice( + 'blink', 'blink_perf.runTest', + timestamp=start, duration=end - start, start_thread=renderer_thread, + end_thread=renderer_thread) + renderer_thread.AddAsyncSlice(s) + + def testTraceEventMetricsSingleBlinkTest(self): + model = model_module.TimelineModel() + renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2) + renderer_main.name = 'CrRendererMain' + + # Set up a main thread model that looks like: + # [ blink_perf.run_test ] + # | [ foo ] [ bar ] [ baz ] + # | | | | | | | | + # 100 120 140 400 420 500 550 600 + # | | | + # CPU dur: 15 18 70 + # + self._AddBlinkTestSlice(renderer_main, 100, 550) + + renderer_main.BeginSlice('blink', 'foo', 120, 122) + renderer_main.EndSlice(140, 137) + + renderer_main.BeginSlice('blink', 'bar', 400, 402) + renderer_main.EndSlice(420, 420) + + # Since this "baz" slice has CPU duration = 70ms, wall-time duration = 100ms + # & its overalapped wall-time with "blink_perf.run_test" is 50 ms, its + # overlapped CPU time with "blink_perf.run_test" is + # 50 * 70 / 100 = 35ms. + renderer_main.BeginSlice('blink', 'baz', 500, 520) + renderer_main.EndSlice(600, 590) + + self.assertEquals( + blink_perf._ComputeTraceEventsThreadTimeForBlinkPerf( + renderer_main, ['foo', 'bar', 'baz']), + {'foo': [15], 'bar': [18], 'baz': [35]}) + + + def testTraceEventMetricsMultiBlinkTest(self): + model = model_module.TimelineModel() + renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2) + renderer_main.name = 'CrRendererMain' + + # Set up a main thread model that looks like: + # [ blink_perf.run_test ] [ blink_perf.run_test ] + # | [ foo ] [ bar ] | [ | foo ] | + # | | | | | | | | | | | + # 100 120 140 400 420 440 500 520 600 640 + # | | | + # CPU dur: 15 18 40 + # + self._AddBlinkTestSlice(renderer_main, 100, 440) + self._AddBlinkTestSlice(renderer_main, 520, 640) + + renderer_main.BeginSlice('blink', 'foo', 120, 122) + renderer_main.EndSlice(140, 137) + + renderer_main.BeginSlice('blink', 'bar', 400, 402) + renderer_main.EndSlice(420, 420) + + # Since this "foo" slice has CPU duration = 40ms, wall-time duration = 100ms + # & its overalapped wall-time with "blink_perf.run_test" is 80 ms, its + # overlapped CPU time with "blink_perf.run_test" is + # 80 * 40 / 100 = 32ms. + renderer_main.BeginSlice('blink', 'foo', 500, 520) + renderer_main.EndSlice(600, 560) + + self.assertEquals( + blink_perf._ComputeTraceEventsThreadTimeForBlinkPerf( + renderer_main, ['foo', 'bar', 'baz']), + {'foo': [15, 32], 'bar': [18, 0], 'baz': [0, 0]}) + + def testTraceEventMetricsNoThreadTimeAvailable(self): + model = model_module.TimelineModel() + renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2) + renderer_main.name = 'CrRendererMain' + + # Set up a main thread model that looks like: + # [ blink_perf.run_test ] + # | [ foo ] [ bar ] | + # | | | | | | + # 100 120 140 400 420 550 + # | | + # CPU dur: None None + # + self._AddBlinkTestSlice(renderer_main, 100, 550) + + renderer_main.BeginSlice('blink', 'foo', 120) + renderer_main.EndSlice(140) + + renderer_main.BeginSlice('blink', 'bar', 400) + renderer_main.EndSlice(420) + + self.assertEquals( + blink_perf._ComputeTraceEventsThreadTimeForBlinkPerf( + renderer_main, ['foo', 'bar']), + {'foo': [20], 'bar': [20]})
diff --git a/tools/perf/page_sets/system_health/loading_stories.py b/tools/perf/page_sets/system_health/loading_stories.py index b5c99a1..465ee822 100644 --- a/tools/perf/page_sets/system_health/loading_stories.py +++ b/tools/perf/page_sets/system_health/loading_stories.py
@@ -356,6 +356,7 @@ TAGS = [story_tags.JAVASCRIPT_HEAVY] +@decorators.Disabled('all') # crbug.com/715936 class LoadDriveStory(_LoadingStory): NAME = 'load:tools:drive' URL = 'https://drive.google.com/drive/my-drive'
diff --git a/ui/base/clipboard/clipboard_android_unittest.cc b/ui/base/clipboard/clipboard_android_unittest.cc deleted file mode 100644 index d52013d4..0000000 --- a/ui/base/clipboard/clipboard_android_unittest.cc +++ /dev/null
@@ -1,90 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ui/base/clipboard/clipboard_android.h" - -#include "base/android/context_utils.h" -#include "base/android/jni_android.h" -#include "base/android/jni_string.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/clipboard/scoped_clipboard_writer.h" - -namespace ui { - -class ClipboardAndroidTest : public ::testing::Test { - public: - ~ClipboardAndroidTest() override { - Clipboard::DestroyClipboardForCurrentThread(); - }; - - protected: - Clipboard& clipboard() { return *Clipboard::GetForCurrentThread(); } -}; - -// Test that if another application writes some text to the pasteboard the -// clipboard properly invalidates other types. -TEST_F(ClipboardAndroidTest, InternalClipboardInvalidation) { - // Write a Webkit smart paste tag to our clipboard. - { - ScopedClipboardWriter clipboard_writer(CLIPBOARD_TYPE_COPY_PASTE); - clipboard_writer.WriteWebSmartPaste(); - } - EXPECT_TRUE(clipboard().IsFormatAvailable( - Clipboard::GetWebKitSmartPasteFormatType(), CLIPBOARD_TYPE_COPY_PASTE)); - - // - // Simulate that another application copied something in the Clipboard - // - std::string new_value("Some text copied by some other app"); - using base::android::ConvertUTF8ToJavaString; - using base::android::MethodID; - using base::android::ScopedJavaLocalRef; - - JNIEnv* env = base::android::AttachCurrentThread(); - ASSERT_TRUE(env); - - ScopedJavaLocalRef<jclass> context_class = - base::android::GetClass(env, "android/content/Context"); - - jmethodID get_system_service = MethodID::Get<MethodID::TYPE_INSTANCE>( - env, context_class.obj(), "getSystemService", - "(Ljava/lang/String;)Ljava/lang/Object;"); - - // Retrieve the system service. - ScopedJavaLocalRef<jstring> service_name = - ConvertUTF8ToJavaString(env, "clipboard"); - ScopedJavaLocalRef<jobject> clipboard_manager( - env, - env->CallObjectMethod(base::android::GetApplicationContext(), - get_system_service, service_name.obj())); - ASSERT_TRUE(clipboard_manager.obj() && !base::android::ClearException(env)); - - ScopedJavaLocalRef<jclass> clipboard_class = - base::android::GetClass(env, "android/text/ClipboardManager"); - jmethodID set_text = MethodID::Get<MethodID::TYPE_INSTANCE>( - env, clipboard_class.obj(), "setText", "(Ljava/lang/CharSequence;)V"); - ScopedJavaLocalRef<jstring> new_value_string = - ConvertUTF8ToJavaString(env, new_value.c_str()); - - // Will need to call toString as CharSequence is not always a String. - env->CallVoidMethod(clipboard_manager.obj(), set_text, - new_value_string.obj()); - - // The WebKit smart paste tag should now be gone. - EXPECT_FALSE(clipboard().IsFormatAvailable( - Clipboard::GetWebKitSmartPasteFormatType(), CLIPBOARD_TYPE_COPY_PASTE)); - - // Make sure some text is available - EXPECT_TRUE(clipboard().IsFormatAvailable( - Clipboard::GetPlainTextWFormatType(), CLIPBOARD_TYPE_COPY_PASTE)); - - // Make sure the text is what we inserted while simulating the other app - std::string contents; - clipboard().ReadAsciiText(CLIPBOARD_TYPE_COPY_PASTE, &contents); - EXPECT_EQ(contents, new_value); -} - -} // namespace ui - -#include "ui/base/clipboard/clipboard_test_template.h"