diff --git a/DEPS b/DEPS index 93a093a..7773e974 100644 --- a/DEPS +++ b/DEPS
@@ -56,7 +56,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. - 'buildtools_revision': '38477c2e103caf651d113dad07cd3e4efb992209', + 'buildtools_revision': '7f2cacbbe274ef9df2c94452e05e8702c3ae65a9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSites.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSites.java index 1597af0..cac588939 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSites.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSites.java
@@ -90,15 +90,21 @@ void removeBlacklistedUrl(String url); /** - * Records metrics about an impression, including the sources (local, server, ...) and visual - * types of the tiles that are shown. - * @param tileTypes An array of values from {@link TileVisualType} indicating the type of each - * tile that's currently showing. - * @param sources An array of values from {@link TileSource} indicating the source of each tile - * that's currently showing. - * @param tileUrls An array of strings indicating the URL of each tile. + * Records metrics about an impression of the surface with tiles. + * @param tilesCount Count of tiles available on the surface at the moment. */ - void recordPageImpression(int[] tileTypes, int[] sources, String[] tileUrls); + void recordPageImpression(int tilesCount); + + /** + * Records metrics about an impression of a tile including its source (local, server, ...) and + * its visual type. + * @param index The index of the tile that was impressed (0-based). + * @param type The visual type of the item as defined in {@link TileVisualType}. + * @param source The {@link TileSource} that generated this item. + * @param url The URL of the tile. + */ + void recordTileImpression( + int index, @TileVisualType int type, @TileSource int source, String url); /** * Records the opening of a Most Visited Item.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSitesBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSitesBridge.java index d59c78349..ad5ff12 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSitesBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSitesBridge.java
@@ -94,8 +94,13 @@ } @Override - public void recordPageImpression(int[] tileTypes, int[] sources, String[] tileUrls) { - nativeRecordPageImpression(mNativeMostVisitedSitesBridge, tileTypes, sources, tileUrls); + public void recordPageImpression(int tilesCount) { + nativeRecordPageImpression(mNativeMostVisitedSitesBridge, tilesCount); + } + + @Override + public void recordTileImpression(int index, int type, int source, String url) { + nativeRecordTileImpression(mNativeMostVisitedSitesBridge, index, type, source, url); } @Override @@ -123,7 +128,9 @@ private native void nativeAddOrRemoveBlacklistedUrl( long nativeMostVisitedSitesBridge, String url, boolean addUrl); private native void nativeRecordPageImpression( - long nativeMostVisitedSitesBridge, int[] tileTypes, int[] sources, String[] tileUrls); + long nativeMostVisitedSitesBridge, int tilesCount); + private native void nativeRecordTileImpression( + long nativeMostVisitedSitesBridge, int index, int type, int source, String url); private native void nativeRecordOpenedMostVisitedItem( long nativeMostVisitedSitesBridge, int index, int tileType, int source); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroupDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroupDelegateImpl.java index cd3903aa..568dc875 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroupDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroupDelegateImpl.java
@@ -92,17 +92,12 @@ public void onLoadingComplete(Tile[] tiles) { assert !mIsDestroyed; - int types[] = new int[tiles.length]; - int sources[] = new int[tiles.length]; - String urls[] = new String[tiles.length]; - for (int i = 0; i < tiles.length; i++) { - types[i] = tiles[i].getType(); - sources[i] = tiles[i].getSource(); - urls[i] = tiles[i].getUrl(); + mMostVisitedSites.recordTileImpression( + i, tiles[i].getType(), tiles[i].getSource(), tiles[i].getUrl()); } - mMostVisitedSites.recordPageImpression(types, sources, urls); + mMostVisitedSites.recordPageImpression(tiles.length); } @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/FakeMostVisitedSites.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/FakeMostVisitedSites.java index 19061a35..a0fc588 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/FakeMostVisitedSites.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/FakeMostVisitedSites.java
@@ -49,7 +49,12 @@ } @Override - public void recordPageImpression(int[] sources, int[] tileTypes, String[] tileUrls) { + public void recordPageImpression(int tilesCount) { + // Metrics are stubbed out. + } + + @Override + public void recordTileImpression(int index, int source, int type, String url) { // Metrics are stubbed out. }
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index a45f527..94c51dcf 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1346,10 +1346,6 @@ "task_profiler/task_profiler_data_serializer.h", "themes/theme_service_win.cc", "themes/theme_service_win.h", - "thumbnails/content_analysis.cc", - "thumbnails/content_analysis.h", - "thumbnails/content_based_thumbnailing_algorithm.cc", - "thumbnails/content_based_thumbnailing_algorithm.h", "thumbnails/simple_thumbnail_crop.cc", "thumbnails/simple_thumbnail_crop.h", "thumbnails/thumbnail_list_source.cc",
diff --git a/chrome/browser/android/ntp/most_visited_sites_bridge.cc b/chrome/browser/android/ntp/most_visited_sites_bridge.cc index f43a562..4bc86d1 100644 --- a/chrome/browser/android/ntp/most_visited_sites_bridge.cc +++ b/chrome/browser/android/ntp/most_visited_sites_bridge.cc
@@ -34,7 +34,6 @@ using ntp_tiles::TileSource; using ntp_tiles::NTPTilesVector; using ntp_tiles::TileVisualType; -using ntp_tiles::metrics::TileImpression; namespace { @@ -171,28 +170,22 @@ void MostVisitedSitesBridge::RecordPageImpression( JNIEnv* env, const JavaParamRef<jobject>& obj, - const JavaParamRef<jintArray>& jtile_types, - const JavaParamRef<jintArray>& jsources, - const JavaParamRef<jobjectArray>& jtile_urls) { - std::vector<int> int_sources; - base::android::JavaIntArrayToIntVector(env, jsources, &int_sources); - std::vector<int> int_tile_types; - base::android::JavaIntArrayToIntVector(env, jtile_types, &int_tile_types); - std::vector<std::string> string_tile_urls; - base::android::AppendJavaStringArrayToStringVector(env, jtile_urls, - &string_tile_urls); + jint jtiles_count) { + ntp_tiles::metrics::RecordPageImpression(jtiles_count); +} - DCHECK_EQ(int_sources.size(), int_tile_types.size()); - DCHECK_EQ(int_sources.size(), string_tile_urls.size()); +void MostVisitedSitesBridge::RecordTileImpression( + JNIEnv* env, + const JavaParamRef<jobject>& obj, + jint jindex, + jint jtype, + jint jsource, + const JavaParamRef<jstring>& jurl) { + GURL url(ConvertJavaStringToUTF8(env, jurl)); + TileSource source = static_cast<TileSource>(jsource); + TileVisualType type = static_cast<TileVisualType>(jtype); - std::vector<TileImpression> tiles; - for (size_t i = 0; i < int_sources.size(); i++) { - TileSource source = static_cast<TileSource>(int_sources[i]); - TileVisualType tile_type = static_cast<TileVisualType>(int_tile_types[i]); - - tiles.emplace_back(source, tile_type, GURL(string_tile_urls[i])); - } - ntp_tiles::metrics::RecordPageImpression(tiles, + ntp_tiles::metrics::RecordTileImpression(jindex, source, type, url, g_browser_process->rappor_service()); }
diff --git a/chrome/browser/android/ntp/most_visited_sites_bridge.h b/chrome/browser/android/ntp/most_visited_sites_bridge.h index 3335f5d..bda4050c 100644 --- a/chrome/browser/android/ntp/most_visited_sites_bridge.h +++ b/chrome/browser/android/ntp/most_visited_sites_bridge.h
@@ -39,12 +39,15 @@ const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jstring>& j_url, jboolean add_url); - void RecordPageImpression( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj, - const base::android::JavaParamRef<jintArray>& jtile_types, - const base::android::JavaParamRef<jintArray>& jsources, - const base::android::JavaParamRef<jobjectArray>& jtile_urls); + void RecordPageImpression(JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj, + jint jtiles_count); + void RecordTileImpression(JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj, + jint jindex, + jint jtype, + jint jsource, + const base::android::JavaParamRef<jstring>& jurl); void RecordOpenedMostVisitedItem( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj,
diff --git a/chrome/browser/chromeos/login/app_launch_controller.cc b/chrome/browser/chromeos/login/app_launch_controller.cc index 94702527..9307f9f9 100644 --- a/chrome/browser/chromeos/login/app_launch_controller.cc +++ b/chrome/browser/chromeos/login/app_launch_controller.cc
@@ -111,8 +111,8 @@ weak_factory_(this) { if (!window_registry_->GetAppWindowsForApp(app_id).empty()) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&AppWindowWatcher::NotifyAppWindowCreated, - weak_factory_.GetWeakPtr())); + FROM_HERE, base::BindOnce(&AppWindowWatcher::NotifyAppWindowCreated, + weak_factory_.GetWeakPtr())); return; } else { window_registry_->AddObserver(this);
diff --git a/chrome/browser/chromeos/login/app_launch_signin_screen.cc b/chrome/browser/chromeos/login/app_launch_signin_screen.cc index 62e11a9..c94fdb8 100644 --- a/chrome/browser/chromeos/login/app_launch_signin_screen.cc +++ b/chrome/browser/chromeos/login/app_launch_signin_screen.cc
@@ -90,9 +90,8 @@ authenticator_ = UserSessionManager::GetInstance()->CreateAuthenticator(this); content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&Authenticator::AuthenticateToUnlock, - authenticator_.get(), - user_context)); + base::BindOnce(&Authenticator::AuthenticateToUnlock, authenticator_.get(), + user_context)); } void AppLaunchSigninScreen::MigrateUserData(const std::string& old_password) {
diff --git a/chrome/browser/chromeos/login/auth/auth_prewarmer.cc b/chrome/browser/chromeos/login/auth/auth_prewarmer.cc index 17ce83bf..3b811a9 100644 --- a/chrome/browser/chromeos/login/auth/auth_prewarmer.cc +++ b/chrome/browser/chromeos/login/auth/auth_prewarmer.cc
@@ -91,10 +91,10 @@ const GURL& url = GaiaUrls::GetInstance()->service_login_url(); content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::Bind(&content::PreconnectUrl, - ProfileHelper::GetSigninProfile()->GetResourceContext(), url, - url, kConnectionsNeeded, true, - net::HttpRequestInfo::EARLY_LOAD_MOTIVATED)); + base::BindOnce(&content::PreconnectUrl, + ProfileHelper::GetSigninProfile()->GetResourceContext(), + url, url, kConnectionsNeeded, true, + net::HttpRequestInfo::EARLY_LOAD_MOTIVATED)); if (!completion_callback_.is_null()) { content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, completion_callback_);
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc index 6877c0f9..efbda30b 100644 --- a/chrome/browser/chromeos/login/chrome_restart_request.cc +++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -308,9 +308,8 @@ base::FilePath(chrome::kLocalStorePoolName), BrowserThread::GetBlockingPool()); local_state_task_runner->PostTaskAndReply( - FROM_HERE, - base::Bind(&EnsureLocalStateIsWritten), - base::Bind(&ChromeRestartRequest::RestartJob, AsWeakPtr())); + FROM_HERE, base::BindOnce(&EnsureLocalStateIsWritten), + base::BindOnce(&ChromeRestartRequest::RestartJob, AsWeakPtr())); } void ChromeRestartRequest::RestartJob() {
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_reauth.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_reauth.cc index 0de29c0..5d266ab7 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_reauth.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_reauth.cc
@@ -100,7 +100,7 @@ callback_.Run(user_context); // Schedule deletion. base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&EndReauthAttempt)); + FROM_HERE, base::BindOnce(&EndReauthAttempt)); } void OnAuthFailure(const chromeos::AuthFailure& error) override {}
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.cc index 6376a3c..21a9117 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.cc
@@ -40,7 +40,7 @@ const base::Callback<void(crypto::ScopedPK11Slot)>& callback, crypto::ScopedPK11Slot slot) { response_task_runner->PostTask(FROM_HERE, - base::Bind(callback, base::Passed(&slot))); + base::BindOnce(callback, base::Passed(&slot))); } // Gets TPM system slot. Must be called on IO thread. @@ -114,7 +114,7 @@ if (!private_key) { LOG(ERROR) << "Private key for signing data not found"; response_task_runner->PostTask(FROM_HERE, - base::Bind(callback, std::string())); + base::BindOnce(callback, std::string())); return; } @@ -125,13 +125,14 @@ SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION) != SECSuccess) { LOG(ERROR) << "Failed to sign data"; response_task_runner->PostTask(FROM_HERE, - base::Bind(callback, std::string())); + base::BindOnce(callback, std::string())); return; } std::string signature(reinterpret_cast<const char*>(sign_result->data), sign_result->len); - response_task_runner->PostTask(FROM_HERE, base::Bind(callback, signature)); + response_task_runner->PostTask(FROM_HERE, + base::BindOnce(callback, signature)); } // Creates a RSA key pair in |slot|. When done, it runs |callback| with the @@ -146,7 +147,8 @@ const base::Callback<void(const std::string&)>& callback) { if (!public_key.empty() && GetPrivateKeyOnWorkerThread(slot.get(), public_key)) { - response_task_runner->PostTask(FROM_HERE, base::Bind(callback, public_key)); + response_task_runner->PostTask(FROM_HERE, + base::BindOnce(callback, public_key)); return; } @@ -157,7 +159,7 @@ &private_key_obj)) { LOG(ERROR) << "Failed to create an RSA key."; response_task_runner->PostTask(FROM_HERE, - base::Bind(callback, std::string())); + base::BindOnce(callback, std::string())); return; } @@ -166,14 +168,15 @@ if (!public_key_der) { LOG(ERROR) << "Failed to export public key."; response_task_runner->PostTask(FROM_HERE, - base::Bind(callback, std::string())); + base::BindOnce(callback, std::string())); return; } response_task_runner->PostTask( - FROM_HERE, base::Bind(callback, std::string(reinterpret_cast<const char*>( - public_key_der->data), - public_key_der->len))); + FROM_HERE, + base::BindOnce(callback, std::string(reinterpret_cast<const char*>( + public_key_der->data), + public_key_der->len))); } } // namespace @@ -237,8 +240,8 @@ content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::Bind(&EnsureUserTPMInitializedOnIOThread, username_hash_, - base::ThreadTaskRunnerHandle::Get(), on_user_tpm_ready)); + base::BindOnce(&EnsureUserTPMInitializedOnIOThread, username_hash_, + base::ThreadTaskRunnerHandle::Get(), on_user_tpm_ready)); } return false; @@ -250,9 +253,9 @@ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, - base::Bind(&EasyUnlockTpmKeyManager::OnTpmKeyCreated, - get_tpm_slot_weak_ptr_factory_.GetWeakPtr(), - std::string()), + base::BindOnce(&EasyUnlockTpmKeyManager::OnTpmKeyCreated, + get_tpm_slot_weak_ptr_factory_.GetWeakPtr(), + std::string()), base::TimeDelta::FromMilliseconds(timeout_ms)); return true; } @@ -287,11 +290,10 @@ key, data, callback); content::BrowserThread::PostTask( - content::BrowserThread::IO, - FROM_HERE, - base::Bind(&GetSystemSlotOnIOThread, - base::ThreadTaskRunnerHandle::Get(), - sign_with_system_slot)); + content::BrowserThread::IO, FROM_HERE, + base::BindOnce(&GetSystemSlotOnIOThread, + base::ThreadTaskRunnerHandle::Get(), + sign_with_system_slot)); } bool EasyUnlockTpmKeyManager::StartedCreatingTpmKeys() const { @@ -321,8 +323,9 @@ content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::Bind(&GetSystemSlotOnIOThread, base::ThreadTaskRunnerHandle::Get(), - create_key_with_system_slot)); + base::BindOnce(&GetSystemSlotOnIOThread, + base::ThreadTaskRunnerHandle::Get(), + create_key_with_system_slot)); } void EasyUnlockTpmKeyManager::CreateKeyInSystemSlot( @@ -341,10 +344,11 @@ base::PostTaskWithTraits( FROM_HERE, {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, - base::Bind(&CreateTpmKeyPairOnWorkerThread, base::Passed(&system_slot), - public_key, base::ThreadTaskRunnerHandle::Get(), - base::Bind(&EasyUnlockTpmKeyManager::OnTpmKeyCreated, - weak_ptr_factory_.GetWeakPtr()))); + base::BindOnce(&CreateTpmKeyPairOnWorkerThread, + base::Passed(&system_slot), public_key, + base::ThreadTaskRunnerHandle::Get(), + base::Bind(&EasyUnlockTpmKeyManager::OnTpmKeyCreated, + weak_ptr_factory_.GetWeakPtr()))); } void EasyUnlockTpmKeyManager::SignDataWithSystemSlot( @@ -358,10 +362,10 @@ base::PostTaskWithTraits( FROM_HERE, {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, - base::Bind(&SignDataOnWorkerThread, base::Passed(&system_slot), - public_key, data, base::ThreadTaskRunnerHandle::Get(), - base::Bind(&EasyUnlockTpmKeyManager::OnDataSigned, - weak_ptr_factory_.GetWeakPtr(), callback))); + base::BindOnce(&SignDataOnWorkerThread, base::Passed(&system_slot), + public_key, data, base::ThreadTaskRunnerHandle::Get(), + base::Bind(&EasyUnlockTpmKeyManager::OnDataSigned, + weak_ptr_factory_.GetWeakPtr(), callback))); } void EasyUnlockTpmKeyManager::OnTpmKeyCreated(const std::string& public_key) {
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_unittest.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_unittest.cc index 76aae0c..6e6d93a 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_unittest.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_unittest.cc
@@ -233,8 +233,8 @@ // Has to be done on IO thread due to thread assertions in nss code. content::BrowserThread::PostTaskAndReply( content::BrowserThread::IO, FROM_HERE, - base::Bind(&EasyUnlockTpmKeyManagerTest::InitTestNssUserOnIOThread, - base::Unretained(this), base::Unretained(&success)), + base::BindOnce(&EasyUnlockTpmKeyManagerTest::InitTestNssUserOnIOThread, + base::Unretained(this), base::Unretained(&success)), run_loop.QuitClosure()); run_loop.Run(); return success; @@ -257,8 +257,9 @@ // Has to be done on IO thread due to thread assertions in nss code. content::BrowserThread::PostTaskAndReply( content::BrowserThread::IO, FROM_HERE, - base::Bind(&EasyUnlockTpmKeyManagerTest::FinalizeTestNssUserOnIOThread, - base::Unretained(this)), + base::BindOnce( + &EasyUnlockTpmKeyManagerTest::FinalizeTestNssUserOnIOThread, + base::Unretained(this)), run_loop.QuitClosure()); run_loop.Run(); } @@ -270,8 +271,8 @@ // Has to be done on IO thread due to thread assertions in nss code. content::BrowserThread::PostTaskAndReply( content::BrowserThread::IO, FROM_HERE, - base::Bind(&EasyUnlockTpmKeyManagerTest::ResetTestNssUserOnIOThread, - base::Unretained(this)), + base::BindOnce(&EasyUnlockTpmKeyManagerTest::ResetTestNssUserOnIOThread, + base::Unretained(this)), run_loop.QuitClosure()); run_loop.Run(); }
diff --git a/chrome/browser/chromeos/login/easy_unlock/short_lived_user_context.cc b/chrome/browser/chromeos/login/easy_unlock/short_lived_user_context.cc index 270742f3..10b3dfb6 100644 --- a/chrome/browser/chromeos/login/easy_unlock/short_lived_user_context.cc +++ b/chrome/browser/chromeos/login/easy_unlock/short_lived_user_context.cc
@@ -32,7 +32,8 @@ task_runner->PostDelayedTask( FROM_HERE, - base::Bind(&ShortLivedUserContext::Reset, weak_ptr_factory_.GetWeakPtr()), + base::BindOnce(&ShortLivedUserContext::Reset, + weak_ptr_factory_.GetWeakPtr()), base::TimeDelta::FromMinutes(kUserContextTimeToLiveMinutes)); }
diff --git a/chrome/browser/chromeos/login/enable_debugging_browsertest.cc b/chrome/browser/chromeos/login/enable_debugging_browsertest.cc index 5a562e2..2874502 100644 --- a/chrome/browser/chromeos/login/enable_debugging_browsertest.cc +++ b/chrome/browser/chromeos/login/enable_debugging_browsertest.cc
@@ -84,7 +84,7 @@ bool succeeded) { LOG(WARNING) << "OnRemoveRootfsVerification: succeeded = " << succeeded; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(original_callback, succeeded)); + FROM_HERE, base::BindOnce(original_callback, succeeded)); if (runner_.get()) runner_->Quit(); else @@ -100,7 +100,7 @@ LOG(WARNING) << "OnQueryDebuggingFeatures: succeeded = " << succeeded << ", feature_mask = " << feature_mask; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(original_callback, succeeded, feature_mask)); + FROM_HERE, base::BindOnce(original_callback, succeeded, feature_mask)); if (runner_.get()) runner_->Quit(); else @@ -115,7 +115,7 @@ LOG(WARNING) << "OnEnableDebuggingFeatures: succeeded = " << succeeded << ", feature_mask = "; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(original_callback, succeeded)); + FROM_HERE, base::BindOnce(original_callback, succeeded)); if (runner_.get()) runner_->Quit(); else
diff --git a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc index a2d3773..9d494764 100644 --- a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc +++ b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc
@@ -245,9 +245,9 @@ // their work before. base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::Bind(&AutoEnrollmentCheckScreen::Finish, - weak_ptr_factory_.GetWeakPtr(), - ScreenExitCode::ENTERPRISE_AUTO_ENROLLMENT_CHECK_COMPLETED)); + base::BindOnce( + &AutoEnrollmentCheckScreen::Finish, weak_ptr_factory_.GetWeakPtr(), + ScreenExitCode::ENTERPRISE_AUTO_ENROLLMENT_CHECK_COMPLETED)); } bool AutoEnrollmentCheckScreen::IsCompleted() const {
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_screen_unittest.cc b/chrome/browser/chromeos/login/enrollment/enrollment_screen_unittest.cc index 8a380cf..e8c8daa 100644 --- a/chrome/browser/chromeos/login/enrollment/enrollment_screen_unittest.cc +++ b/chrome/browser/chromeos/login/enrollment/enrollment_screen_unittest.cc
@@ -158,8 +158,9 @@ // Schedule user retry button click after 30 sec. base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&EnrollmentScreen::OnRetry, - enrollment_screen_->weak_ptr_factory_.GetWeakPtr()), + FROM_HERE, + base::BindOnce(&EnrollmentScreen::OnRetry, + enrollment_screen_->weak_ptr_factory_.GetWeakPtr()), base::TimeDelta::FromSeconds(30)); // Fast forward time by 1 minute.
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc index 66bb6fa..7b3da7a 100644 --- a/chrome/browser/chromeos/login/existing_user_controller.cc +++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -152,7 +152,7 @@ // Last but not least tell the policy subsystem to refresh now as it might // have been stuck until now too. content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, - base::Bind(&RefreshPoliciesOnUIThread)); + base::BindOnce(&RefreshPoliciesOnUIThread)); } // Record UMA for password login of regular user when Easy sign-in is enabled. @@ -372,10 +372,10 @@ content::BrowserThread::PostDelayedTask( content::BrowserThread::IO, FROM_HERE, - base::Bind(&TransferContextAuthenticationsOnIOThread, - base::RetainedRef(signin_profile_context_getter), - base::RetainedRef(webview_context_getter), - base::RetainedRef(browser_process_context_getter)), + base::BindOnce(&TransferContextAuthenticationsOnIOThread, + base::RetainedRef(signin_profile_context_getter), + base::RetainedRef(webview_context_getter), + base::RetainedRef(browser_process_context_getter)), base::TimeDelta::FromMilliseconds(kAuthCacheTransferDelayMs)); } } @@ -727,9 +727,10 @@ ShowError(IDS_LOGIN_ERROR_OWNER_REQUIRED, error); content::BrowserThread::PostDelayedTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&SessionManagerClient::StopSession, - base::Unretained(DBusThreadManager::Get()-> - GetSessionManagerClient())), + base::BindOnce( + &SessionManagerClient::StopSession, + base::Unretained( + DBusThreadManager::Get()->GetSessionManagerClient())), base::TimeDelta::FromMilliseconds(kSafeModeRestartUiDelayMs)); } else if (failure.reason() == AuthFailure::TPM_ERROR) { ShowTPMError();
diff --git a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc index 7fc7149..3932372 100644 --- a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc +++ b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
@@ -266,7 +266,7 @@ profile_prepared_observer.Wait(); base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&ClearNotifications)); + FROM_HERE, base::BindOnce(&ClearNotifications)); content::RunAllPendingInMessageLoop(); } @@ -820,7 +820,7 @@ profile_prepared_observer.Wait(); base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&ClearNotifications)); + FROM_HERE, base::BindOnce(&ClearNotifications)); content::RunAllPendingInMessageLoop(); } @@ -840,7 +840,7 @@ profile_prepared_observer.Wait(); base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&ClearNotifications)); + FROM_HERE, base::BindOnce(&ClearNotifications)); content::RunAllPendingInMessageLoop(); }
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.cc b/chrome/browser/chromeos/login/lock/screen_locker.cc index 1a0599f7..fd78daa 100644 --- a/chrome/browser/chromeos/login/lock/screen_locker.cc +++ b/chrome/browser/chromeos/login/lock/screen_locker.cc
@@ -320,8 +320,9 @@ // Add guard for case when something get broken in call chain to unlock // for sure. base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&ScreenLocker::UnlockOnLoginSuccess, - weak_factory_.GetWeakPtr()), + FROM_HERE, + base::BindOnce(&ScreenLocker::UnlockOnLoginSuccess, + weak_factory_.GetWeakPtr()), base::TimeDelta::FromMilliseconds(kUnlockGuardTimeoutMs)); delegate_->AnimateAuthenticationSuccess(); @@ -397,20 +398,21 @@ ->TransformKey(user_context); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind(&ExtendedAuthenticator::AuthenticateToCheck, - extended_authenticator_.get(), updated_context, - base::Bind(&ScreenLocker::OnPasswordAuthSuccess, - weak_factory_.GetWeakPtr(), updated_context))); + base::BindOnce( + &ExtendedAuthenticator::AuthenticateToCheck, + extended_authenticator_.get(), updated_context, + base::Bind(&ScreenLocker::OnPasswordAuthSuccess, + weak_factory_.GetWeakPtr(), updated_context))); return; } } BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind(&ExtendedAuthenticator::AuthenticateToCheck, - extended_authenticator_.get(), user_context, - base::Bind(&ScreenLocker::OnPasswordAuthSuccess, - weak_factory_.GetWeakPtr(), user_context))); + base::BindOnce(&ExtendedAuthenticator::AuthenticateToCheck, + extended_authenticator_.get(), user_context, + base::Bind(&ScreenLocker::OnPasswordAuthSuccess, + weak_factory_.GetWeakPtr(), user_context))); } const user_manager::User* ScreenLocker::FindUnlockUser(
diff --git a/chrome/browser/chromeos/login/lock/webui_screen_locker.cc b/chrome/browser/chromeos/login/lock/webui_screen_locker.cc index b48de8e4..aa4fd53 100644 --- a/chrome/browser/chromeos/login/lock/webui_screen_locker.cc +++ b/chrome/browser/chromeos/login/lock/webui_screen_locker.cc
@@ -393,23 +393,23 @@ if (state == PowerManagerClient::LidState::OPEN) { content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&WebUIScreenLocker::FocusUserPod, - weak_factory_.GetWeakPtr())); + base::BindOnce(&WebUIScreenLocker::FocusUserPod, + weak_factory_.GetWeakPtr())); } } void WebUIScreenLocker::SuspendImminent() { content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&WebUIScreenLocker::ResetAndFocusUserPod, - weak_factory_.GetWeakPtr())); + base::BindOnce(&WebUIScreenLocker::ResetAndFocusUserPod, + weak_factory_.GetWeakPtr())); } void WebUIScreenLocker::SuspendDone(const base::TimeDelta& sleep_duration) { content::BrowserThread::PostTask( - content::BrowserThread::UI, - FROM_HERE, - base::Bind(&WebUIScreenLocker::FocusUserPod, weak_factory_.GetWeakPtr())); + content::BrowserThread::UI, FROM_HERE, + base::BindOnce(&WebUIScreenLocker::FocusUserPod, + weak_factory_.GetWeakPtr())); } void WebUIScreenLocker::RenderProcessGone(base::TerminationStatus status) {
diff --git a/chrome/browser/chromeos/login/login_browsertest.cc b/chrome/browser/chromeos/login/login_browsertest.cc index a1fd32e..44929f5 100644 --- a/chrome/browser/chromeos/login/login_browsertest.cc +++ b/chrome/browser/chromeos/login/login_browsertest.cc
@@ -221,8 +221,8 @@ StartupUtils::MarkOobeCompleted(); base::RunLoop loop; fake_auth_policy_client()->RefreshDevicePolicy( - base::Bind(&ActiveDirectoryLoginTest::OnRefreshedPolicy, - base::Unretained(this), loop.QuitClosure())); + base::BindOnce(&ActiveDirectoryLoginTest::OnRefreshedPolicy, + base::Unretained(this), loop.QuitClosure())); loop.Run(); }
diff --git a/chrome/browser/chromeos/login/login_screen_policy_browsertest.cc b/chrome/browser/chromeos/login/login_screen_policy_browsertest.cc index 5da1aaf..48824f9 100644 --- a/chrome/browser/chromeos/login/login_screen_policy_browsertest.cc +++ b/chrome/browser/chromeos/login/login_screen_policy_browsertest.cc
@@ -48,7 +48,7 @@ void TearDownOnMainThread() override { // This shuts down the login UI. base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&chrome::AttemptExit)); + FROM_HERE, base::BindOnce(&chrome::AttemptExit)); base::RunLoop().RunUntilIdle(); } };
diff --git a/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc b/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc index 2fc7f66..a9fe71d 100644 --- a/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc +++ b/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc
@@ -56,8 +56,8 @@ focused_ = true; if (runner_.get()) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&FocusPODWaiter::ExitMessageLoop, base::Unretained(this))); + FROM_HERE, base::BindOnce(&FocusPODWaiter::ExitMessageLoop, + base::Unretained(this))); } }
diff --git a/chrome/browser/chromeos/login/oobe_browsertest.cc b/chrome/browser/chromeos/login/oobe_browsertest.cc index fd2fb54..4cdcfd4 100644 --- a/chrome/browser/chromeos/login/oobe_browsertest.cc +++ b/chrome/browser/chromeos/login/oobe_browsertest.cc
@@ -47,7 +47,7 @@ // If the login display is still showing, exit gracefully. if (LoginDisplayHost::default_host()) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&chrome::AttemptExit)); + FROM_HERE, base::BindOnce(&chrome::AttemptExit)); content::RunMessageLoop(); }
diff --git a/chrome/browser/chromeos/login/profile_auth_data.cc b/chrome/browser/chromeos/login/profile_auth_data.cc index 08968f5..9fef4cb3 100644 --- a/chrome/browser/chromeos/login/profile_auth_data.cc +++ b/chrome/browser/chromeos/login/profile_auth_data.cc
@@ -179,8 +179,8 @@ } BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::Bind(&ProfileAuthDataTransferer::BeginTransferOnIOThread, - base::Unretained(this))); + base::BindOnce(&ProfileAuthDataTransferer::BeginTransferOnIOThread, + base::Unretained(this))); } void ProfileAuthDataTransferer::BeginTransferOnIOThread() {
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc index dda3f1f..428d8599 100644 --- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc +++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -1217,13 +1217,12 @@ ASSERT_TRUE(profile); base::RunLoop run_loop; content::BrowserThread::PostTask( - content::BrowserThread::IO, - FROM_HERE, - base::Bind(&SAMLPolicyTest::GetCookiesOnIOThread, - base::Unretained(this), - scoped_refptr<net::URLRequestContextGetter>( - profile->GetRequestContext()), - run_loop.QuitClosure())); + content::BrowserThread::IO, FROM_HERE, + base::BindOnce(&SAMLPolicyTest::GetCookiesOnIOThread, + base::Unretained(this), + scoped_refptr<net::URLRequestContextGetter>( + profile->GetRequestContext()), + run_loop.QuitClosure())); run_loop.Run(); }
diff --git a/chrome/browser/chromeos/login/screens/chrome_user_selection_screen.cc b/chrome/browser/chromeos/login/screens/chrome_user_selection_screen.cc index 0f2b0461..19ae27f0 100644 --- a/chrome/browser/chromeos/login/screens/chrome_user_selection_screen.cc +++ b/chrome/browser/chromeos/login/screens/chrome_user_selection_screen.cc
@@ -109,8 +109,8 @@ // been informed of the change. base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::Bind(&ChromeUserSelectionScreen::SetPublicSessionDisplayName, - weak_factory_.GetWeakPtr(), account_id)); + base::BindOnce(&ChromeUserSelectionScreen::SetPublicSessionDisplayName, + weak_factory_.GetWeakPtr(), account_id)); } void ChromeUserSelectionScreen::CheckForPublicSessionLocalePolicyChange(
diff --git a/chrome/browser/chromeos/login/screens/update_screen.cc b/chrome/browser/chromeos/login/screens/update_screen.cc index d26f50f7..c80d5ec 100644 --- a/chrome/browser/chromeos/login/screens/update_screen.cc +++ b/chrome/browser/chromeos/login/screens/update_screen.cc
@@ -361,7 +361,7 @@ is_first_detection_notification_ = false; base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::Bind( + base::BindOnce( base::IgnoreResult(&NetworkPortalDetector::StartDetectionIfIdle), base::Unretained(network_portal_detector::GetInstance()))); return; @@ -536,8 +536,8 @@ // Send UPDATE_STATUS_UPDATING message every |kHostStatusReportDelay|ms. base::SequencedTaskRunnerHandle::Get()->PostNonNestableDelayedTask( FROM_HERE, - base::Bind(&UpdateScreen::SetHostPairingControllerStatus, - weak_factory_.GetWeakPtr(), update_status), + base::BindOnce(&UpdateScreen::SetHostPairingControllerStatus, + weak_factory_.GetWeakPtr(), update_status), base::TimeDelta::FromMilliseconds(kHostStatusReportDelay)); } }
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index 478276e..a2ce9eb 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -1178,7 +1178,7 @@ // NOTIFICATION_PROFILE_CREATED which marks user profile as initialized. base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::Bind( + base::BindOnce( &UserSessionManager::CompleteProfileCreateAfterAuthTransfer, AsWeakPtr(), profile)); } @@ -1189,8 +1189,8 @@ // Call FinalizePrepareProfile directly and skip RestoreAuthSessionImpl // because there is no need to merge session for Active Directory users. base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&UserSessionManager::FinalizePrepareProfile, - AsWeakPtr(), profile)); + FROM_HERE, base::BindOnce(&UserSessionManager::FinalizePrepareProfile, + AsWeakPtr(), profile)); return; } @@ -1340,8 +1340,9 @@ base::Bind(&UserSessionManager::ChildAccountStatusReceivedCallback, weak_factory_.GetWeakPtr(), profile)); base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&UserSessionManager::StopChildStatusObserving, - weak_factory_.GetWeakPtr(), profile), + FROM_HERE, + base::BindOnce(&UserSessionManager::StopChildStatusObserving, + weak_factory_.GetWeakPtr(), profile), base::TimeDelta::FromMilliseconds(kFlagsFetchingLoginTimeoutMs)); user_manager::UserManager* user_manager = user_manager::UserManager::Get(); @@ -1660,7 +1661,7 @@ // Restart unconditionally in case if we are stuck somewhere in a session // restore process. http://crbug.com/520346. base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(RestartOnTimeout), + FROM_HERE, base::BindOnce(RestartOnTimeout), base::TimeDelta::FromSeconds(kMaxRestartDelaySeconds)); if (CheckEasyUnlockKeyOps(base::Bind(&UserSessionManager::AttemptRestart,
diff --git a/chrome/browser/chromeos/login/signin/merge_session_resource_throttle.cc b/chrome/browser/chromeos/login/signin/merge_session_resource_throttle.cc index 5483789..b64316e 100644 --- a/chrome/browser/chromeos/login/signin/merge_session_resource_throttle.cc +++ b/chrome/browser/chromeos/login/signin/merge_session_resource_throttle.cc
@@ -62,7 +62,7 @@ content::ResourceRequestInfo::ForRequest(request_); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind( + base::BindOnce( &DelayXHRLoadOnUIThread, info->GetWebContentsGetterForRequest(), request_->url(), base::Bind(&MergeSessionResourceThrottle::OnBlockingPageComplete,
diff --git a/chrome/browser/chromeos/login/signin/merge_session_xhr_request_waiter.cc b/chrome/browser/chromeos/login/signin/merge_session_xhr_request_waiter.cc index 487c3e9b..11a57e1 100644 --- a/chrome/browser/chromeos/login/signin/merge_session_xhr_request_waiter.cc +++ b/chrome/browser/chromeos/login/signin/merge_session_xhr_request_waiter.cc
@@ -47,8 +47,8 @@ manager->AddObserver(this); BrowserThread::PostDelayedTask( BrowserThread::UI, FROM_HERE, - base::Bind(&MergeSessionXHRRequestWaiter::OnTimeout, - weak_ptr_factory_.GetWeakPtr()), + base::BindOnce(&MergeSessionXHRRequestWaiter::OnTimeout, + weak_ptr_factory_.GetWeakPtr()), base::TimeDelta::FromMilliseconds(kMaxRequestWaitTimeMS)); } else { NotifyBlockingDone();
diff --git a/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc b/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc index 0364a12c..01aeea74 100644 --- a/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc +++ b/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc
@@ -151,7 +151,7 @@ base::WaitableEvent::InitialState::NOT_SIGNALED)) { content::BrowserThread::PostTask( identifier, FROM_HERE, - base::Bind(&BlockThreadOnThread, base::Owned(unblock_event_))); + base::BindOnce(&BlockThreadOnThread, base::Owned(unblock_event_))); } ~BrowserThreadBlocker() { unblock_event_->Signal(); } @@ -408,8 +408,7 @@ context_ = profile->GetRequestContext(); content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::Bind(&CookieReader::ReadCookiesOnIOThread, - this)); + base::BindOnce(&CookieReader::ReadCookiesOnIOThread, this)); runner_ = new content::MessageLoopRunner; runner_->Run(); } @@ -441,8 +440,7 @@ cookie_list_ = cookies; content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&CookieReader::OnCookiesReadyOnUIThread, - this)); + base::BindOnce(&CookieReader::OnCookiesReadyOnUIThread, this)); } void OnCookiesReadyOnUIThread() { @@ -647,8 +645,8 @@ start_event_.Signal(); content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&FakeGoogle::QuitRunnerOnUIThread, - base::Unretained(this))); + base::BindOnce(&FakeGoogle::QuitRunnerOnUIThread, + base::Unretained(this))); http_response->set_code(net::HTTP_OK); http_response->set_content_type("text/html"); @@ -721,8 +719,8 @@ start_event_.Signal(); content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&DelayedFakeGaia::QuitRunnerOnUIThread, - base::Unretained(this))); + base::BindOnce(&DelayedFakeGaia::QuitRunnerOnUIThread, + base::Unretained(this))); blocking_event_.Wait(); FakeGaia::HandleMergeSession(request, http_response); }
diff --git a/chrome/browser/chromeos/login/signin/oauth2_token_fetcher.cc b/chrome/browser/chromeos/login/signin/oauth2_token_fetcher.cc index c2ff8b39..7b9e179 100644 --- a/chrome/browser/chromeos/login/signin/oauth2_token_fetcher.cc +++ b/chrome/browser/chromeos/login/signin/oauth2_token_fetcher.cc
@@ -53,12 +53,9 @@ // If network is offline, defer the token fetching until online. VLOG(1) << "Network is offline. Deferring OAuth2 token fetch."; BrowserThread::PostDelayedTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&OAuth2TokenFetcher::StartExchangeFromCookies, - AsWeakPtr(), - session_index, - signin_scoped_device_id), + BrowserThread::UI, FROM_HERE, + base::BindOnce(&OAuth2TokenFetcher::StartExchangeFromCookies, + AsWeakPtr(), session_index, signin_scoped_device_id), base::TimeDelta::FromMilliseconds(kRequestRestartDelay)); return; }
diff --git a/chrome/browser/chromeos/login/supervised/supervised_user_authenticator.cc b/chrome/browser/chromeos/login/supervised/supervised_user_authenticator.cc index bca16cf0..94ca08b 100644 --- a/chrome/browser/chromeos/login/supervised/supervised_user_authenticator.cc +++ b/chrome/browser/chromeos/login/supervised/supervised_user_authenticator.cc
@@ -190,43 +190,35 @@ // the user in because their data is horked. So, override with // the appropriate failure. BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&SupervisedUserAuthenticator::OnAuthenticationFailure, - this, - state)); + BrowserThread::UI, FROM_HERE, + base::BindOnce(&SupervisedUserAuthenticator::OnAuthenticationFailure, + this, state)); break; case NO_MOUNT: // In this case, whether login succeeded or not, we can't log // the user in because no data exist. So, override with // the appropriate failure. BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&SupervisedUserAuthenticator::OnAuthenticationFailure, - this, - state)); + BrowserThread::UI, FROM_HERE, + base::BindOnce(&SupervisedUserAuthenticator::OnAuthenticationFailure, + this, state)); break; case FAILED_TPM: // In this case, we tried to create/mount cryptohome and failed // because of the critical TPM error. // Chrome will notify user and request reboot. BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&SupervisedUserAuthenticator::OnAuthenticationFailure, - this, - state)); + BrowserThread::UI, FROM_HERE, + base::BindOnce(&SupervisedUserAuthenticator::OnAuthenticationFailure, + this, state)); break; case SUCCESS: VLOG(2) << "Supervised user login"; BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&SupervisedUserAuthenticator::OnAuthenticationSuccess, - this, - current_state_->hash(), - current_state_->add_key)); + BrowserThread::UI, FROM_HERE, + base::BindOnce(&SupervisedUserAuthenticator::OnAuthenticationSuccess, + this, current_state_->hash(), + current_state_->add_key)); break; default: NOTREACHED();
diff --git a/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc b/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc index b3bffd4..b2b0dc7 100644 --- a/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc +++ b/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc
@@ -410,9 +410,9 @@ case SupervisedUserCreationController::CRYPTOHOME_NO_MOUNT: case SupervisedUserCreationController::CRYPTOHOME_FAILED_MOUNT: case SupervisedUserCreationController::CRYPTOHOME_FAILED_TPM: - ::login::GetSecureModuleUsed( - base::Bind(&SupervisedUserCreationScreen::UpdateSecureModuleMessages, - weak_factory_.GetWeakPtr())); + ::login::GetSecureModuleUsed(base::BindOnce( + &SupervisedUserCreationScreen::UpdateSecureModuleMessages, + weak_factory_.GetWeakPtr())); return; case SupervisedUserCreationController::CLOUD_SERVER_ERROR: case SupervisedUserCreationController::TOKEN_WRITE_FAILED:
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.cc b/chrome/browser/chromeos/login/test/oobe_base_test.cc index c7eed6d5..8139b03 100644 --- a/chrome/browser/chromeos/login/test/oobe_base_test.cc +++ b/chrome/browser/chromeos/login/test/oobe_base_test.cc
@@ -128,7 +128,7 @@ // If the login display is still showing, exit gracefully. if (LoginDisplayHost::default_host()) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&chrome::AttemptExit)); + FROM_HERE, base::BindOnce(&chrome::AttemptExit)); content::RunMessageLoop(); } EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_impl.cc b/chrome/browser/chromeos/login/ui/login_display_host_impl.cc index bd4afc4a..97eb2c7c 100644 --- a/chrome/browser/chromeos/login/ui/login_display_host_impl.cc +++ b/chrome/browser/chromeos/login/ui/login_display_host_impl.cc
@@ -1248,7 +1248,7 @@ } base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&EnableSystemSoundsForAccessibility), + FROM_HERE, base::BindOnce(&EnableSystemSoundsForAccessibility), media::SoundsManager::Get()->GetDuration(SOUND_STARTUP)); }
diff --git a/chrome/browser/chromeos/login/ui/login_feedback.cc b/chrome/browser/chromeos/login/ui/login_feedback.cc index 3906002..5b5174f 100644 --- a/chrome/browser/chromeos/login/ui/login_feedback.cc +++ b/chrome/browser/chromeos/login/ui/login_feedback.cc
@@ -259,7 +259,8 @@ // Make sure there is a feedback app window opened. base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, - base::Bind(&LoginFeedback::EnsureFeedbackUI, weak_factory_.GetWeakPtr()), + base::BindOnce(&LoginFeedback::EnsureFeedbackUI, + weak_factory_.GetWeakPtr()), base::TimeDelta::FromSeconds(1)); }
diff --git a/chrome/browser/chromeos/login/ui/user_adding_screen.cc b/chrome/browser/chromeos/login/ui/user_adding_screen.cc index d70983e..0e07736f 100644 --- a/chrome/browser/chromeos/login/ui/user_adding_screen.cc +++ b/chrome/browser/chromeos/login/ui/user_adding_screen.cc
@@ -50,9 +50,8 @@ CHECK(!IsRunning()); gfx::Rect screen_bounds(chromeos::CalculateScreenBounds(gfx::Size())); display_host_ = new chromeos::LoginDisplayHostImpl(screen_bounds); - display_host_->StartUserAdding( - base::Bind(&UserAddingScreenImpl::OnDisplayHostCompletion, - base::Unretained(this))); + display_host_->StartUserAdding(base::BindOnce( + &UserAddingScreenImpl::OnDisplayHostCompletion, base::Unretained(this))); session_manager::SessionManager::Get()->SetSessionState( session_manager::SessionState::LOGIN_SECONDARY);
diff --git a/chrome/browser/chromeos/login/user_flow.cc b/chrome/browser/chromeos/login/user_flow.cc index 7507a6b..2c3325a2 100644 --- a/chrome/browser/chromeos/login/user_flow.cc +++ b/chrome/browser/chromeos/login/user_flow.cc
@@ -103,8 +103,8 @@ void ExtendedUserFlow::UnregisterFlowSoon() { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::Bind(&ChromeUserManager::ResetUserFlow, - base::Unretained(ChromeUserManager::Get()), account_id())); + base::BindOnce(&ChromeUserManager::ResetUserFlow, + base::Unretained(ChromeUserManager::Get()), account_id())); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/users/avatar/user_image_loader.cc b/chrome/browser/chromeos/login/users/avatar/user_image_loader.cc index 6d2890b..e4516a9 100644 --- a/chrome/browser/chromeos/login/users/avatar/user_image_loader.cc +++ b/chrome/browser/chromeos/login/users/avatar/user_image_loader.cc
@@ -220,8 +220,9 @@ if (!data_is_ready) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::Bind(image_info.loaded_cb, base::Passed(base::WrapUnique( - new user_manager::UserImage)))); + base::BindOnce( + image_info.loaded_cb, + base::Passed(base::WrapUnique(new user_manager::UserImage)))); return; }
diff --git a/chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.cc b/chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.cc index 069bb110..394ef9e 100644 --- a/chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.cc +++ b/chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.cc
@@ -976,10 +976,8 @@ image_properties->GetString(kImagePathNodeName, &image_path); if (!image_path.empty()) { background_task_runner_->PostTask( - FROM_HERE, - base::Bind(base::IgnoreResult(&base::DeleteFile), - base::FilePath(image_path), - false)); + FROM_HERE, base::BindOnce(base::IgnoreResult(&base::DeleteFile), + base::FilePath(image_path), false)); } update->RemoveWithoutPathExpansion(user_id(), nullptr); }
diff --git a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc index b3fdb4a..3a02872 100644 --- a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc +++ b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
@@ -221,8 +221,8 @@ if (base::ThreadTaskRunnerHandle::IsSet()) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::Bind(&ChromeUserManagerImpl::RetrieveTrustedDevicePolicies, - weak_factory_.GetWeakPtr())); + base::BindOnce(&ChromeUserManagerImpl::RetrieveTrustedDevicePolicies, + weak_factory_.GetWeakPtr())); } local_accounts_subscription_ = cros_settings_->AddSettingsObserver( @@ -519,9 +519,9 @@ // in ProfileManager. It happens in case of sync profile load when // NOTIFICATION_PROFILE_CREATED is called synchronously. base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&ChromeUserManagerImpl::SwitchActiveUser, - weak_factory_.GetWeakPtr(), GetPendingUserSwitchID())); + FROM_HERE, base::BindOnce(&ChromeUserManagerImpl::SwitchActiveUser, + weak_factory_.GetWeakPtr(), + GetPendingUserSwitchID())); SetPendingUserSwitchId(EmptyAccountId()); } break; @@ -1361,7 +1361,8 @@ std::string* out_resolved_locale) const { base::PostTaskWithTraitsAndReply( FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, - base::Bind(ResolveLocale, locale, base::Unretained(out_resolved_locale)), + base::BindOnce(ResolveLocale, locale, + base::Unretained(out_resolved_locale)), on_resolved_callback); }
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc index 7b01d15..59f012b 100644 --- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc +++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc
@@ -332,11 +332,12 @@ } else if (!wallpaper_path_.empty()) { manager->task_runner_->PostTask( FROM_HERE, - base::Bind(&WallpaperManager::GetCustomWallpaperInternal, account_id_, - info_, wallpaper_path_, true /* update wallpaper */, - base::ThreadTaskRunnerHandle::Get(), - base::Passed(std::move(on_finish_)), - manager->weak_factory_.GetWeakPtr())); + base::BindOnce(&WallpaperManager::GetCustomWallpaperInternal, + account_id_, info_, wallpaper_path_, + true /* update wallpaper */, + base::ThreadTaskRunnerHandle::Get(), + base::Passed(std::move(on_finish_)), + manager->weak_factory_.GetWeakPtr())); } else if (!info_.location.empty()) { manager->LoadWallpaper(account_id_, info_, true, std::move(on_finish_)); } else { @@ -562,10 +563,9 @@ case chrome::NOTIFICATION_LOGIN_USER_CHANGED: { ClearDisposableWallpaperCache(); BrowserThread::PostDelayedTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&WallpaperManager::MoveLoggedInUserCustomWallpaper, - weak_factory_.GetWeakPtr()), + BrowserThread::UI, FROM_HERE, + base::BindOnce(&WallpaperManager::MoveLoggedInUserCustomWallpaper, + weak_factory_.GetWeakPtr()), base::TimeDelta::FromSeconds(kMoveCustomWallpaperDelaySeconds)); break; } @@ -573,8 +573,8 @@ if (!GetCommandLine()->HasSwitch(switches::kDisableBootAnimation)) { BrowserThread::PostDelayedTask( BrowserThread::UI, FROM_HERE, - base::Bind(&WallpaperManager::CacheUsersWallpapers, - weak_factory_.GetWeakPtr()), + base::BindOnce(&WallpaperManager::CacheUsersWallpapers, + weak_factory_.GetWeakPtr()), base::TimeDelta::FromMilliseconds(kCacheWallpaperDelayMs)); } else { should_cache_wallpaper_ = true; @@ -586,8 +586,8 @@ if (should_cache_wallpaper_) { BrowserThread::PostDelayedTask( BrowserThread::UI, FROM_HERE, - base::Bind(&WallpaperManager::CacheUsersWallpapers, - weak_factory_.GetWeakPtr()), + base::BindOnce(&WallpaperManager::CacheUsersWallpapers, + weak_factory_.GetWeakPtr()), base::TimeDelta::FromMilliseconds(kCacheWallpaperDelayMs)); should_cache_wallpaper_ = false; } @@ -683,10 +683,11 @@ sequence_token_, base::SequencedWorkerPool::BLOCK_SHUTDOWN); // TODO(bshe): This may break if RawImage becomes RefCountedMemory. blocking_task_runner->PostTask( - FROM_HERE, - base::Bind(&WallpaperManager::SaveCustomWallpaper, wallpaper_files_id, - base::FilePath(wallpaper_info.location), - wallpaper_info.layout, base::Passed(std::move(deep_copy)))); + FROM_HERE, base::BindOnce(&WallpaperManager::SaveCustomWallpaper, + wallpaper_files_id, + base::FilePath(wallpaper_info.location), + wallpaper_info.layout, + base::Passed(std::move(deep_copy)))); } std::string relative_path =
diff --git a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc index 9e20e63c..fdeab49 100644 --- a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc +++ b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
@@ -426,7 +426,6 @@ auto provider = base::MakeUnique<BreakingNewsSuggestionsProvider>( service, std::move(handler), base::MakeUnique<base::DefaultClock>(), base::MakeUnique<RemoteSuggestionsDatabase>(database_dir, task_runner)); - provider->Start(); service->RegisterProvider(std::move(provider)); } @@ -535,8 +534,7 @@ RegisterPrefetchingObserver(service, profile); #endif - if (base::FeatureList::IsEnabled( - ntp_snippets::kContentSuggestionsPushFeature)) { + if (base::FeatureList::IsEnabled(ntp_snippets::kBreakingNewsPushFeature)) { SubscribeForGCMPushUpdates(pref_service, service, profile); } return service;
diff --git a/chrome/browser/thumbnails/content_analysis.cc b/chrome/browser/thumbnails/content_analysis.cc deleted file mode 100644 index 70743e6..0000000 --- a/chrome/browser/thumbnails/content_analysis.cc +++ /dev/null
@@ -1,770 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/thumbnails/content_analysis.h" - -#include <stddef.h> -#include <stdint.h> - -#include <algorithm> -#include <cmath> -#include <deque> -#include <functional> -#include <limits> -#include <numeric> -#include <vector> - -#include "base/logging.h" -#include "skia/ext/convolver.h" -#include "skia/ext/recursive_gaussian_convolution.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "third_party/skia/include/core/SkSize.h" -#include "ui/gfx/color_analysis.h" - -namespace { - -const float kSigmaThresholdForRecursive = 1.5f; -const float kAspectRatioToleranceFactor = 1.02f; - -template<class InputIterator, class OutputIterator, class Compare> -void SlidingWindowMinMax(InputIterator first, - InputIterator last, - OutputIterator output, - int window_size, - Compare cmp) { - typedef std::deque< - std::pair<typename std::iterator_traits<InputIterator>::value_type, int> > - deque_type; - deque_type slider; - int front_tail_length = window_size / 2; - int i = 0; - DCHECK_LT(front_tail_length, last - first); - // This min-max filter functions the way image filters do. The min/max we - // compute is placed in the center of the window. Thus, first we need to - // 'pre-load' the window with the slider with right-tail of the filter. - for (; first < last && i < front_tail_length; ++i, ++first) - slider.push_back(std::make_pair(*first, i)); - - for (; first < last; ++i, ++first, ++output) { - while (!slider.empty() && !cmp(slider.back().first, *first)) - slider.pop_back(); - slider.push_back(std::make_pair(*first, i)); - - while (slider.front().second <= i - window_size) - slider.pop_front(); - *output = slider.front().first; - } - - // Now at the tail-end we will simply need to use whatever value is left of - // the filter to compute the remaining front_tail_length taps in the output. - - // If input shorter than window, remainder length needs to be adjusted. - front_tail_length = std::min(front_tail_length, i); - for (; front_tail_length >= 0; --front_tail_length, ++i) { - while (slider.front().second <= i - window_size) - slider.pop_front(); - *output = slider.front().first; - } -} - -size_t FindOtsuThresholdingIndex(const std::vector<int>& histogram) { - // Otsu's method seeks to maximize variance between two classes of pixels - // correspondng to valleys and peaks of the profile. - double w1 = histogram[0]; // Total weight of the first class. - double t1 = 0.5 * w1; - double w2 = 0.0; - double t2 = 0.0; - for (size_t i = 1; i < histogram.size(); ++i) { - w2 += histogram[i]; - t2 += (0.5 + i) * histogram[i]; - } - - size_t max_index = 0; - double m1 = t1 / w1; - double m2 = t2 / w2; - double max_variance_score = w1 * w2 * (m1 - m2) * (m1 - m2); - // Iterate through all possible ways of splitting the histogram. - for (size_t i = 1; i < histogram.size() - 1; i++) { - double bin_volume = (0.5 + i) * histogram[i]; - w1 += histogram[i]; - w2 -= histogram[i]; - t2 -= bin_volume; - t1 += bin_volume; - m1 = t1 / w1; - m2 = t2 / w2; - double variance_score = w1 * w2 * (m1 - m2) * (m1 - m2); - if (variance_score >= max_variance_score) { - max_variance_score = variance_score; - max_index = i; - } - } - - return max_index; -} - -bool ComputeScaledHistogram(const std::vector<float>& source, - std::vector<int>* histogram, - std::pair<float, float>* minmax) { - DCHECK(histogram); - DCHECK(minmax); - histogram->clear(); - histogram->resize(256); - float value_min = std::numeric_limits<float>::max(); - float value_max = 0.0f; - - std::vector<float>::const_iterator it; - for (it = source.begin(); it < source.end(); ++it) { - value_min = std::min(value_min, *it); - value_max = std::max(value_max, *it); - } - - *minmax = std::make_pair(value_min, value_max); - - if (value_max - value_min <= std::numeric_limits<float>::epsilon() * 100.0f) { - // Scaling won't work and there is nothing really to segment anyway. - return false; - } - - float value_span = value_max - value_min; - float scale = 255.0f / value_span; - for (it = source.begin(); it < source.end(); ++it) { - float scaled_value = (*it - value_min) * scale; - (*histogram)[static_cast<int>(scaled_value)] += 1; - } - return true; -} - -void ConstrainedProfileThresholding(const std::vector<float>& profile, - const std::vector<int>& histogram, - int current_clip_index, - float current_threshold, - const std::pair<float, float>& range, - int size_for_threshold, - int target_size, - std::vector<bool>* result) { - DCHECK(!profile.empty()); - DCHECK_EQ(histogram.size(), 256U); - DCHECK(result); - - // A subroutine performing thresholding on the |profile|. - if (size_for_threshold != target_size) { - // Find a cut-off point (on the histogram) closest to the desired size. - int candidate_size = profile.size(); - int candidate_clip_index = 0; - for (std::vector<int>::const_iterator it = histogram.begin(); - it != histogram.end(); ++it, ++candidate_clip_index) { - if (std::abs(candidate_size - target_size) < - std::abs(candidate_size - *it - target_size)) { - break; - } - candidate_size -= *it; - } - - if (std::abs(candidate_size - target_size) < - std::abs(candidate_size -size_for_threshold)) { - current_clip_index = candidate_clip_index; - current_threshold = (range.second - range.first) * - current_clip_index / 255.0f + range.first; - // Recount, rather than assume. One-offs due to rounding can be very - // harmful when eroding / dilating the result. - size_for_threshold = std::count_if(profile.begin(), profile.end(), - [current_threshold](float value) { - return value > current_threshold; - }); - } - } - - result->resize(profile.size()); - for (size_t i = 0; i < profile.size(); ++i) - (*result)[i] = profile[i] > current_threshold; - - while (size_for_threshold > target_size) { - // If the current size is larger than target size, erode exactly as needed. - std::vector<bool>::iterator mod_it = result->begin(); - std::vector<bool>::const_iterator lead_it = result->begin(); - bool prev_value = true; - for (++lead_it; - lead_it < result->end() && size_for_threshold > target_size; - ++lead_it, ++mod_it) { - bool value = *mod_it; - // If any neighbour is false, switch the element off. - if (!prev_value || !*lead_it) { - *mod_it = false; - --size_for_threshold; - } - prev_value = value; - } - - if (lead_it == result->end() && !prev_value) { - *mod_it = false; - --size_for_threshold; - } - } - - while (size_for_threshold < target_size) { - std::vector<bool>::iterator mod_it = result->begin(); - std::vector<bool>::const_iterator lead_it = result->begin(); - bool prev_value = false; - for (++lead_it; - lead_it < result->end() && size_for_threshold < target_size; - ++lead_it, ++mod_it) { - bool value = *mod_it; - // If any neighbour is false, switch the element off. - if (!prev_value || !*lead_it) { - *mod_it = true; - ++size_for_threshold; - } - prev_value = value; - } - - if (lead_it == result->end() && !prev_value) { - *mod_it = true; - ++size_for_threshold; - } - } -} - -} // namespace - -namespace thumbnailing_utils { - -void ApplyGaussianGradientMagnitudeFilter(SkBitmap* input_bitmap, - float kernel_sigma) { - // The purpose of this function is to highlight salient - // (attention-attracting?) features of the image for use in image - // retargeting. - DCHECK(input_bitmap); - DCHECK(input_bitmap->getPixels()); - DCHECK_EQ(kAlpha_8_SkColorType, input_bitmap->colorType()); - - // To perform computations we will need one intermediate buffer. It can - // very well be just another bitmap. - const SkISize image_size = SkISize::Make(input_bitmap->width(), - input_bitmap->height()); - SkBitmap intermediate; - intermediate.allocPixels(input_bitmap->info().makeWH(image_size.width(), - image_size.height())); - - SkBitmap intermediate2; - intermediate2.allocPixels(input_bitmap->info().makeWH(image_size.width(), - image_size.height())); - - if (kernel_sigma <= kSigmaThresholdForRecursive) { - // For small kernels classic implementation is faster. - skia::ConvolutionFilter1D smoothing_filter; - skia::SetUpGaussianConvolutionKernel( - &smoothing_filter, kernel_sigma, false); - skia::SingleChannelConvolveX1D( - input_bitmap->getAddr8(0, 0), - static_cast<int>(input_bitmap->rowBytes()), - 0, input_bitmap->bytesPerPixel(), - smoothing_filter, - image_size, - intermediate.getAddr8(0, 0), - static_cast<int>(intermediate.rowBytes()), - 0, intermediate.bytesPerPixel(), false); - skia::SingleChannelConvolveY1D( - intermediate.getAddr8(0, 0), - static_cast<int>(intermediate.rowBytes()), - 0, intermediate.bytesPerPixel(), - smoothing_filter, - image_size, - input_bitmap->getAddr8(0, 0), - static_cast<int>(input_bitmap->rowBytes()), - 0, input_bitmap->bytesPerPixel(), false); - - skia::ConvolutionFilter1D gradient_filter; - skia::SetUpGaussianConvolutionKernel(&gradient_filter, kernel_sigma, true); - skia::SingleChannelConvolveX1D( - input_bitmap->getAddr8(0, 0), - static_cast<int>(input_bitmap->rowBytes()), - 0, input_bitmap->bytesPerPixel(), - gradient_filter, - image_size, - intermediate.getAddr8(0, 0), - static_cast<int>(intermediate.rowBytes()), - 0, intermediate.bytesPerPixel(), true); - skia::SingleChannelConvolveY1D( - input_bitmap->getAddr8(0, 0), - static_cast<int>(input_bitmap->rowBytes()), - 0, input_bitmap->bytesPerPixel(), - gradient_filter, - image_size, - intermediate2.getAddr8(0, 0), - static_cast<int>(intermediate2.rowBytes()), - 0, intermediate2.bytesPerPixel(), true); - } else { - // For larger sigma values use the recursive filter. - skia::RecursiveFilter smoothing_filter(kernel_sigma, - skia::RecursiveFilter::FUNCTION); - skia::SingleChannelRecursiveGaussianX( - input_bitmap->getAddr8(0, 0), - static_cast<int>(input_bitmap->rowBytes()), - 0, input_bitmap->bytesPerPixel(), - smoothing_filter, - image_size, - intermediate.getAddr8(0, 0), - static_cast<int>(intermediate.rowBytes()), - 0, intermediate.bytesPerPixel(), false); - unsigned char smoothed_max = skia::SingleChannelRecursiveGaussianY( - intermediate.getAddr8(0, 0), - static_cast<int>(intermediate.rowBytes()), - 0, intermediate.bytesPerPixel(), - smoothing_filter, - image_size, - input_bitmap->getAddr8(0, 0), - static_cast<int>(input_bitmap->rowBytes()), - 0, input_bitmap->bytesPerPixel(), false); - if (smoothed_max < 127) { - int bit_shift = 8 - static_cast<int>( - std::log10(static_cast<float>(smoothed_max)) / std::log10(2.0f)); - for (int r = 0; r < image_size.height(); ++r) { - uint8_t* row = input_bitmap->getAddr8(0, r); - for (int c = 0; c < image_size.width(); ++c, ++row) { - *row <<= bit_shift; - } - } - } - - skia::RecursiveFilter gradient_filter( - kernel_sigma, skia::RecursiveFilter::FIRST_DERIVATIVE); - skia::SingleChannelRecursiveGaussianX( - input_bitmap->getAddr8(0, 0), - static_cast<int>(input_bitmap->rowBytes()), - 0, input_bitmap->bytesPerPixel(), - gradient_filter, - image_size, - intermediate.getAddr8(0, 0), - static_cast<int>(intermediate.rowBytes()), - 0, intermediate.bytesPerPixel(), true); - skia::SingleChannelRecursiveGaussianY( - input_bitmap->getAddr8(0, 0), - static_cast<int>(input_bitmap->rowBytes()), - 0, input_bitmap->bytesPerPixel(), - gradient_filter, - image_size, - intermediate2.getAddr8(0, 0), - static_cast<int>(intermediate2.rowBytes()), - 0, intermediate2.bytesPerPixel(), true); - } - - unsigned grad_max = 0; - for (int r = 0; r < image_size.height(); ++r) { - const uint8_t* grad_x_row = intermediate.getAddr8(0, r); - const uint8_t* grad_y_row = intermediate2.getAddr8(0, r); - for (int c = 0; c < image_size.width(); ++c) { - unsigned grad_x = grad_x_row[c]; - unsigned grad_y = grad_y_row[c]; - grad_max = std::max(grad_max, grad_x * grad_x + grad_y * grad_y); - } - } - - int bit_shift = 0; - if (grad_max > 255) - bit_shift = static_cast<int>( - std::log10(static_cast<float>(grad_max)) / std::log10(2.0f)) - 7; - for (int r = 0; r < image_size.height(); ++r) { - const uint8_t* grad_x_row = intermediate.getAddr8(0, r); - const uint8_t* grad_y_row = intermediate2.getAddr8(0, r); - uint8_t* target_row = input_bitmap->getAddr8(0, r); - for (int c = 0; c < image_size.width(); ++c) { - unsigned grad_x = grad_x_row[c]; - unsigned grad_y = grad_y_row[c]; - target_row[c] = (grad_x * grad_x + grad_y * grad_y) >> bit_shift; - } - } -} - -void ExtractImageProfileInformation(const SkBitmap& input_bitmap, - const gfx::Rect& area, - const gfx::Size& target_size, - bool apply_log, - std::vector<float>* rows, - std::vector<float>* columns) { - DCHECK(rows); - DCHECK(columns); - DCHECK(input_bitmap.getPixels()); - DCHECK_EQ(kAlpha_8_SkColorType, input_bitmap.colorType()); - DCHECK_GE(area.x(), 0); - DCHECK_GE(area.y(), 0); - DCHECK_LE(area.right(), input_bitmap.width()); - DCHECK_LE(area.bottom(), input_bitmap.height()); - - // Make sure rows and columns are allocated and initialized to 0. - rows->clear(); - columns->clear(); - rows->resize(area.height(), 0); - columns->resize(area.width(), 0); - - for (int r = 0; r < area.height(); ++r) { - // Points to the first byte of the row in the rectangle. - const uint8_t* image_row = input_bitmap.getAddr8(area.x(), r + area.y()); - unsigned row_sum = 0; - for (int c = 0; c < area.width(); ++c, ++image_row) { - row_sum += *image_row; - (*columns)[c] += *image_row; - } - (*rows)[r] = row_sum; - } - - if (apply_log) { - // Generally for processing we will need to take logarithm of this data. - // The option not to apply it is left principally as a test seam. - std::vector<float>::iterator it; - for (it = columns->begin(); it < columns->end(); ++it) - *it = std::log(1.0f + *it); - - for (it = rows->begin(); it < rows->end(); ++it) - *it = std::log(1.0f + *it); - } - - if (!target_size.IsEmpty()) { - // If the target size is given, profiles should be further processed through - // morphological closing. The idea is to close valleys smaller than what - // can be seen after scaling down to avoid deforming noticable features - // when profiles are used. - // Morphological closing is defined as dilation followed by errosion. In - // normal-speak: sliding-window maximum followed by minimum. - int column_window_size = 1 + 2 * - static_cast<int>(0.5f * area.width() / target_size.width() + 0.5f); - int row_window_size = 1 + 2 * - static_cast<int>(0.5f * area.height() / target_size.height() + 0.5f); - - // Dilate and erode each profile with the given window size. - if (column_window_size >= 3) { - SlidingWindowMinMax(columns->begin(), - columns->end(), - columns->begin(), - column_window_size, - std::greater<float>()); - SlidingWindowMinMax(columns->begin(), - columns->end(), - columns->begin(), - column_window_size, - std::less<float>()); - } - - if (row_window_size >= 3) { - SlidingWindowMinMax(rows->begin(), - rows->end(), - rows->begin(), - row_window_size, - std::greater<float>()); - SlidingWindowMinMax(rows->begin(), - rows->end(), - rows->begin(), - row_window_size, - std::less<float>()); - } - } -} - -float AutoSegmentPeaks(const std::vector<float>& input) { - // This is a thresholding operation based on Otsu's method. - std::vector<int> histogram; - std::pair<float, float> minmax; - if (!ComputeScaledHistogram(input, &histogram, &minmax)) - return minmax.first; - - // max_index refers to the bin *after* which we need to split. The sought - // threshold is the centre of this bin, scaled back to the original range. - size_t max_index = FindOtsuThresholdingIndex(histogram); - return (minmax.second - minmax.first) * (max_index + 0.5f) / 255.0f + - minmax.first; -} - -gfx::Size AdjustClippingSizeToAspectRatio(const gfx::Size& target_size, - const gfx::Size& image_size, - const gfx::Size& computed_size) { - DCHECK_GT(target_size.width(), 0); - DCHECK_GT(target_size.height(), 0); - // If the computed thumbnail would be too wide or to tall, we shall attempt - // to fix it. Generally the idea is to re-add content to the part which has - // been more aggressively shrunk unless there is nothing to add there or if - // adding there won't fix anything. Should that be the case, we will - // (reluctantly) take away more from the other dimension. - float desired_aspect = - static_cast<float>(target_size.width()) / target_size.height(); - int computed_width = std::max(computed_size.width(), target_size.width()); - int computed_height = std::max(computed_size.height(), target_size.height()); - float computed_aspect = static_cast<float>(computed_width) / computed_height; - float aspect_change_delta = std::abs(computed_aspect - desired_aspect); - float prev_aspect_change_delta = 1000.0f; - const float kAspectChangeEps = 0.01f; - const float kLargeEffect = 2.0f; - - while ((prev_aspect_change_delta - aspect_change_delta > kAspectChangeEps) && - (computed_aspect / desired_aspect > kAspectRatioToleranceFactor || - desired_aspect / computed_aspect > kAspectRatioToleranceFactor)) { - int new_computed_width = computed_width; - int new_computed_height = computed_height; - float row_dimension_shrink = - static_cast<float>(image_size.height()) / computed_height; - float column_dimension_shrink = - static_cast<float>(image_size.width()) / computed_width; - - if (computed_aspect / desired_aspect > kAspectRatioToleranceFactor) { - // Too wide. - if (row_dimension_shrink > column_dimension_shrink) { - // Bring the computed_height to the least of: - // (1) image height (2) the number of lines that would - // make up the desired aspect or (3) number of lines we would get - // at the same 'aggressivity' level as width or. - new_computed_height = std::min( - static_cast<int>(image_size.height()), - static_cast<int>(computed_width / desired_aspect + 0.5f)); - new_computed_height = std::min( - new_computed_height, - static_cast<int>( - image_size.height() / column_dimension_shrink + 0.5f)); - } else if (row_dimension_shrink >= kLargeEffect || - new_computed_width <= target_size.width()) { - // Even though rows were resized less, we will generally rather add than - // remove (or there is nothing to remove in x already). - new_computed_height = std::min( - static_cast<int>(image_size.height()), - static_cast<int>(computed_width / desired_aspect + 0.5f)); - } else { - // Rows were already shrunk less aggressively. This means there is - // simply no room left too expand. Cut columns to get the desired - // aspect ratio. - new_computed_width = desired_aspect * computed_height + 0.5f; - } - } else { - // Too tall. - if (column_dimension_shrink > row_dimension_shrink) { - // Columns were shrunk more aggressively. Try to relax the same way as - // above. - new_computed_width = std::min( - static_cast<int>(image_size.width()), - static_cast<int>(desired_aspect * computed_height + 0.5f)); - new_computed_width = std::min( - new_computed_width, - static_cast<int>( - image_size.width() / row_dimension_shrink + 0.5f)); - } else if (column_dimension_shrink >= kLargeEffect || - new_computed_height <= target_size.height()) { - new_computed_width = std::min( - static_cast<int>(image_size.width()), - static_cast<int>(desired_aspect * computed_height + 0.5f)); - } else { - new_computed_height = computed_width / desired_aspect + 0.5f; - } - } - - new_computed_width = std::max(new_computed_width, target_size.width()); - new_computed_height = std::max(new_computed_height, target_size.height()); - - // Update loop control variables. - float new_computed_aspect = - static_cast<float>(new_computed_width) / new_computed_height; - - if (std::abs(new_computed_aspect - desired_aspect) > - std::abs(computed_aspect - desired_aspect)) { - // Do not take inferior results. - break; - } - - computed_width = new_computed_width; - computed_height = new_computed_height; - computed_aspect = new_computed_aspect; - prev_aspect_change_delta = aspect_change_delta; - aspect_change_delta = std::abs(new_computed_aspect - desired_aspect); - } - - return gfx::Size(computed_width, computed_height); -} - -void ConstrainedProfileSegmentation(const std::vector<float>& row_profile, - const std::vector<float>& column_profile, - const gfx::Size& target_size, - std::vector<bool>* included_rows, - std::vector<bool>* included_columns) { - DCHECK(included_rows); - DCHECK(included_columns); - - std::vector<int> histogram_rows; - std::pair<float, float> minmax_rows; - bool rows_well_behaved = ComputeScaledHistogram( - row_profile, &histogram_rows, &minmax_rows); - - float row_threshold = minmax_rows.first; - size_t clip_index_rows = 0; - - if (rows_well_behaved) { - clip_index_rows = FindOtsuThresholdingIndex(histogram_rows); - row_threshold = (minmax_rows.second - minmax_rows.first) * - (clip_index_rows + 0.5f) / 255.0f + minmax_rows.first; - } - - std::vector<int> histogram_columns; - std::pair<float, float> minmax_columns; - bool columns_well_behaved = ComputeScaledHistogram(column_profile, - &histogram_columns, - &minmax_columns); - float column_threshold = minmax_columns.first; - size_t clip_index_columns = 0; - - if (columns_well_behaved) { - clip_index_columns = FindOtsuThresholdingIndex(histogram_columns); - column_threshold = (minmax_columns.second - minmax_columns.first) * - (clip_index_columns + 0.5f) / 255.0f + minmax_columns.first; - } - - int auto_segmented_width = count_if( - column_profile.begin(), column_profile.end(), - [column_threshold](float value) { return value > column_threshold; }); - int auto_segmented_height = - count_if(row_profile.begin(), row_profile.end(), - [row_threshold](float value) { return value > row_threshold; }); - - gfx::Size computed_size = AdjustClippingSizeToAspectRatio( - target_size, - gfx::Size(column_profile.size(), row_profile.size()), - gfx::Size(auto_segmented_width, auto_segmented_height)); - - // Apply thresholding. - if (rows_well_behaved) { - ConstrainedProfileThresholding(row_profile, - histogram_rows, - clip_index_rows, - row_threshold, - minmax_rows, - auto_segmented_height, - computed_size.height(), - included_rows); - } else { - // This is essentially an error condition, invoked when no segmentation was - // possible. This will result in applying a very low threshold and likely - // in producing a thumbnail which should get rejected. - included_rows->resize(row_profile.size()); - for (size_t i = 0; i < row_profile.size(); ++i) - (*included_rows)[i] = row_profile[i] > row_threshold; - } - - if (columns_well_behaved) { - ConstrainedProfileThresholding(column_profile, - histogram_columns, - clip_index_columns, - column_threshold, - minmax_columns, - auto_segmented_width, - computed_size.width(), - included_columns); - } else { - included_columns->resize(column_profile.size()); - for (size_t i = 0; i < column_profile.size(); ++i) - (*included_columns)[i] = column_profile[i] > column_threshold; - } -} - -SkBitmap ComputeDecimatedImage(const SkBitmap& bitmap, - const std::vector<bool>& rows, - const std::vector<bool>& columns) { - DCHECK(bitmap.getPixels()); - DCHECK_GT(bitmap.bytesPerPixel(), 0); - DCHECK_EQ(bitmap.width(), static_cast<int>(columns.size())); - DCHECK_EQ(bitmap.height(), static_cast<int>(rows.size())); - - unsigned target_row_count = std::count(rows.begin(), rows.end(), true); - unsigned target_column_count = std::count( - columns.begin(), columns.end(), true); - - if (target_row_count == 0 || target_column_count == 0) - return SkBitmap(); // Not quite an error, so no DCHECK. Just return empty. - - if (target_row_count == rows.size() && target_column_count == columns.size()) - return SkBitmap(); // Equivalent of the situation above (empty target). - - // Allocate the target image. - SkBitmap target; - target.allocPixels(bitmap.info().makeWH(target_column_count, - target_row_count)); - - int target_row = 0; - for (int r = 0; r < bitmap.height(); ++r) { - if (!rows[r]) - continue; // We can just skip this one. - uint8_t* src_row = - static_cast<uint8_t*>(bitmap.getPixels()) + r * bitmap.rowBytes(); - uint8_t* insertion_target = static_cast<uint8_t*>(target.getPixels()) + - target_row * target.rowBytes(); - int left_copy_pixel = -1; - for (int c = 0; c < bitmap.width(); ++c) { - if (left_copy_pixel < 0 && columns[c]) { - left_copy_pixel = c; // Next time we will start copying from here. - } else if (left_copy_pixel >= 0 && !columns[c]) { - // This closes a fragment we want to copy. We do it now. - size_t bytes_to_copy = (c - left_copy_pixel) * bitmap.bytesPerPixel(); - memcpy(insertion_target, - src_row + left_copy_pixel * bitmap.bytesPerPixel(), - bytes_to_copy); - left_copy_pixel = -1; - insertion_target += bytes_to_copy; - } - } - // We can still have the tail end to process here. - if (left_copy_pixel >= 0) { - size_t bytes_to_copy = - (bitmap.width() - left_copy_pixel) * bitmap.bytesPerPixel(); - memcpy(insertion_target, - src_row + left_copy_pixel * bitmap.bytesPerPixel(), - bytes_to_copy); - } - target_row++; - } - - return target; -} - -SkBitmap CreateRetargetedThumbnailImage( - const SkBitmap& source_bitmap, - const gfx::Size& target_size, - float kernel_sigma) { - // First thing we need for this method is to color-reduce the source_bitmap. - SkBitmap reduced_color; - reduced_color.allocPixels(SkImageInfo::MakeA8(source_bitmap.width(), - source_bitmap.height())); - - if (!color_utils::ComputePrincipalComponentImage(source_bitmap, - &reduced_color)) { - // CCIR601 luminance conversion vector. - gfx::Vector3dF transform(0.299f, 0.587f, 0.114f); - if (!color_utils::ApplyColorReduction( - source_bitmap, transform, true, &reduced_color)) { - DLOG(WARNING) << "Failed to compute luminance image from a screenshot. " - << "Cannot compute retargeted thumbnail."; - return SkBitmap(); - } - DLOG(WARNING) << "Could not compute principal color image for a thumbnail. " - << "Using luminance instead."; - } - - // Turn 'color-reduced' image into the 'energy' image. - ApplyGaussianGradientMagnitudeFilter(&reduced_color, kernel_sigma); - - // Extract vertical and horizontal projection of image features. - std::vector<float> row_profile; - std::vector<float> column_profile; - ExtractImageProfileInformation(reduced_color, - gfx::Rect(reduced_color.width(), - reduced_color.height()), - target_size, - true, - &row_profile, - &column_profile); - - std::vector<bool> included_rows, included_columns; - ConstrainedProfileSegmentation(row_profile, - column_profile, - target_size, - &included_rows, - &included_columns); - - // Use the original image and computed inclusion vectors to create a resized - // image. - return ComputeDecimatedImage(source_bitmap, included_rows, included_columns); -} - -} // namespace thumbnailing_utils
diff --git a/chrome/browser/thumbnails/content_analysis.h b/chrome/browser/thumbnails/content_analysis.h deleted file mode 100644 index f9d0029..0000000 --- a/chrome/browser/thumbnails/content_analysis.h +++ /dev/null
@@ -1,84 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_THUMBNAILS_CONTENT_ANALYSIS_H_ -#define CHROME_BROWSER_THUMBNAILS_CONTENT_ANALYSIS_H_ - -#include <vector> - -#include "third_party/skia/include/core/SkColor.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/size.h" - -class SkBitmap; - -namespace thumbnailing_utils { - -// Compute in-place gaussian gradient magnitude of |input_bitmap| with sigma -// |kernel_sigma|. |input_bitmap| is requried to be of SkBitmap::kA8_Config -// type. The routine computes first-order gaussian derivative on a -// gaussian-smoothed image. Beware, this is fairly slow since kernel size is -// 4 * kernel_sigma + 1. -void ApplyGaussianGradientMagnitudeFilter(SkBitmap* input_bitmap, - float kernel_sigma); - -// Accumulates vertical and horizontal sum of pixel values from a subsection of -// |input_bitmap| defined by |image_area|. The image is required to be of -// SkBitmap::kA8_Config type. -// If non-empty |target_size| is given, the routine will use it to process the -// profiles with closing operator sized to eliminate gaps which would be smaller -// than 1 pixel after rescaling to |target_size|. -// If |apply_log| is true, logarithm of counts are used for morhology (and -// returned). -void ExtractImageProfileInformation(const SkBitmap& input_bitmap, - const gfx::Rect& image_area, - const gfx::Size& target_size, - bool apply_log, - std::vector<float>* rows, - std::vector<float>* columns); - -// Compute a threshold value separating background (low) from signal (high) -// areas in the |input| profile. -float AutoSegmentPeaks(const std::vector<float>& input); - -// Compute and return a workable (not too distorted, not bigger than the image) -// target size for retargeting in ConstrainedProfileSegmentation. |target_size| -// is the desired image size (defines aspect ratio and minimal image size) while -// |computed_size| is the size of a result of unconstrained segmentation. -// This routine makes very little sense outside ConstrainedProfileSegmentation -// and is exposed only for unit tests (it is somehow complicated). -gfx::Size AdjustClippingSizeToAspectRatio(const gfx::Size& target_size, - const gfx::Size& image_size, - const gfx::Size& computed_size); - -// Compute thresholding guides |included_rows| and |included_columns| by -// segmenting 1-d profiles |row_profile| and |column_profile|. The routine will -// attempt to keep the image which would result from using these guides as close -// to the desired aspect ratio (given by |target_size|) as reasonable. -void ConstrainedProfileSegmentation(const std::vector<float>& row_profile, - const std::vector<float>& column_profile, - const gfx::Size& target_size, - std::vector<bool>* included_rows, - std::vector<bool>* included_columns); - -// Shrinks the source |bitmap| by removing rows and columns where |rows| and -// |columns| are false, respectively. The function returns a new bitmap if the -// shrinking can be performed and an empty instance otherwise. -SkBitmap ComputeDecimatedImage(const SkBitmap& bitmap, - const std::vector<bool>& rows, - const std::vector<bool>& columns); - -// Creates a new bitmap which contains only 'interesting' areas of -// |source_bitmap|. The |target_size| is used to estimate some computation -// parameters, but the resulting bitmap will not necessarily be of that size. -// |kernel_sigma| defines the degree of image smoothing in gradient computation. -// For a natural-sized (not shrunk) screenshot at 96 DPI and regular font size -// 5.0 was determined to be a good value. -SkBitmap CreateRetargetedThumbnailImage(const SkBitmap& source_bitmap, - const gfx::Size& target_size, - float kernel_sigma); - -} // namespace thumbnailing_utils - -#endif // CHROME_BROWSER_THUMBNAILS_CONTENT_ANALYSIS_H_
diff --git a/chrome/browser/thumbnails/content_analysis_unittest.cc b/chrome/browser/thumbnails/content_analysis_unittest.cc deleted file mode 100644 index 387da01e..0000000 --- a/chrome/browser/thumbnails/content_analysis_unittest.cc +++ /dev/null
@@ -1,687 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/thumbnails/content_analysis.h" - -#include <stddef.h> -#include <stdint.h> - -#include <algorithm> -#include <cmath> -#include <cstdlib> -#include <functional> -#include <limits> -#include <memory> -#include <numeric> -#include <vector> - -#include "skia/ext/platform_canvas.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/color_analysis.h" -#include "ui/gfx/color_utils.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/rect_f.h" -#include "ui/gfx/geometry/size.h" -#include "ui/gfx/image/image.h" - -namespace { - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -unsigned long ImagePixelSum(const SkBitmap& bitmap, const gfx::Rect& rect) { - // Get the sum of pixel values in the rectangle. Applicable only to - // monochrome bitmaps. - DCHECK_EQ(kAlpha_8_SkColorType, bitmap.colorType()); - unsigned long total = 0; - for (int r = rect.y(); r < rect.bottom(); ++r) { - const uint8_t* row_data = - static_cast<const uint8_t*>(bitmap.getPixels()) + r * bitmap.rowBytes(); - for (int c = rect.x(); c < rect.right(); ++c) - total += row_data[c]; - } - - return total; -} - -bool CompareImageFragments(const SkBitmap& bitmap_left, - const SkBitmap& bitmap_right, - const gfx::Size& comparison_area, - const gfx::Point& origin_left, - const gfx::Point& origin_right) { - for (int r = 0; r < comparison_area.height(); ++r) { - for (int c = 0; c < comparison_area.width(); ++c) { - SkColor color_left = bitmap_left.getColor(origin_left.x() + c, - origin_left.y() + r); - SkColor color_right = bitmap_right.getColor(origin_right.x() + c, - origin_right.y() + r); - if (color_left != color_right) - return false; - } - } - - return true; -} - -float AspectDifference(const gfx::Size& reference, const gfx::Size& candidate) { - return std::abs(static_cast<float>(candidate.width()) / candidate.height() - - static_cast<float>(reference.width()) / reference.height()); -} - -} // namespace - -namespace thumbnailing_utils { - -class ThumbnailContentAnalysisTest : public testing::Test { -}; - -TEST_F(ThumbnailContentAnalysisTest, ApplyGradientMagnitudeOnImpulse) { - gfx::Canvas canvas(gfx::Size(800, 600), 1.0f, true); - - // The image consists of a point spike on uniform (non-zero) background. - canvas.FillRect(gfx::Rect(0, 0, 800, 600), SkColorSetRGB(10, 10, 10)); - canvas.FillRect(gfx::Rect(400, 300, 1, 1), SkColorSetRGB(255, 255, 255)); - - SkBitmap source = canvas.GetBitmap(); - - SkBitmap reduced_color; - reduced_color.allocPixels(SkImageInfo::MakeA8(source.width(), - source.height())); - - gfx::Vector3dF transform(0.299f, 0.587f, 0.114f); - EXPECT_TRUE(color_utils::ApplyColorReduction( - source, transform, true, &reduced_color)); - - float sigma = 2.5f; - ApplyGaussianGradientMagnitudeFilter(&reduced_color, sigma); - - // Expect everything to be within 8 * sigma. - int tail_length = static_cast<int>(8.0f * sigma + 0.5f); - gfx::Rect echo_rect(399 - tail_length, 299 - tail_length, - 2 * tail_length + 1, 2 * tail_length + 1); - unsigned long data_sum = ImagePixelSum(reduced_color, echo_rect); - unsigned long all_sum = ImagePixelSum(reduced_color, gfx::Rect(800, 600)); - EXPECT_GT(data_sum, 0U); - EXPECT_EQ(data_sum, all_sum); - - sigma = 5.0f; - ApplyGaussianGradientMagnitudeFilter(&reduced_color, sigma); - - // Expect everything to be within 8 * sigma. - tail_length = static_cast<int>(8.0f * sigma + 0.5f); - echo_rect = gfx::Rect(399 - tail_length, 299 - tail_length, - 2 * tail_length + 1, 2 * tail_length + 1); - data_sum = ImagePixelSum(reduced_color, echo_rect); - all_sum = ImagePixelSum(reduced_color, gfx::Rect(800, 600)); - EXPECT_GT(data_sum, 0U); - EXPECT_EQ(data_sum, all_sum); -} - -TEST_F(ThumbnailContentAnalysisTest, ApplyGradientMagnitudeOnFrame) { - gfx::Canvas canvas(gfx::Size(800, 600), 1.0f, true); - - // The image consists of a single white block in the centre. - gfx::RectF draw_rect(300, 200, 200, 200); - canvas.FillRect(gfx::Rect(0, 0, 800, 600), SkColorSetRGB(0, 0, 0)); - canvas.DrawRect(draw_rect, SkColorSetRGB(255, 255, 255)); - - SkBitmap source = canvas.GetBitmap(); - - SkBitmap reduced_color; - reduced_color.allocPixels(SkImageInfo::MakeA8(source.width(), - source.height())); - - gfx::Vector3dF transform(0.299f, 0.587f, 0.114f); - EXPECT_TRUE(color_utils::ApplyColorReduction( - source, transform, true, &reduced_color)); - - float sigma = 2.5f; - ApplyGaussianGradientMagnitudeFilter(&reduced_color, sigma); - - int tail_length = static_cast<int>(8.0f * sigma + 0.5f); - gfx::Rect outer_rect(draw_rect.x() - tail_length, - draw_rect.y() - tail_length, - draw_rect.width() + 2 * tail_length, - draw_rect.height() + 2 * tail_length); - gfx::Rect inner_rect(draw_rect.x() + tail_length, - draw_rect.y() + tail_length, - draw_rect.width() - 2 * tail_length, - draw_rect.height() - 2 * tail_length); - unsigned long data_sum = ImagePixelSum(reduced_color, outer_rect); - unsigned long all_sum = ImagePixelSum(reduced_color, gfx::Rect(800, 600)); - EXPECT_GT(data_sum, 0U); - EXPECT_EQ(data_sum, all_sum); - EXPECT_EQ(ImagePixelSum(reduced_color, inner_rect), 0U); -} - -TEST_F(ThumbnailContentAnalysisTest, ExtractImageProfileInformation) { - gfx::Canvas canvas(gfx::Size(800, 600), 1.0f, true); - - // The image consists of a white frame drawn in the centre. - gfx::RectF draw_rect(100, 100, 200, 100); - gfx::Rect image_rect(0, 0, 800, 600); - canvas.FillRect(image_rect, SkColorSetRGB(0, 0, 0)); - canvas.DrawRect(draw_rect, SkColorSetRGB(255, 255, 255)); - - SkBitmap source = canvas.GetBitmap(); - SkBitmap reduced_color; - reduced_color.allocPixels(SkImageInfo::MakeA8(source.width(), - source.height())); - - gfx::Vector3dF transform(1, 0, 0); - EXPECT_TRUE(color_utils::ApplyColorReduction( - source, transform, true, &reduced_color)); - std::vector<float> column_profile; - std::vector<float> row_profile; - ExtractImageProfileInformation(reduced_color, - image_rect, - gfx::Size(), - false, - &row_profile, - &column_profile); - EXPECT_EQ(0, std::accumulate(column_profile.begin(), - column_profile.begin() + draw_rect.x() - 1, - 0)); - EXPECT_EQ(column_profile[draw_rect.x()], 255U * (draw_rect.height() + 1)); - EXPECT_EQ(2 * 255 * (draw_rect.width() - 2), - std::accumulate(column_profile.begin() + draw_rect.x() + 1, - column_profile.begin() + draw_rect.right() - 1, - 0)); - - EXPECT_EQ(0, std::accumulate(row_profile.begin(), - row_profile.begin() + draw_rect.y() - 1, - 0)); - EXPECT_EQ(row_profile[draw_rect.y()], 255U * (draw_rect.width() + 1)); - EXPECT_EQ(2 * 255 * (draw_rect.height() - 2), - std::accumulate(row_profile.begin() + draw_rect.y() + 1, - row_profile.begin() + draw_rect.bottom() - 1, - 0)); - - gfx::Rect test_rect(150, 80, 400, 100); - ExtractImageProfileInformation(reduced_color, - test_rect, - gfx::Size(), - false, - &row_profile, - &column_profile); - - // Some overlap with the drawn rectagle. If you work it out on a piece of - // paper, sums should be as follows. - EXPECT_EQ(255 * (test_rect.bottom() - draw_rect.y()) + - 255 * (draw_rect.right() - test_rect.x()), - std::accumulate(row_profile.begin(), row_profile.end(), 0)); - EXPECT_EQ(255 * (test_rect.bottom() - draw_rect.y()) + - 255 * (draw_rect.right() - test_rect.x()), - std::accumulate(column_profile.begin(), column_profile.end(), 0)); -} - -TEST_F(ThumbnailContentAnalysisTest, - ExtractImageProfileInformationWithClosing) { - gfx::Canvas canvas(gfx::Size(800, 600), 1.0f, true); - - // The image consists of a two white frames drawn side by side, with a - // single-pixel vertical gap in between. - gfx::Rect image_rect(0, 0, 800, 600); - canvas.FillRect(image_rect, SkColorSetRGB(0, 0, 0)); - canvas.DrawRect(gfx::RectF(300, 250, 99, 100), SkColorSetRGB(255, 255, 255)); - canvas.DrawRect(gfx::RectF(401, 250, 99, 100), SkColorSetRGB(255, 255, 255)); - - SkBitmap source = canvas.GetBitmap(); - SkBitmap reduced_color; - reduced_color.allocPixels(SkImageInfo::MakeA8(source.width(), - source.height())); - - gfx::Vector3dF transform(1, 0, 0); - EXPECT_TRUE(color_utils::ApplyColorReduction( - source, transform, true, &reduced_color)); - std::vector<float> column_profile; - std::vector<float> row_profile; - - ExtractImageProfileInformation(reduced_color, - image_rect, - gfx::Size(), - true, - &row_profile, - &column_profile); - // Column profiles should have two spikes in the middle, with a single - // 0-valued value between them. - EXPECT_GT(column_profile[398], 0.0f); - EXPECT_GT(column_profile[399], column_profile[398]); - EXPECT_GT(column_profile[402], 0.0f); - EXPECT_GT(column_profile[401], column_profile[402]); - EXPECT_EQ(column_profile[401], column_profile[399]); - EXPECT_EQ(column_profile[402], column_profile[398]); - EXPECT_EQ(column_profile[400], 0.0f); - EXPECT_EQ(column_profile[299], 0.0f); - EXPECT_EQ(column_profile[502], 0.0f); - - // Now the same with closing applied. The space in the middle will be closed. - ExtractImageProfileInformation(reduced_color, - image_rect, - gfx::Size(200, 100), - true, - &row_profile, - &column_profile); - EXPECT_GT(column_profile[398], 0); - EXPECT_GT(column_profile[400], 0); - EXPECT_GT(column_profile[402], 0); - EXPECT_EQ(column_profile[299], 0); - EXPECT_EQ(column_profile[502], 0); - EXPECT_EQ(column_profile[399], column_profile[401]); - EXPECT_EQ(column_profile[398], column_profile[402]); -} - -TEST_F(ThumbnailContentAnalysisTest, AdjustClippingSizeToAspectRatio) { - // The test will exercise several relations of sizes. Basic invariants - // checked in each case: each dimension in adjusted_size ougth not be greater - // than the source image and not lesser than requested target. Aspect ratio - // of adjusted_size should never be worse than that of computed_size. - gfx::Size target_size(212, 100); - gfx::Size image_size(1000, 2000); - gfx::Size computed_size(420, 200); - - gfx::Size adjusted_size = AdjustClippingSizeToAspectRatio( - target_size, image_size, computed_size); - - EXPECT_LE(adjusted_size.width(), image_size.width()); - EXPECT_LE(adjusted_size.height(), image_size.height()); - EXPECT_GE(adjusted_size.width(), target_size.width()); - EXPECT_GE(adjusted_size.height(), target_size.height()); - EXPECT_LE(AspectDifference(target_size, adjusted_size), - AspectDifference(target_size, computed_size)); - // This case is special (and trivial): no change expected. - EXPECT_EQ(computed_size, adjusted_size); - - // Computed size is too tall. Adjusted size has to add rows. - computed_size.SetSize(600, 150); - adjusted_size = AdjustClippingSizeToAspectRatio( - target_size, image_size, computed_size); - // Invariant check. - EXPECT_LE(adjusted_size.width(), image_size.width()); - EXPECT_LE(adjusted_size.height(), image_size.height()); - EXPECT_GE(adjusted_size.width(), target_size.width()); - EXPECT_GE(adjusted_size.height(), target_size.height()); - EXPECT_LE(AspectDifference(target_size, adjusted_size), - AspectDifference(target_size, computed_size)); - // Specific to this case. - EXPECT_EQ(computed_size.width(), adjusted_size.width()); - EXPECT_LE(computed_size.height(), adjusted_size.height()); - EXPECT_NEAR( - static_cast<float>(target_size.width()) / target_size.height(), - static_cast<float>(adjusted_size.width()) / adjusted_size.height(), - 0.02f); - - // Computed size is too wide. Adjusted size has to add columns. - computed_size.SetSize(200, 400); - adjusted_size = AdjustClippingSizeToAspectRatio( - target_size, image_size, computed_size); - // Invariant check. - EXPECT_LE(adjusted_size.width(), image_size.width()); - EXPECT_LE(adjusted_size.height(), image_size.height()); - EXPECT_GE(adjusted_size.width(), target_size.width()); - EXPECT_GE(adjusted_size.height(), target_size.height()); - EXPECT_LE(AspectDifference(target_size, adjusted_size), - AspectDifference(target_size, computed_size)); - EXPECT_NEAR( - static_cast<float>(target_size.width()) / target_size.height(), - static_cast<float>(adjusted_size.width()) / adjusted_size.height(), - 0.02f); - - target_size.SetSize(416, 205); - image_size.SetSize(1200, 1200); - computed_size.SetSize(900, 300); - adjusted_size = AdjustClippingSizeToAspectRatio( - target_size, image_size, computed_size); - // Invariant check. - EXPECT_LE(adjusted_size.width(), image_size.width()); - EXPECT_LE(adjusted_size.height(), image_size.height()); - EXPECT_GE(adjusted_size.width(), target_size.width()); - EXPECT_GE(adjusted_size.height(), target_size.height()); - EXPECT_LE(AspectDifference(target_size, adjusted_size), - AspectDifference(target_size, computed_size)); - // Specific to this case. - EXPECT_EQ(computed_size.width(), adjusted_size.width()); - EXPECT_LE(computed_size.height(), adjusted_size.height()); - EXPECT_NEAR( - static_cast<float>(target_size.width()) / target_size.height(), - static_cast<float>(adjusted_size.width()) / adjusted_size.height(), - 0.02f); - - target_size.SetSize(416, 205); - image_size.SetSize(1200, 1200); - computed_size.SetSize(300, 300); - adjusted_size = AdjustClippingSizeToAspectRatio( - target_size, image_size, computed_size); - // Invariant check. - EXPECT_LE(adjusted_size.width(), image_size.width()); - EXPECT_LE(adjusted_size.height(), image_size.height()); - EXPECT_GE(adjusted_size.width(), target_size.width()); - EXPECT_GE(adjusted_size.height(), target_size.height()); - EXPECT_LE(AspectDifference(target_size, adjusted_size), - AspectDifference(target_size, computed_size)); - // Specific to this case. - EXPECT_EQ(computed_size.height(), adjusted_size.height()); - EXPECT_LE(computed_size.width(), adjusted_size.width()); - EXPECT_NEAR( - static_cast<float>(target_size.width()) / target_size.height(), - static_cast<float>(adjusted_size.width()) / adjusted_size.height(), - 0.02f); - - computed_size.SetSize(200, 300); - adjusted_size = AdjustClippingSizeToAspectRatio( - target_size, image_size, computed_size); - // Invariant check. - EXPECT_LE(adjusted_size.width(), image_size.width()); - EXPECT_LE(adjusted_size.height(), image_size.height()); - EXPECT_GE(adjusted_size.width(), target_size.width()); - EXPECT_GE(adjusted_size.height(), target_size.height()); - EXPECT_LE(AspectDifference(target_size, adjusted_size), - AspectDifference(target_size, computed_size)); - // Specific to this case. - EXPECT_EQ(computed_size.height(), adjusted_size.height()); - EXPECT_LE(computed_size.width(), adjusted_size.width()); - EXPECT_NEAR( - static_cast<float>(target_size.width()) / target_size.height(), - static_cast<float>(adjusted_size.width()) / adjusted_size.height(), - 0.02f); - - target_size.SetSize(416, 205); - image_size.SetSize(1400, 600); - computed_size.SetSize(300, 300); - adjusted_size = AdjustClippingSizeToAspectRatio( - target_size, image_size, computed_size); - // Invariant check. - EXPECT_LE(adjusted_size.width(), image_size.width()); - EXPECT_LE(adjusted_size.height(), image_size.height()); - EXPECT_GE(adjusted_size.width(), target_size.width()); - EXPECT_GE(adjusted_size.height(), target_size.height()); - EXPECT_LE(AspectDifference(target_size, adjusted_size), - AspectDifference(target_size, computed_size)); - // Specific to this case. - EXPECT_EQ(computed_size.height(), adjusted_size.height()); - EXPECT_LE(computed_size.width(), adjusted_size.width()); - EXPECT_NEAR( - static_cast<float>(target_size.width()) / target_size.height(), - static_cast<float>(adjusted_size.width()) / adjusted_size.height(), - 0.02f); - - computed_size.SetSize(900, 300); - adjusted_size = AdjustClippingSizeToAspectRatio( - target_size, image_size, computed_size); - // Invariant check. - EXPECT_LE(adjusted_size.width(), image_size.width()); - EXPECT_LE(adjusted_size.height(), image_size.height()); - EXPECT_GE(adjusted_size.width(), target_size.width()); - EXPECT_GE(adjusted_size.height(), target_size.height()); - EXPECT_LE(AspectDifference(target_size, adjusted_size), - AspectDifference(target_size, computed_size)); - // Specific to this case. - EXPECT_LE(computed_size.height(), adjusted_size.height()); - EXPECT_NEAR( - static_cast<float>(target_size.width()) / target_size.height(), - static_cast<float>(adjusted_size.width()) / adjusted_size.height(), - 0.02f); -} - -TEST_F(ThumbnailContentAnalysisTest, AutoSegmentPeaks) { - std::vector<float> profile_info; - - EXPECT_EQ(AutoSegmentPeaks(profile_info), std::numeric_limits<float>::max()); - profile_info.resize(1000, 1.0f); - EXPECT_EQ(AutoSegmentPeaks(profile_info), 1.0f); - std::srand(42); - std::generate(profile_info.begin(), profile_info.end(), std::rand); - float threshold = AutoSegmentPeaks(profile_info); - EXPECT_GT(threshold, 0); // Not much to expect. - - // There should be roughly 50% above and below the threshold. - // Random is not really random thanks to srand, so we can sort-of compare. - int above_count = - std::count_if(profile_info.begin(), profile_info.end(), - [threshold](float value) { return value > threshold; }); - EXPECT_GT(above_count, 450); // Not much to expect. - EXPECT_LT(above_count, 550); - - for (unsigned i = 0; i < profile_info.size(); ++i) { - float y = std::sin(M_PI * i / 250.0f); - profile_info[i] = y > 0 ? y : 0; - } - threshold = AutoSegmentPeaks(profile_info); - - above_count = - std::count_if(profile_info.begin(), profile_info.end(), - [threshold](float value) { return value > threshold; }); - EXPECT_LT(above_count, 500); // Negative y expected to fall below threshold. - - // Expect two peaks around between 0 and 250 and 500 and 750. - std::vector<bool> thresholded_values(profile_info.size(), false); - std::transform(profile_info.begin(), profile_info.end(), - thresholded_values.begin(), - [threshold](float value) { return value > threshold; }); - EXPECT_TRUE(thresholded_values[125]); - EXPECT_TRUE(thresholded_values[625]); - int transitions = 0; - for (unsigned i = 1; i < thresholded_values.size(); ++i) { - if (thresholded_values[i] != thresholded_values[i-1]) - transitions++; - } - EXPECT_EQ(transitions, 4); // We have two contiguous peaks. Good going! -} - -TEST_F(ThumbnailContentAnalysisTest, ConstrainedProfileSegmentation) { - const size_t kRowCount = 800; - const size_t kColumnCount = 1400; - const gfx::Size target_size(300, 150); - std::vector<float> rows_profile(kRowCount); - std::vector<float> columns_profile(kColumnCount); - - std::srand(42); - std::generate(rows_profile.begin(), rows_profile.end(), []() { - return std::rand() / static_cast<float>(RAND_MAX) + 1.f; - }); - std::generate(columns_profile.begin(), columns_profile.end(), []() { - return std::rand() / static_cast<float>(RAND_MAX) + 1.f; - }); - - std::transform(rows_profile.begin() + 300, - rows_profile.begin() + 450, - rows_profile.begin() + 300, - [](float value) { return value + 8.f; }); - std::transform(columns_profile.begin() + 400, - columns_profile.begin() + 1000, - columns_profile.begin() + 400, - [](float value) { return value + 10.f; }); - - // Make sure that threshold falls somewhere reasonable. - float row_threshold = AutoSegmentPeaks(rows_profile); - EXPECT_GT(row_threshold, 1.0f); - EXPECT_LT(row_threshold, 9.0f); - - int row_above_count = std::count_if( - rows_profile.begin(), - rows_profile.end(), - [row_threshold](float value) { return value > row_threshold; }); - EXPECT_EQ(row_above_count, 150); - - float column_threshold = AutoSegmentPeaks(columns_profile); - EXPECT_GT(column_threshold, 1.0f); - EXPECT_LT(column_threshold, 11.0f); - - int column_above_count = std::count_if( - columns_profile.begin(), - columns_profile.end(), - [column_threshold](float value) { return value > column_threshold; }); - EXPECT_EQ(column_above_count, 600); - - - std::vector<bool> rows_guide; - std::vector<bool> columns_guide; - ConstrainedProfileSegmentation( - rows_profile, columns_profile, target_size, &rows_guide, &columns_guide); - - int row_count = std::count(rows_guide.begin(), rows_guide.end(), true); - int column_count = std::count( - columns_guide.begin(), columns_guide.end(), true); - float expected_aspect = - static_cast<float>(target_size.width()) / target_size.height(); - float actual_aspect = static_cast<float>(column_count) / row_count; - EXPECT_GE(1.05f, expected_aspect / actual_aspect); - EXPECT_GE(1.05f, actual_aspect / expected_aspect); -} - -TEST_F(ThumbnailContentAnalysisTest, ComputeDecimatedImage) { - gfx::Size image_size(1600, 1200); - gfx::Canvas canvas(image_size, 1.0f, true); - - // Make some content we will later want to keep. - canvas.FillRect(gfx::Rect(100, 200, 100, 100), SkColorSetRGB(125, 0, 0)); - canvas.FillRect(gfx::Rect(300, 200, 100, 100), SkColorSetRGB(0, 200, 0)); - canvas.FillRect(gfx::Rect(500, 200, 100, 100), SkColorSetRGB(0, 0, 225)); - canvas.FillRect(gfx::Rect(100, 400, 600, 100), SkColorSetRGB(125, 200, 225)); - - std::vector<bool> rows(image_size.height(), false); - std::fill_n(rows.begin() + 200, 100, true); - std::fill_n(rows.begin() + 400, 100, true); - - std::vector<bool> columns(image_size.width(), false); - std::fill_n(columns.begin() + 100, 100, true); - std::fill_n(columns.begin() + 300, 100, true); - std::fill_n(columns.begin() + 500, 100, true); - - SkBitmap source = canvas.GetBitmap(); - SkBitmap result = ComputeDecimatedImage(source, rows, columns); - EXPECT_FALSE(result.empty()); - EXPECT_EQ(300, result.width()); - EXPECT_EQ(200, result.height()); - - // The call should have removed all empty spaces. - ASSERT_TRUE(CompareImageFragments(source, - result, - gfx::Size(100, 100), - gfx::Point(100, 200), - gfx::Point(0, 0))); - ASSERT_TRUE(CompareImageFragments(source, - result, - gfx::Size(100, 100), - gfx::Point(300, 200), - gfx::Point(100, 0))); - ASSERT_TRUE(CompareImageFragments(source, - result, - gfx::Size(100, 100), - gfx::Point(500, 200), - gfx::Point(200, 0))); - ASSERT_TRUE(CompareImageFragments(source, - result, - gfx::Size(100, 100), - gfx::Point(100, 400), - gfx::Point(0, 100))); -} - -TEST_F(ThumbnailContentAnalysisTest, CreateRetargetedThumbnailImage) { - gfx::Size image_size(1200, 1300); - gfx::Canvas canvas(image_size, 1.0f, true); - - // The following will create a 'fake image' consisting of color blocks placed - // on a neutral background. The entire layout is supposed to mimic a - // screenshot of a web page. - // The tested function is supposed to locate the interesing areas in the - // middle. - const int margin_horizontal = 60; - const int margin_vertical = 20; - canvas.FillRect(gfx::Rect(image_size), SkColorSetRGB(200, 210, 210)); - const gfx::Rect header_rect(margin_horizontal, - margin_vertical, - image_size.width() - 2 * margin_horizontal, - 100); - const gfx::Rect footer_rect(margin_horizontal, - image_size.height() - margin_vertical - 100, - image_size.width() - 2 * margin_horizontal, - 100); - const gfx::Rect body_rect(margin_horizontal, - header_rect.bottom() + margin_vertical, - image_size.width() - 2 * margin_horizontal, - footer_rect.y() - header_rect.bottom() - - 2 * margin_vertical); - canvas.FillRect(header_rect, SkColorSetRGB(200, 40, 10)); - canvas.FillRect(footer_rect, SkColorSetRGB(10, 40, 180)); - canvas.FillRect(body_rect, SkColorSetRGB(150, 180, 40)); - - // 'Fine print' at the bottom. - const int fine_print = 8; - const SkColor print_color = SkColorSetRGB(45, 30, 30); - for (int y = footer_rect.y() + fine_print; - y < footer_rect.bottom() - fine_print; - y += 2 * fine_print) { - for (int x = footer_rect.x() + fine_print; - x < footer_rect.right() - fine_print; - x += 2 * fine_print) { - canvas.DrawRect(gfx::RectF(x, y, fine_print, fine_print), print_color); - } - } - - // Blocky content at the top. - const int block_size = header_rect.height() - margin_vertical; - for (int x = header_rect.x() + margin_horizontal; - x < header_rect.right() - block_size; - x += block_size + margin_horizontal) { - const int half_block = block_size / 2 - 5; - const SkColor block_color = SkColorSetRGB(255, 255, 255); - const int y = header_rect.y() + margin_vertical / 2; - int second_col = x + half_block + 10; - int second_row = y + half_block + 10; - canvas.FillRect(gfx::Rect(x, y, half_block, block_size), block_color); - canvas.FillRect(gfx::Rect(second_col, y, half_block, half_block), - block_color); - canvas.FillRect(gfx::Rect(second_col, second_row, half_block, half_block), - block_color); - } - - // Now the main body. Mostly text with some 'pictures'. - for (int y = body_rect.y() + fine_print; - y < body_rect.bottom() - fine_print; - y += 2 * fine_print) { - for (int x = body_rect.x() + fine_print; - x < body_rect.right() - fine_print; - x += 2 * fine_print) { - canvas.DrawRect(gfx::RectF(x, y, fine_print, fine_print), print_color); - } - } - - for (int line = 0; line < 3; ++line) { - int alignment = line % 2; - const int y = body_rect.y() + - body_rect.height() / 3 * line + margin_vertical; - const int x = body_rect.x() + - alignment * body_rect.width() / 2 + margin_vertical; - gfx::Rect pict_rect(x, y, body_rect.width() / 2 - 2 * margin_vertical, - body_rect.height() / 3 - 2 * margin_vertical); - canvas.FillRect(pict_rect, SkColorSetRGB(255, 255, 255)); - canvas.DrawRect(gfx::RectF(pict_rect), SkColorSetRGB(0, 0, 0)); - } - - SkBitmap source = canvas.GetBitmap(); - - SkBitmap result = CreateRetargetedThumbnailImage( - source, gfx::Size(424, 264), 2.5); - EXPECT_FALSE(result.empty()); - - // Given the nature of computation We can't really assert much here about the - // image itself. We know it should have been computed, should be smaller than - // the original and it must not be zero. - EXPECT_LT(result.width(), image_size.width()); - EXPECT_LT(result.height(), image_size.height()); - - int histogram[256] = {}; - color_utils::BuildLumaHistogram(result, histogram); - int non_zero_color_count = std::count_if( - histogram, histogram + 256, [](int value) { return value > 0; }); - EXPECT_GT(non_zero_color_count, 4); - -} - -} // namespace thumbnailing_utils
diff --git a/chrome/browser/thumbnails/content_based_thumbnailing_algorithm.cc b/chrome/browser/thumbnails/content_based_thumbnailing_algorithm.cc deleted file mode 100644 index 65591785..0000000 --- a/chrome/browser/thumbnails/content_based_thumbnailing_algorithm.cc +++ /dev/null
@@ -1,227 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/thumbnails/content_based_thumbnailing_algorithm.h" - -#include <stddef.h> - -#include "base/metrics/histogram_macros.h" -#include "base/task_scheduler/post_task.h" -#include "base/threading/sequenced_worker_pool.h" -#include "chrome/browser/thumbnails/content_analysis.h" -#include "chrome/browser/thumbnails/simple_thumbnail_crop.h" -#include "content/public/browser/browser_thread.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/gfx/color_utils.h" -#include "ui/gfx/geometry/size_conversions.h" -#include "ui/gfx/scrollbar_size.h" -#include "ui/gfx/skbitmap_operations.h" -#include "ui/gfx/skia_util.h" - -namespace { - -const char kThumbnailHistogramName[] = "Thumbnail.RetargetMS"; -const char kFailureHistogramName[] = "Thumbnail.FailedRetargetMS"; -const float kScoreBoostFromSuccessfulRetargeting = 1.1f; - -void CallbackInvocationAdapter( - const thumbnails::ThumbnailingAlgorithm::ConsumerCallback& callback, - scoped_refptr<thumbnails::ThumbnailingContext> context, - const SkBitmap& source_bitmap) { - callback.Run(*context.get(), source_bitmap); -} - -} // namespace - -namespace thumbnails { - -using content::BrowserThread; - -ContentBasedThumbnailingAlgorithm::ContentBasedThumbnailingAlgorithm( - const gfx::Size& target_size) - : target_size_(target_size) { - DCHECK(!target_size.IsEmpty()); -} - -ClipResult ContentBasedThumbnailingAlgorithm::GetCanvasCopyInfo( - const gfx::Size& source_size, - ui::ScaleFactor scale_factor, - gfx::Rect* clipping_rect, - gfx::Size* copy_size) const { - DCHECK(!source_size.IsEmpty()); - gfx::Size copy_thumbnail_size = - SimpleThumbnailCrop::GetCopySizeForThumbnail(scale_factor, target_size_); - - ClipResult clipping_method = thumbnails::CLIP_RESULT_NOT_CLIPPED; - *clipping_rect = GetClippingRect(source_size, copy_thumbnail_size, copy_size, - &clipping_method); - return clipping_method; -} - -void ContentBasedThumbnailingAlgorithm::ProcessBitmap( - scoped_refptr<ThumbnailingContext> context, - const ConsumerCallback& callback, - const SkBitmap& bitmap) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK(context.get()); - if (bitmap.isNull() || bitmap.empty()) - return; - - gfx::Size target_thumbnail_size = - SimpleThumbnailCrop::ComputeTargetSizeAtMaximumScale(target_size_); - - SkBitmap source_bitmap = - PrepareSourceBitmap(bitmap, target_thumbnail_size, context.get()); - - // If the source is same (or smaller) than the target, just return it as - // the final result. Otherwise, send the shrinking task to the blocking - // thread pool. - if (source_bitmap.width() <= target_thumbnail_size.width() || - source_bitmap.height() <= target_thumbnail_size.height()) { - context->score.boring_score = - color_utils::CalculateBoringScore(source_bitmap); - context->score.good_clipping = - (context->clip_result == CLIP_RESULT_WIDER_THAN_TALL || - context->clip_result == CLIP_RESULT_TALLER_THAN_WIDE || - context->clip_result == CLIP_RESULT_NOT_CLIPPED || - context->clip_result == CLIP_RESULT_SOURCE_SAME_AS_TARGET); - - callback.Run(*context.get(), source_bitmap); - return; - } - - base::PostTaskWithTraits( - FROM_HERE, - {base::TaskPriority::BACKGROUND, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, - base::Bind(&CreateRetargetedThumbnail, source_bitmap, - target_thumbnail_size, context, callback)); -} - -// static -SkBitmap ContentBasedThumbnailingAlgorithm::PrepareSourceBitmap( - const SkBitmap& received_bitmap, - const gfx::Size& thumbnail_size, - ThumbnailingContext* context) { - gfx::Size resize_target; - SkBitmap clipped_bitmap; - if (context->clip_result == CLIP_RESULT_UNPROCESSED) { - // This case will require extracting a fragment from the retrieved bitmap. - int scrollbar_size = gfx::scrollbar_size(); - gfx::Size scrollbarless( - std::max(1, received_bitmap.width() - scrollbar_size), - std::max(1, received_bitmap.height() - scrollbar_size)); - - gfx::Rect clipping_rect = GetClippingRect( - scrollbarless, - thumbnail_size, - &resize_target, - &context->clip_result); - - received_bitmap.extractSubset(&clipped_bitmap, - gfx::RectToSkIRect(clipping_rect)); - } else { - // This means that the source bitmap has been requested and at least - // clipped. Upstream code in same cases seems opportunistic and it may - // not perform actual resizing if copying with resize is not supported. - // In this case we will resize to the orignally requested copy size. - resize_target = context->requested_copy_size; - clipped_bitmap = received_bitmap; - } - - SkBitmap result_bitmap = SkBitmapOperations::DownsampleByTwoUntilSize( - clipped_bitmap, resize_target.width(), resize_target.height()); - - return result_bitmap; -} - -// static -void ContentBasedThumbnailingAlgorithm::CreateRetargetedThumbnail( - const SkBitmap& source_bitmap, - const gfx::Size& thumbnail_size, - scoped_refptr<ThumbnailingContext> context, - const ConsumerCallback& callback) { - base::TimeTicks begin_compute_thumbnail = base::TimeTicks::Now(); - float kernel_sigma = - context->clip_result == CLIP_RESULT_SOURCE_SAME_AS_TARGET ? 5.0f : 2.5f; - SkBitmap thumbnail = thumbnailing_utils::CreateRetargetedThumbnailImage( - source_bitmap, thumbnail_size, kernel_sigma); - bool processing_failed = thumbnail.empty(); - if (processing_failed) { - // Log and apply the method very much like in SimpleThumbnailCrop (except - // that some clipping and copying is not required). - LOG(WARNING) << "CreateRetargetedThumbnailImage failed. " - << "The thumbnail for " << context->url - << " will be created the old-fashioned way."; - - ClipResult clip_result; - gfx::Rect clipping_rect = SimpleThumbnailCrop::GetClippingRect( - gfx::Size(source_bitmap.width(), source_bitmap.height()), - thumbnail_size, - &clip_result); - source_bitmap.extractSubset(&thumbnail, gfx::RectToSkIRect(clipping_rect)); - thumbnail = SkBitmapOperations::DownsampleByTwoUntilSize( - thumbnail, thumbnail_size.width(), thumbnail_size.height()); - } - - if (processing_failed) { - LOCAL_HISTOGRAM_TIMES(kFailureHistogramName, - base::TimeTicks::Now() - begin_compute_thumbnail); - } else { - LOCAL_HISTOGRAM_TIMES(kThumbnailHistogramName, - base::TimeTicks::Now() - begin_compute_thumbnail); - } - context->score.boring_score = - color_utils::CalculateBoringScore(source_bitmap); - if (!processing_failed) - context->score.boring_score *= kScoreBoostFromSuccessfulRetargeting; - context->score.good_clipping = - (context->clip_result == CLIP_RESULT_WIDER_THAN_TALL || - context->clip_result == CLIP_RESULT_TALLER_THAN_WIDE || - context->clip_result == CLIP_RESULT_NOT_CLIPPED || - context->clip_result == CLIP_RESULT_SOURCE_SAME_AS_TARGET); - // Post the result (the bitmap) back to the callback. - BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&CallbackInvocationAdapter, callback, context, thumbnail)); -} - -ContentBasedThumbnailingAlgorithm::~ContentBasedThumbnailingAlgorithm() { -} - -// static -gfx::Rect ContentBasedThumbnailingAlgorithm::GetClippingRect( - const gfx::Size& source_size, - const gfx::Size& thumbnail_size, - gfx::Size* target_size, - ClipResult* clip_result) { - // Compute and return the clipping rectagle of the source image and the - // size of the target bitmap which will be used for the further processing. - // This function in 'general case' is trivial (don't clip, halve the source) - // but it is needed for handling edge cases (source smaller than the target - // thumbnail size). - DCHECK(target_size); - DCHECK(clip_result); - gfx::Rect clipping_rect; - if (source_size.width() < thumbnail_size.width() || - source_size.height() < thumbnail_size.height()) { - clipping_rect = gfx::Rect(thumbnail_size); - *target_size = thumbnail_size; - *clip_result = CLIP_RESULT_SOURCE_IS_SMALLER; - } else if (source_size.width() < thumbnail_size.width() * 4 || - source_size.height() < thumbnail_size.height() * 4) { - clipping_rect = gfx::Rect(source_size); - *target_size = source_size; - *clip_result = CLIP_RESULT_SOURCE_SAME_AS_TARGET; - } else { - clipping_rect = gfx::Rect(source_size); - target_size->SetSize(source_size.width() / 2, source_size.height() / 2); - *clip_result = CLIP_RESULT_NOT_CLIPPED; - } - - return clipping_rect; -} - -} // namespace thumbnails
diff --git a/chrome/browser/thumbnails/content_based_thumbnailing_algorithm.h b/chrome/browser/thumbnails/content_based_thumbnailing_algorithm.h deleted file mode 100644 index ede432c..0000000 --- a/chrome/browser/thumbnails/content_based_thumbnailing_algorithm.h +++ /dev/null
@@ -1,62 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_THUMBNAILS_CONTENT_BASED_THUMBNAILING_ALGORITHM_H_ -#define CHROME_BROWSER_THUMBNAILS_CONTENT_BASED_THUMBNAILING_ALGORITHM_H_ - -#include "base/macros.h" -#include "chrome/browser/thumbnails/thumbnailing_algorithm.h" - -namespace thumbnails { - -// Encapsulates a method of creating a thumbnail from a captured tab shot which -// attempts to preserve only relevant fragments of the original image. -// The algorithm detects areas of high activity at low resolution and discards -// rows and columns which do not intersect with these areas. -class ContentBasedThumbnailingAlgorithm : public ThumbnailingAlgorithm { - public: - explicit ContentBasedThumbnailingAlgorithm(const gfx::Size& target_size); - - ClipResult GetCanvasCopyInfo(const gfx::Size& source_size, - ui::ScaleFactor scale_factor, - gfx::Rect* clipping_rect, - gfx::Size* copy_size) const override; - - void ProcessBitmap(scoped_refptr<ThumbnailingContext> context, - const ConsumerCallback& callback, - const SkBitmap& bitmap) override; - - // Prepares (clips to size, copies etc.) the bitmap passed to ProcessBitmap. - // Always returns a bitmap that can be properly refcounted. - // Extracted and exposed as a test seam. - static SkBitmap PrepareSourceBitmap(const SkBitmap& received_bitmap, - const gfx::Size& thumbnail_size, - ThumbnailingContext* context); - - // The function processes |source_bitmap| into a thumbnail of |thumbnail_size| - // and passes the result into |callback| (on UI thread). |context| describes - // how the thumbnail is being created. - static void CreateRetargetedThumbnail( - const SkBitmap& source_bitmap, - const gfx::Size& thumbnail_size, - scoped_refptr<ThumbnailingContext> context, - const ConsumerCallback& callback); - - protected: - ~ContentBasedThumbnailingAlgorithm() override; - - private: - static gfx::Rect GetClippingRect(const gfx::Size& source_size, - const gfx::Size& thumbnail_size, - gfx::Size* target_size, - ClipResult* clip_result); - - const gfx::Size target_size_; - - DISALLOW_COPY_AND_ASSIGN(ContentBasedThumbnailingAlgorithm); -}; - -} // namespace thumbnails - -#endif // CHROME_BROWSER_THUMBNAILS_CONTENT_BASED_THUMBNAILING_ALGORITHM_H_
diff --git a/chrome/browser/thumbnails/content_based_thumbnailing_algorithm_unittest.cc b/chrome/browser/thumbnails/content_based_thumbnailing_algorithm_unittest.cc deleted file mode 100644 index cf6de0e..0000000 --- a/chrome/browser/thumbnails/content_based_thumbnailing_algorithm_unittest.cc +++ /dev/null
@@ -1,167 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/thumbnails/content_based_thumbnailing_algorithm.h" - -#include "base/macros.h" -#include "base/run_loop.h" -#include "chrome/browser/thumbnails/simple_thumbnail_crop.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/test/test_browser_thread_bundle.h" -#include "skia/ext/platform_canvas.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/scrollbar_size.h" - -namespace thumbnails { - -typedef testing::Test ContentBasedThumbnailingAlgorithmTest; - -class ConsumerCallbackCatcher { - public: - ConsumerCallbackCatcher() - : called_back_(false), clip_result_(CLIP_RESULT_UNPROCESSED) { - } - - void UiThreadCallback(const ThumbnailingContext& context, - const SkBitmap& bitmap) { - called_back_ = true; - captured_bitmap_ = bitmap; - clip_result_ = context.clip_result; - score_ = context.score; - } - - bool called_back() const { - return called_back_; - } - - const SkBitmap& captured_bitmap() const { - return captured_bitmap_; - } - - ClipResult clip_result() const { - return clip_result_; - } - - const ThumbnailScore& score() const { - return score_; - } - - private: - SkBitmap captured_bitmap_; - bool called_back_; - ClipResult clip_result_; - ThumbnailScore score_; - - DISALLOW_COPY_AND_ASSIGN(ConsumerCallbackCatcher); -}; - -TEST_F(ContentBasedThumbnailingAlgorithmTest, GetCanvasCopyInfo) { - // We will want to use the entirety of the image as the source. Usually, - // an image in its original size should be requested, except for reakky large - // canvas. In that case, image will be shrunk but wit aspect ratio preserved. - const gfx::Size thumbnail_size(312, 165); - scoped_refptr<ThumbnailingAlgorithm> algorithm( - new ContentBasedThumbnailingAlgorithm(thumbnail_size)); - - gfx::Rect clipping_rect; - gfx::Size target_size; - gfx::Size source_size(1000, 600); - - ClipResult clip_result = algorithm->GetCanvasCopyInfo( - source_size, ui::SCALE_FACTOR_100P, &clipping_rect, &target_size); - EXPECT_EQ(CLIP_RESULT_SOURCE_SAME_AS_TARGET, clip_result); - EXPECT_EQ(source_size.ToString(), clipping_rect.size().ToString()); - EXPECT_EQ(gfx::Point(0, 0).ToString(), clipping_rect.origin().ToString()); - EXPECT_EQ(source_size, target_size); - - source_size.SetSize(6000, 3000); - clip_result = algorithm->GetCanvasCopyInfo( - source_size, ui::SCALE_FACTOR_100P, &clipping_rect, &target_size); - EXPECT_EQ(CLIP_RESULT_NOT_CLIPPED, clip_result); - EXPECT_EQ(source_size.ToString(), clipping_rect.size().ToString()); - EXPECT_EQ(gfx::Point(0, 0).ToString(), clipping_rect.origin().ToString()); - EXPECT_LT(target_size.width(), source_size.width()); - EXPECT_LT(target_size.height(), source_size.height()); - EXPECT_NEAR(static_cast<float>(target_size.width()) / target_size.height(), - static_cast<float>(source_size.width()) / source_size.height(), - 0.1f); - source_size.SetSize(300, 200); - clip_result = algorithm->GetCanvasCopyInfo( - source_size, ui::SCALE_FACTOR_100P, &clipping_rect, &target_size); - EXPECT_EQ(CLIP_RESULT_SOURCE_IS_SMALLER, clip_result); - EXPECT_EQ(clipping_rect.size().ToString(), - SimpleThumbnailCrop::GetCopySizeForThumbnail( - ui::SCALE_FACTOR_100P, thumbnail_size).ToString()); - EXPECT_EQ(gfx::Point(0, 0).ToString(), clipping_rect.origin().ToString()); -} - -TEST_F(ContentBasedThumbnailingAlgorithmTest, PrepareSourceBitmap) { - const gfx::Size thumbnail_size(312, 165); - const gfx::Size copy_size(400, 200); - scoped_refptr<ThumbnailingContext> context( - ThumbnailingContext::CreateThumbnailingContextForTest()); - context->requested_copy_size = copy_size; - - // This calls for exercising two distinct paths: with prior clipping and - // without. - SkBitmap source; - source.allocN32Pixels(800, 600); - source.eraseARGB(255, 50, 150, 200); - SkBitmap result = ContentBasedThumbnailingAlgorithm::PrepareSourceBitmap( - source, thumbnail_size, context.get()); - EXPECT_EQ(CLIP_RESULT_SOURCE_SAME_AS_TARGET, context->clip_result); - EXPECT_GE(result.width(), copy_size.width()); - EXPECT_GE(result.height(), copy_size.height()); - EXPECT_LT(result.width(), source.width()); - EXPECT_LT(result.height(), source.height()); - // The check below is a bit of a side effect: since the image was clipped - // by scrollbar_size, it cannot be shrunk and thus what we get below is - // true. - EXPECT_NEAR(result.width(), source.width(), gfx::scrollbar_size()); - EXPECT_NEAR(result.height(), source.height(), gfx::scrollbar_size()); - - result = ContentBasedThumbnailingAlgorithm::PrepareSourceBitmap( - source, thumbnail_size, context.get()); - EXPECT_EQ(CLIP_RESULT_SOURCE_SAME_AS_TARGET, context->clip_result); - EXPECT_GE(result.width(), copy_size.width()); - EXPECT_GE(result.height(), copy_size.height()); - EXPECT_LT(result.width(), source.width()); - EXPECT_LT(result.height(), source.height()); -} - -TEST_F(ContentBasedThumbnailingAlgorithmTest, CreateRetargetedThumbnail) { - // This tests the invocation of the main thumbnail-making apparatus. - // The actual content is not really of concern here, just check the plumbing. - const gfx::Size image_size(1200, 800); - gfx::Canvas canvas(image_size, 1.0f, true); - - // The image consists of vertical non-overlapping stripes 150 pixels wide. - canvas.FillRect(gfx::Rect(200, 200, 800, 400), SkColorSetRGB(255, 255, 255)); - SkBitmap source = canvas.GetBitmap(); - - ConsumerCallbackCatcher catcher; - const gfx::Size thumbnail_size(432, 284); - scoped_refptr<ThumbnailingContext> context( - ThumbnailingContext::CreateThumbnailingContextForTest()); - context->requested_copy_size = image_size; - context->clip_result = CLIP_RESULT_SOURCE_SAME_AS_TARGET; - - content::TestBrowserThreadBundle test_browser_thread_bundle; - ContentBasedThumbnailingAlgorithm::CreateRetargetedThumbnail( - source, - thumbnail_size, - context, - base::Bind(&ConsumerCallbackCatcher::UiThreadCallback, - base::Unretained(&catcher))); - base::RunLoop().RunUntilIdle(); - ASSERT_TRUE(catcher.called_back()); - EXPECT_TRUE(catcher.score().good_clipping); - EXPECT_FALSE(catcher.captured_bitmap().empty()); - EXPECT_LT(catcher.captured_bitmap().width(), source.width()); - EXPECT_LT(catcher.captured_bitmap().height(), source.height()); -} - -} // namespace thumbnails
diff --git a/chrome/browser/thumbnails/thumbnail_service.h b/chrome/browser/thumbnails/thumbnail_service.h index 97000d2e..cf8290f 100644 --- a/chrome/browser/thumbnails/thumbnail_service.h +++ b/chrome/browser/thumbnails/thumbnail_service.h
@@ -36,6 +36,7 @@ // process of creating a thumbnail from tab contents. The lifetime of these // instances is limited to the act of processing a single tab image. They // are permitted to hold the state of such process. + // TODO(treib): Return a scoped_refptr rather than raw pointer. virtual ThumbnailingAlgorithm* GetThumbnailingAlgorithm() const = 0; // Gets a thumbnail for a given page. Returns true iff we have the thumbnail.
diff --git a/chrome/browser/thumbnails/thumbnail_service_impl.cc b/chrome/browser/thumbnails/thumbnail_service_impl.cc index 8c2d1a9..603c1a21 100644 --- a/chrome/browser/thumbnails/thumbnail_service_impl.cc +++ b/chrome/browser/thumbnails/thumbnail_service_impl.cc
@@ -4,16 +4,12 @@ #include "chrome/browser/thumbnails/thumbnail_service_impl.h" -#include "base/command_line.h" #include "base/memory/ref_counted_memory.h" #include "base/time/time.h" #include "chrome/browser/history/history_utils.h" #include "chrome/browser/history/top_sites_factory.h" -#include "chrome/browser/thumbnails/content_based_thumbnailing_algorithm.h" #include "chrome/browser/thumbnails/simple_thumbnail_crop.h" #include "chrome/browser/thumbnails/thumbnailing_context.h" -#include "chrome/common/chrome_switches.h" -#include "components/search/search.h" #include "content/public/browser/browser_thread.h" #include "url/gurl.h" @@ -28,15 +24,6 @@ const int kThumbnailWidth = 154; const int kThumbnailHeight = 96; -// True if thumbnail retargeting feature is enabled (Finch/flags). -bool IsThumbnailRetargetingEnabled() { - if (!search::IsInstantExtendedAPIEnabled()) - return false; - - return base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableThumbnailRetargeting); -} - void AddForcedURLOnUIThread(scoped_refptr<history::TopSites> top_sites, const GURL& url) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -50,9 +37,7 @@ namespace thumbnails { ThumbnailServiceImpl::ThumbnailServiceImpl(Profile* profile) - : top_sites_(TopSitesFactory::GetForProfile(profile)), - use_thumbnail_retargeting_(IsThumbnailRetargetingEnabled()) { -} + : top_sites_(TopSitesFactory::GetForProfile(profile)) {} ThumbnailServiceImpl::~ThumbnailServiceImpl() { } @@ -89,10 +74,7 @@ ThumbnailingAlgorithm* ThumbnailServiceImpl::GetThumbnailingAlgorithm() const { - const gfx::Size thumbnail_size(kThumbnailWidth, kThumbnailHeight); - if (use_thumbnail_retargeting_) - return new ContentBasedThumbnailingAlgorithm(thumbnail_size); - return new SimpleThumbnailCrop(thumbnail_size); + return new SimpleThumbnailCrop(gfx::Size(kThumbnailWidth, kThumbnailHeight)); } bool ThumbnailServiceImpl::ShouldAcquirePageThumbnail(const GURL& url) {
diff --git a/chrome/browser/thumbnails/thumbnail_service_impl.h b/chrome/browser/thumbnails/thumbnail_service_impl.h index 537bf0e..19b29727 100644 --- a/chrome/browser/thumbnails/thumbnail_service_impl.h +++ b/chrome/browser/thumbnails/thumbnail_service_impl.h
@@ -40,7 +40,6 @@ ~ThumbnailServiceImpl() override; scoped_refptr<history::TopSites> top_sites_; - bool use_thumbnail_retargeting_; DISALLOW_COPY_AND_ASSIGN(ThumbnailServiceImpl); };
diff --git a/chrome/browser/ui/search/ntp_user_data_logger.cc b/chrome/browser/ui/search/ntp_user_data_logger.cc index 370ff05..91253f7 100644 --- a/chrome/browser/ui/search/ntp_user_data_logger.cc +++ b/chrome/browser/ui/search/ntp_user_data_logger.cc
@@ -165,8 +165,8 @@ DVLOG(1) << "Emitting NTP load time: " << load_time << ", " << "number of tiles: " << impression_was_logged_.count(); - std::vector<ntp_tiles::metrics::TileImpression> tiles; bool has_server_side_suggestions = false; + int tiles_count = 0; for (int i = 0; i < kNumMostVisited; i++) { if (!impression_was_logged_[i]) { break; @@ -175,14 +175,14 @@ ntp_tiles::TileSource::SUGGESTIONS_SERVICE) { has_server_side_suggestions = true; } - // No URL passed since we're not interested in favicon-related Rappor - // metrics. - tiles.emplace_back(impression_tile_source_[i], impression_tile_type_[i], - GURL()); + // No URL and rappor service passed - not interested in favicon-related + // Rappor metrics. + ntp_tiles::metrics::RecordTileImpression(i, impression_tile_source_[i], + impression_tile_type_[i], GURL(), + /*rappor_service=*/nullptr); + ++tiles_count; } - - // Not interested in Rappor metrics. - ntp_tiles::metrics::RecordPageImpression(tiles, /*rappor_service=*/nullptr); + ntp_tiles::metrics::RecordPageImpression(tiles_count); UMA_HISTOGRAM_LOAD_TIME("NewTabPage.TilesReceivedTime", tiles_received_time_); UMA_HISTOGRAM_LOAD_TIME("NewTabPage.LoadTime", load_time);
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 53cdd61..c042489 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -424,10 +424,6 @@ // Enables user control over muting tab audio from the tab strip. const char kEnableTabAudioMuting[] = "enable-tab-audio-muting"; -// Enables fanciful thumbnail processing. Used with NTP for -// instant-extended-api, where thumbnails are generally smaller. -const char kEnableThumbnailRetargeting[] = "enable-thumbnail-retargeting"; - // Enables Web Notification custom layouts. const char kEnableWebNotificationCustomLayouts[] = "enable-web-notification-custom-layouts";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 597aee9b..7a74fa7 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -132,7 +132,6 @@ extern const char kEnableSiteSettings[]; extern const char kEnableSupervisedUserManagedBookmarksFolder[]; extern const char kEnableTabAudioMuting[]; -extern const char kEnableThumbnailRetargeting[]; extern const char kEnableWebNotificationCustomLayouts[]; extern const char kEnableWebRtcEventLoggingFromExtension[]; extern const char kExtensionContentVerification[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 3ebf6d1..9070ab1 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3283,8 +3283,6 @@ "../browser/sync/sessions/sync_sessions_web_contents_router_unittest.cc", "../browser/sync/sync_startup_tracker_unittest.cc", "../browser/task_profiler/task_profiler_data_serializer_unittest.cc", - "../browser/thumbnails/content_analysis_unittest.cc", - "../browser/thumbnails/content_based_thumbnailing_algorithm_unittest.cc", "../browser/thumbnails/simple_thumbnail_crop_unittest.cc", "../browser/thumbnails/thumbnail_service_unittest.cc", "../browser/translate/chrome_translate_client_unittest.cc",
diff --git a/components/ntp_snippets/BUILD.gn b/components/ntp_snippets/BUILD.gn index a719f54f..651fe36e 100644 --- a/components/ntp_snippets/BUILD.gn +++ b/components/ntp_snippets/BUILD.gn
@@ -17,6 +17,7 @@ "bookmarks/bookmark_suggestions_provider.h", "breaking_news/breaking_news_gcm_app_handler.cc", "breaking_news/breaking_news_gcm_app_handler.h", + "breaking_news/breaking_news_listener.h", "breaking_news/breaking_news_suggestions_provider.cc", "breaking_news/breaking_news_suggestions_provider.h", "breaking_news/subscription_json_request.cc",
diff --git a/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.cc b/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.cc index d25f967..31c4e1c2 100644 --- a/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.cc +++ b/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.cc
@@ -15,19 +15,19 @@ namespace ntp_snippets { -const char kContentSuggestionsGCMAppID[] = "com.google.contentsuggestions.gcm"; +const char kBreakingNewsGCMAppID[] = "com.google.breakingnews.gcm"; // The sender ID is used in the registration process. // See: https://developers.google.com/cloud-messaging/gcm#senderid // TODO(mamir): use proper sender Id. -const char kContentSuggestionsGCMSenderId[] = "128223710667"; +const char kBreakingNewsGCMSenderId[] = "128223710667"; // OAuth2 Scope passed to getToken to obtain GCM registration tokens. // Must match Java GoogleCloudMessaging.INSTANCE_ID_SCOPE. const char kGCMScope[] = "GCM"; -// Key of the suggestion json in the data in the pushed content suggestion. -const char kPushedSuggestionKey[] = "payload"; +// Key of the news json in the data in the pushed breaking news. +const char kPushedNewsKey[] = "payload"; BreakingNewsGCMAppHandler::BreakingNewsGCMAppHandler( gcm::GCMDriver* gcm_driver, @@ -40,7 +40,7 @@ pref_service_(pref_service), subscription_manager_(std::move(subscription_manager)), parse_json_callback_(parse_json_callback), - weak_factory_(this) {} + weak_ptr_factory_(this) {} BreakingNewsGCMAppHandler::~BreakingNewsGCMAppHandler() { StopListening(); @@ -54,23 +54,23 @@ #endif Subscribe(); on_new_content_callback_ = std::move(on_new_content_callback); - gcm_driver_->AddAppHandler(kContentSuggestionsGCMAppID, this); + gcm_driver_->AddAppHandler(kBreakingNewsGCMAppID, this); } void BreakingNewsGCMAppHandler::StopListening() { - DCHECK_EQ(gcm_driver_->GetAppHandler(kContentSuggestionsGCMAppID), this); - gcm_driver_->RemoveAppHandler(kContentSuggestionsGCMAppID); + DCHECK_EQ(gcm_driver_->GetAppHandler(kBreakingNewsGCMAppID), this); + gcm_driver_->RemoveAppHandler(kBreakingNewsGCMAppID); on_new_content_callback_ = OnNewContentCallback(); // TODO(mamir): Check which token should be used for unsubscription when // handling change in the token. std::string token = pref_service_->GetString( - ntp_snippets::prefs::kContentSuggestionsGCMSubscriptionTokenCache); + ntp_snippets::prefs::kBreakingNewsGCMSubscriptionTokenCache); subscription_manager_->Unsubscribe(token); } void BreakingNewsGCMAppHandler::Subscribe() { std::string token = pref_service_->GetString( - ntp_snippets::prefs::kContentSuggestionsGCMSubscriptionTokenCache); + ntp_snippets::prefs::kBreakingNewsGCMSubscriptionTokenCache); // If a token has been already obtained, subscribe directly at the content // suggestions server. if (!token.empty()) { @@ -80,11 +80,11 @@ return; } - instance_id_driver_->GetInstanceID(kContentSuggestionsGCMAppID) - ->GetToken(kContentSuggestionsGCMSenderId, kGCMScope, + instance_id_driver_->GetInstanceID(kBreakingNewsGCMAppID) + ->GetToken(kBreakingNewsGCMSenderId, kGCMScope, std::map<std::string, std::string>() /* options */, base::Bind(&BreakingNewsGCMAppHandler::DidSubscribe, - weak_factory_.GetWeakPtr())); + weak_ptr_factory_.GetWeakPtr())); } void BreakingNewsGCMAppHandler::DidSubscribe(const std::string& subscription_id, @@ -92,7 +92,7 @@ switch (result) { case InstanceID::SUCCESS: pref_service_->SetString( - ntp_snippets::prefs::kContentSuggestionsGCMSubscriptionTokenCache, + ntp_snippets::prefs::kBreakingNewsGCMSubscriptionTokenCache, subscription_id); subscription_manager_->Subscribe(subscription_id); return; @@ -114,27 +114,27 @@ void BreakingNewsGCMAppHandler::OnStoreReset() { pref_service_->ClearPref( - ntp_snippets::prefs::kContentSuggestionsGCMSubscriptionTokenCache); + ntp_snippets::prefs::kBreakingNewsGCMSubscriptionTokenCache); } void BreakingNewsGCMAppHandler::OnMessage(const std::string& app_id, const gcm::IncomingMessage& message) { - DCHECK_EQ(app_id, kContentSuggestionsGCMAppID); + DCHECK_EQ(app_id, kBreakingNewsGCMAppID); - gcm::MessageData::const_iterator it = message.data.find(kPushedSuggestionKey); + gcm::MessageData::const_iterator it = message.data.find(kPushedNewsKey); if (it == message.data.end()) { LOG(WARNING) - << "Receiving pushed content failure: Content suggestion ID missing."; + << "Receiving pushed content failure: Breaking News ID missing."; return; } - std::string suggestions = it->second; + std::string news = it->second; - parse_json_callback_.Run(suggestions, + parse_json_callback_.Run(news, base::Bind(&BreakingNewsGCMAppHandler::OnJsonSuccess, - weak_factory_.GetWeakPtr()), + weak_ptr_factory_.GetWeakPtr()), base::Bind(&BreakingNewsGCMAppHandler::OnJsonError, - weak_factory_.GetWeakPtr(), suggestions)); + weak_ptr_factory_.GetWeakPtr(), news)); } void BreakingNewsGCMAppHandler::OnMessagesDeleted(const std::string& app_id) { @@ -160,8 +160,8 @@ void BreakingNewsGCMAppHandler::RegisterProfilePrefs( PrefRegistrySimple* registry) { - registry->RegisterStringPref( - prefs::kContentSuggestionsGCMSubscriptionTokenCache, std::string()); + registry->RegisterStringPref(prefs::kBreakingNewsGCMSubscriptionTokenCache, + std::string()); } void BreakingNewsGCMAppHandler::OnJsonSuccess(
diff --git a/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.h b/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.h index c21a05b..4dcfe34 100644 --- a/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.h +++ b/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.h
@@ -8,6 +8,7 @@ #include "base/memory/weak_ptr.h" #include "components/gcm_driver/gcm_app_handler.h" #include "components/gcm_driver/instance_id/instance_id.h" +#include "components/ntp_snippets/breaking_news/breaking_news_listener.h" #include "components/ntp_snippets/breaking_news/subscription_manager.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" @@ -27,7 +28,8 @@ // Handler for pushed GCM breaking news. It retrieves a subscription token // from the GCM server and registers/unregisters itself with the GCM service to // be called upon received push breaking news. -class BreakingNewsGCMAppHandler : public gcm::GCMAppHandler { +class BreakingNewsGCMAppHandler : public BreakingNewsListener, + public gcm::GCMAppHandler { public: // Callbacks for JSON parsing to allow injecting platform-dependent code. using SuccessCallback = @@ -51,14 +53,9 @@ // If still listening, calls StopListening() ~BreakingNewsGCMAppHandler() override; - // Subscribe to the GCM service if necessary and start listening for pushed - // content suggestions. Must not be called if already listening. - void StartListening(OnNewContentCallback on_new_content_callback); - - // Remove the handler, and stop listening for incoming GCM messages. Any - // further pushed content suggestions will be ignored. Must be called while - // listening. - void StopListening(); + // BreakingNewsListener overrides. + void StartListening(OnNewContentCallback on_new_content_callback) override; + void StopListening() override; // GCMAppHandler overrides. void ShutdownHandler() override; @@ -100,7 +97,7 @@ // the content provider. OnNewContentCallback on_new_content_callback_; - base::WeakPtrFactory<BreakingNewsGCMAppHandler> weak_factory_; + base::WeakPtrFactory<BreakingNewsGCMAppHandler> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(BreakingNewsGCMAppHandler); };
diff --git a/components/ntp_snippets/breaking_news/breaking_news_listener.h b/components/ntp_snippets/breaking_news/breaking_news_listener.h new file mode 100644 index 0000000..41c1909 --- /dev/null +++ b/components/ntp_snippets/breaking_news/breaking_news_listener.h
@@ -0,0 +1,30 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_NTP_SNIPPETS_BREAKING_NEWS_BREAKING_NEWS_LISTENER_H_ +#define COMPONENTS_NTP_SNIPPETS_BREAKING_NEWS_BREAKING_NEWS_LISTENER_H_ + +#include <memory> + +#include "base/callback_forward.h" +#include "base/values.h" + +namespace ntp_snippets { + +class BreakingNewsListener { + public: + using OnNewContentCallback = + base::Callback<void(std::unique_ptr<base::Value> content)>; + + // Subscribe to the breaking news service and start listening for pushed + // breaking news. Must not be called if already listening. + virtual void StartListening(OnNewContentCallback on_new_content_callback) = 0; + + // Stop listening for incoming breaking news. Any further pushed breaking news + // will be ignored. Must be called while listening. + virtual void StopListening() = 0; +}; +} // namespace ntp_snippets + +#endif // COMPONENTS_NTP_SNIPPETS_BREAKING_NEWS_BREAKING_NEWS_LISTENER_H_
diff --git a/components/ntp_snippets/breaking_news/breaking_news_suggestions_provider.cc b/components/ntp_snippets/breaking_news/breaking_news_suggestions_provider.cc index 0d57a2d..bfa8cd3 100644 --- a/components/ntp_snippets/breaking_news/breaking_news_suggestions_provider.cc +++ b/components/ntp_snippets/breaking_news/breaking_news_suggestions_provider.cc
@@ -7,7 +7,7 @@ #include "base/bind.h" #include "base/json/json_writer.h" #include "base/time/clock.h" -#include "components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.h" +#include "components/ntp_snippets/breaking_news/breaking_news_listener.h" #include "components/ntp_snippets/category.h" #include "components/ntp_snippets/pref_names.h" #include "components/ntp_snippets/remote/json_to_categories.h" @@ -17,11 +17,11 @@ BreakingNewsSuggestionsProvider::BreakingNewsSuggestionsProvider( ContentSuggestionsProvider::Observer* observer, - std::unique_ptr<BreakingNewsGCMAppHandler> gcm_app_handler, + std::unique_ptr<BreakingNewsListener> breaking_news_listener, std::unique_ptr<base::Clock> clock, std::unique_ptr<RemoteSuggestionsDatabase> database) : ContentSuggestionsProvider(observer), - gcm_app_handler_(std::move(gcm_app_handler)), + breaking_news_listener_(std::move(breaking_news_listener)), clock_(std::move(clock)), database_(std::move(database)), provided_category_( @@ -33,17 +33,14 @@ database_->LoadSnippets( base::Bind(&BreakingNewsSuggestionsProvider::OnDatabaseLoaded, base::Unretained(this))); + // Unretained because |this| owns |breaking_news_listener_|. + breaking_news_listener_->StartListening( + base::Bind(&BreakingNewsSuggestionsProvider::OnNewContentSuggestion, + base::Unretained(this))); } BreakingNewsSuggestionsProvider::~BreakingNewsSuggestionsProvider() { - gcm_app_handler_->StopListening(); -} - -void BreakingNewsSuggestionsProvider::Start() { - // Unretained because |this| owns |gcm_app_handler_|. - gcm_app_handler_->StartListening( - base::Bind(&BreakingNewsSuggestionsProvider::OnNewContentSuggestion, - base::Unretained(this))); + breaking_news_listener_->StopListening(); } void BreakingNewsSuggestionsProvider::OnNewContentSuggestion(
diff --git a/components/ntp_snippets/breaking_news/breaking_news_suggestions_provider.h b/components/ntp_snippets/breaking_news/breaking_news_suggestions_provider.h index df316a9..23b40ab 100644 --- a/components/ntp_snippets/breaking_news/breaking_news_suggestions_provider.h +++ b/components/ntp_snippets/breaking_news/breaking_news_suggestions_provider.h
@@ -11,7 +11,7 @@ #include "components/prefs/pref_registry_simple.h" namespace ntp_snippets { -class BreakingNewsGCMAppHandler; +class BreakingNewsListener; } namespace base { @@ -20,21 +20,20 @@ namespace ntp_snippets { -// Receives breaking news suggestions via GCM push messages, stores them and -// provides them as content suggestions. -class BreakingNewsSuggestionsProvider : public ContentSuggestionsProvider { +// Receives breaking news suggestions asynchronously via BreakingNewsListener, +// stores them and provides them as content suggestions. +// This class is final because it does things in its constructor which make it +// unsafe to derive from it. +class BreakingNewsSuggestionsProvider final + : public ContentSuggestionsProvider { public: BreakingNewsSuggestionsProvider( ContentSuggestionsProvider::Observer* observer, - std::unique_ptr<BreakingNewsGCMAppHandler> gcm_app_handler, + std::unique_ptr<BreakingNewsListener> breaking_news_listener_, std::unique_ptr<base::Clock> clock, std::unique_ptr<RemoteSuggestionsDatabase> database); ~BreakingNewsSuggestionsProvider() override; - // Starts the underlying GCM handler and registers the callback when GCM - // receives a message. - void Start(); - private: // ContentSuggestionsProvider implementation. CategoryStatus GetCategoryStatus(Category category) override; @@ -55,8 +54,8 @@ const DismissedSuggestionsCallback& callback) override; void ClearDismissedSuggestionsForDebugging(Category category) override; - // Callback called from the GCM handler when new content has been pushed from - // the server. + // Callback called from the breaking news listener when new content has been + // pushed from the server. void OnNewContentSuggestion(std::unique_ptr<base::Value> content); // Callbacks for the RemoteSuggestionsDatabase. @@ -67,7 +66,7 @@ void NotifyNewSuggestions( std::vector<std::unique_ptr<RemoteSuggestion>> suggestions); - std::unique_ptr<BreakingNewsGCMAppHandler> gcm_app_handler_; + std::unique_ptr<BreakingNewsListener> breaking_news_listener_; std::unique_ptr<base::Clock> clock_; // The database for persisting suggestions.
diff --git a/components/ntp_snippets/breaking_news/subscription_manager.cc b/components/ntp_snippets/breaking_news/subscription_manager.cc index 5588bf9..aba15d2 100644 --- a/components/ntp_snippets/breaking_news/subscription_manager.cc +++ b/components/ntp_snippets/breaking_news/subscription_manager.cc
@@ -66,7 +66,7 @@ // change. // TODO(mamir): store region and language. pref_service_->SetString( - ntp_snippets::prefs::kContentSuggestionsSubscriptionDataToken, + ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken, subscription_token_); break; default: @@ -97,7 +97,7 @@ bool SubscriptionManager::IsSubscribed() { std::string subscription_token_ = pref_service_->GetString( - ntp_snippets::prefs::kContentSuggestionsSubscriptionDataToken); + ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken); return !subscription_token_.empty(); } @@ -109,7 +109,7 @@ // In case of successful unsubscription, clear the previously stored data. // TODO(mamir): clear stored region and language. pref_service_->ClearPref( - ntp_snippets::prefs::kContentSuggestionsSubscriptionDataToken); + ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken); break; default: // TODO(mamir): handle failure. @@ -118,14 +118,13 @@ } void SubscriptionManager::RegisterProfilePrefs(PrefRegistrySimple* registry) { - registry->RegisterStringPref(prefs::kContentSuggestionsSubscriptionDataToken, + registry->RegisterStringPref(prefs::kBreakingNewsSubscriptionDataToken, std::string()); } GURL GetPushUpdatesSubscriptionEndpoint(version_info::Channel channel) { std::string endpoint = base::GetFieldTrialParamValueByFeature( - ntp_snippets::kContentSuggestionsPushFeature, - kPushSubscriptionBackendParam); + ntp_snippets::kBreakingNewsPushFeature, kPushSubscriptionBackendParam); if (!endpoint.empty()) { return GURL{endpoint}; } @@ -146,8 +145,7 @@ GURL GetPushUpdatesUnsubscriptionEndpoint(version_info::Channel channel) { std::string endpoint = base::GetFieldTrialParamValueByFeature( - ntp_snippets::kContentSuggestionsPushFeature, - kPushUnsubscriptionBackendParam); + ntp_snippets::kBreakingNewsPushFeature, kPushUnsubscriptionBackendParam); if (!endpoint.empty()) { return GURL{endpoint}; }
diff --git a/components/ntp_snippets/breaking_news/subscription_manager_unittest.cc b/components/ntp_snippets/breaking_news/subscription_manager_unittest.cc index 1cf4f41..b90d1e5 100644 --- a/components/ntp_snippets/breaking_news/subscription_manager_unittest.cc +++ b/components/ntp_snippets/breaking_news/subscription_manager_unittest.cc
@@ -71,7 +71,7 @@ RespondWithData(""); EXPECT_TRUE(manager.IsSubscribed()); EXPECT_EQ(GetPrefService()->GetString( - ntp_snippets::prefs::kContentSuggestionsSubscriptionDataToken), + ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken), token); } @@ -83,33 +83,33 @@ RespondWithError(net::ERR_TIMED_OUT); EXPECT_FALSE(manager.IsSubscribed()); EXPECT_FALSE(GetPrefService()->HasPrefPath( - ntp_snippets::prefs::kContentSuggestionsSubscriptionDataToken)); + ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken)); } TEST_F(SubscriptionManagerTest, UnsubscribeSuccessfully) { std::string token = "1234567890"; GetPrefService()->SetString( - ntp_snippets::prefs::kContentSuggestionsSubscriptionDataToken, token); + ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken, token); SubscriptionManager manager(GetRequestContext(), GetPrefService(), GURL(url), GURL(url)); manager.Unsubscribe(token); RespondWithData(""); EXPECT_FALSE(manager.IsSubscribed()); EXPECT_FALSE(GetPrefService()->HasPrefPath( - ntp_snippets::prefs::kContentSuggestionsSubscriptionDataToken)); + ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken)); } TEST_F(SubscriptionManagerTest, UnsubscribeWithErrors) { std::string token = "1234567890"; GetPrefService()->SetString( - ntp_snippets::prefs::kContentSuggestionsSubscriptionDataToken, token); + ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken, token); SubscriptionManager manager(GetRequestContext(), GetPrefService(), GURL(url), GURL(url)); manager.Unsubscribe(token); RespondWithError(net::ERR_TIMED_OUT); EXPECT_TRUE(manager.IsSubscribed()); EXPECT_EQ(GetPrefService()->GetString( - ntp_snippets::prefs::kContentSuggestionsSubscriptionDataToken), + ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken), token); }
diff --git a/components/ntp_snippets/features.cc b/components/ntp_snippets/features.cc index d080397..f32adff 100644 --- a/components/ntp_snippets/features.cc +++ b/components/ntp_snippets/features.cc
@@ -18,7 +18,7 @@ &kBookmarkSuggestionsFeature, &kCategoryOrder, &kCategoryRanker, - &kContentSuggestionsPushFeature, + &kBreakingNewsPushFeature, &kForeignSessionsSuggestionsFeature, &kIncreasedVisibility, &kKeepPrefetchedContentSuggestions, @@ -46,8 +46,8 @@ const base::Feature kForeignSessionsSuggestionsFeature{ "NTPForeignSessionsSuggestions", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kContentSuggestionsPushFeature{ - "ContentSuggestionsPush", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kBreakingNewsPushFeature{"BreakingNewsPush", + base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kCategoryRanker{"ContentSuggestionsCategoryRanker", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/components/ntp_snippets/features.h b/components/ntp_snippets/features.h index be450632..83800fa15 100644 --- a/components/ntp_snippets/features.h +++ b/components/ntp_snippets/features.h
@@ -38,7 +38,7 @@ extern const base::Feature kIncreasedVisibility; // Feature to listen for GCM push updates from the server. -extern const base::Feature kContentSuggestionsPushFeature; +extern const base::Feature kBreakingNewsPushFeature; // Feature to choose a category ranker. extern const base::Feature kCategoryRanker;
diff --git a/components/ntp_snippets/pref_names.cc b/components/ntp_snippets/pref_names.cc index 13a2b615..1583914 100644 --- a/components/ntp_snippets/pref_names.cc +++ b/components/ntp_snippets/pref_names.cc
@@ -81,11 +81,11 @@ const char kClickBasedCategoryRankerLastDecayTime[] = "ntp_suggestions.click_based_category_ranker.last_decay_time"; -const char kContentSuggestionsSubscriptionDataToken[] = - "ntp_suggestions.content_suggestions_subscription_data.token"; +const char kBreakingNewsSubscriptionDataToken[] = + "ntp_suggestions.breaking_news_subscription_data.token"; -const char kContentSuggestionsGCMSubscriptionTokenCache[] = - "ntp_suggestions.content_suggestions_gcm_subscription_token_cache"; +const char kBreakingNewsGCMSubscriptionTokenCache[] = + "ntp_suggestions.breaking_news_gcm_subscription_token_cache"; } // namespace prefs } // namespace ntp_snippets
diff --git a/components/ntp_snippets/pref_names.h b/components/ntp_snippets/pref_names.h index 8dac4cd..75090cc 100644 --- a/components/ntp_snippets/pref_names.h +++ b/components/ntp_snippets/pref_names.h
@@ -90,23 +90,22 @@ // The pref name for the time when last click decay has happened. extern const char kClickBasedCategoryRankerLastDecayTime[]; -// kContentSuggestionsSubscriptionData* hold the data used when subscribing for -// content suggestions via GCM push updates. They are stored in pref such that -// in case of change (e.g. the token renders invalid), re-subscription is -// required. +// The folllowing prefs hold the data used when subscribing for content +// suggestions via GCM push updates. They are stored in pref such that in case +// of change (e.g. the token renders invalid), re-subscription is required. /////////////////////////////////////////////////////////////////////////////// // The pref name for the subscription token used when subscription for // breaking news push updates. -extern const char kContentSuggestionsSubscriptionDataToken[]; -//////////////////////// End of kContentSuggestionsSubscriptionData * +extern const char kBreakingNewsSubscriptionDataToken[]; +//////////////////////// End of breaking news subscription-related prefs. // The pref name for the subscription token received from the gcm server. As // recommended by the GCM team, it is cached in pref for faster bookkeeping to // see if subscription exists. This is pref holds the valid token even if // different from the one used for subscription. When they are different, Chrome // unsubscribes the old token from the content suggestions server, subscribe -// with the new one and update kContentSuggestionsSubscriptionDataToken. -extern const char kContentSuggestionsGCMSubscriptionTokenCache[]; +// with the new one and update kBreakingNewsSubscriptionDataToken. +extern const char kBreakingNewsGCMSubscriptionTokenCache[]; } // namespace prefs } // namespace ntp_snippets
diff --git a/components/ntp_tiles/metrics.cc b/components/ntp_tiles/metrics.cc index f657ced1..4064c15 100644 --- a/components/ntp_tiles/metrics.cc +++ b/components/ntp_tiles/metrics.cc
@@ -85,46 +85,45 @@ } // namespace -void RecordPageImpression(const std::vector<TileImpression>& tiles, +void RecordPageImpression(int number_of_tiles) { + UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.NumberOfTiles", number_of_tiles); +} + +void RecordTileImpression(int index, + TileSource source, + TileVisualType type, + const GURL& url, rappor::RapporService* rappor_service) { - UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.NumberOfTiles", tiles.size()); + UMA_HISTOGRAM_ENUMERATION("NewTabPage.SuggestionsImpression", index, + kMaxNumTiles); - for (int index = 0; index < static_cast<int>(tiles.size()); index++) { - TileSource source = tiles[index].source; - TileVisualType tile_type = tiles[index].type; + std::string source_name = GetSourceHistogramName(source); + std::string impression_histogram = base::StringPrintf( + "NewTabPage.SuggestionsImpression.%s", source_name.c_str()); + LogHistogramEvent(impression_histogram, index, kMaxNumTiles); - UMA_HISTOGRAM_ENUMERATION("NewTabPage.SuggestionsImpression", index, - kMaxNumTiles); + if (type > LAST_RECORDED_TILE_TYPE) { + return; + } - std::string source_name = GetSourceHistogramName(source); - std::string impression_histogram = base::StringPrintf( - "NewTabPage.SuggestionsImpression.%s", source_name.c_str()); - LogHistogramEvent(impression_histogram, index, kMaxNumTiles); + UMA_HISTOGRAM_ENUMERATION("NewTabPage.TileType", type, + LAST_RECORDED_TILE_TYPE + 1); - if (tile_type > LAST_RECORDED_TILE_TYPE) { - continue; - } + std::string tile_type_histogram = + base::StringPrintf("NewTabPage.TileType.%s", source_name.c_str()); + LogHistogramEvent(tile_type_histogram, type, LAST_RECORDED_TILE_TYPE + 1); - UMA_HISTOGRAM_ENUMERATION("NewTabPage.TileType", tile_type, - LAST_RECORDED_TILE_TYPE + 1); + const char* tile_type_suffix = GetTileTypeSuffix(type); + if (tile_type_suffix) { + // Note: This handles a null |rappor_service|. + rappor::SampleDomainAndRegistryFromGURL( + rappor_service, + base::StringPrintf("NTP.SuggestionsImpressions.%s", tile_type_suffix), + url); - std::string tile_type_histogram = - base::StringPrintf("NewTabPage.TileType.%s", source_name.c_str()); - LogHistogramEvent(tile_type_histogram, tile_type, - LAST_RECORDED_TILE_TYPE + 1); - - const char* tile_type_suffix = GetTileTypeSuffix(tile_type); - if (tile_type_suffix) { - // Note: This handles a null |rappor_service|. - rappor::SampleDomainAndRegistryFromGURL( - rappor_service, - base::StringPrintf("NTP.SuggestionsImpressions.%s", tile_type_suffix), - tiles[index].url); - - std::string icon_impression_histogram = base::StringPrintf( - "NewTabPage.SuggestionsImpression.%s", tile_type_suffix); - LogHistogramEvent(icon_impression_histogram, index, kMaxNumTiles); - } + std::string icon_impression_histogram = base::StringPrintf( + "NewTabPage.SuggestionsImpression.%s", tile_type_suffix); + LogHistogramEvent(icon_impression_histogram, index, kMaxNumTiles); } }
diff --git a/components/ntp_tiles/metrics.h b/components/ntp_tiles/metrics.h index 187d719..eb0bf2d2 100644 --- a/components/ntp_tiles/metrics.h +++ b/components/ntp_tiles/metrics.h
@@ -19,19 +19,16 @@ namespace ntp_tiles { namespace metrics { -struct TileImpression { - TileImpression(TileSource source, TileVisualType type, const GURL& url) - : source(source), type(type), url(url) {} - - TileSource source; - TileVisualType type; - GURL url; -}; - // Records an NTP impression, after all tiles have loaded. -// Includes the visual types (see above) of all visible tiles. If -// |rappor_service| is null, no rappor metrics will be reported. -void RecordPageImpression(const std::vector<TileImpression>& tiles, +void RecordPageImpression(int number_of_tiles); + +// Records a tile impression at |index| (zero based) created by |source|. This +// should be called only after the visual |type| of the tile has been +// determined. If |rappor_service| is null, no rappor metrics will be reported. +void RecordTileImpression(int index, + TileSource source, + TileVisualType type, + const GURL& url, rappor::RapporService* rappor_service); // Records a click on a tile.
diff --git a/components/ntp_tiles/metrics_unittest.cc b/components/ntp_tiles/metrics_unittest.cc index 4b5eac9a..dbbe4c1 100644 --- a/components/ntp_tiles/metrics_unittest.cc +++ b/components/ntp_tiles/metrics_unittest.cc
@@ -22,19 +22,33 @@ using testing::ElementsAre; using testing::IsEmpty; -TEST(RecordPageImpressionTest, ShouldRecordUmaForIcons) { +TEST(RecordPageImpressionTest, ShouldRecordNumberOfTiles) { base::HistogramTester histogram_tester; - RecordPageImpression({{TileSource::TOP_SITES, ICON_REAL, GURL()}, - {TileSource::TOP_SITES, ICON_REAL, GURL()}, - {TileSource::TOP_SITES, ICON_REAL, GURL()}, - {TileSource::TOP_SITES, ICON_COLOR, GURL()}, - {TileSource::TOP_SITES, ICON_COLOR, GURL()}, - {TileSource::SUGGESTIONS_SERVICE, ICON_REAL, GURL()}, - {TileSource::SUGGESTIONS_SERVICE, ICON_DEFAULT, GURL()}, - {TileSource::POPULAR, ICON_COLOR, GURL()}}, - /*rappor_service=*/nullptr); + RecordPageImpression(5); EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.NumberOfTiles"), - ElementsAre(base::Bucket(/*min=*/8, /*count=*/1))); + ElementsAre(base::Bucket(/*min=*/5, /*count=*/1))); +} + +TEST(RecordTileImpressionTest, ShouldRecordUmaForIcons) { + base::HistogramTester histogram_tester; + + RecordTileImpression(0, TileSource::TOP_SITES, ICON_REAL, GURL(), + /*rappor_service=*/nullptr); + RecordTileImpression(1, TileSource::TOP_SITES, ICON_REAL, GURL(), + /*rappor_service=*/nullptr); + RecordTileImpression(2, TileSource::TOP_SITES, ICON_REAL, GURL(), + /*rappor_service=*/nullptr); + RecordTileImpression(3, TileSource::TOP_SITES, ICON_COLOR, GURL(), + /*rappor_service=*/nullptr); + RecordTileImpression(4, TileSource::TOP_SITES, ICON_COLOR, GURL(), + /*rappor_service=*/nullptr); + RecordTileImpression(5, TileSource::SUGGESTIONS_SERVICE, ICON_REAL, GURL(), + /*rappor_service=*/nullptr); + RecordTileImpression(6, TileSource::SUGGESTIONS_SERVICE, ICON_DEFAULT, GURL(), + /*rappor_service=*/nullptr); + RecordTileImpression(7, TileSource::POPULAR, ICON_COLOR, GURL(), + /*rappor_service=*/nullptr); + EXPECT_THAT( histogram_tester.GetAllSamples("NewTabPage.SuggestionsImpression"), ElementsAre(base::Bucket(/*min=*/0, /*count=*/1), @@ -88,14 +102,16 @@ ElementsAre(base::Bucket(/*min=*/6, /*count=*/1))); } -TEST(RecordPageImpressionTest, ShouldRecordUmaForThumbnails) { +TEST(RecordTileImpressionTest, ShouldRecordUmaForThumbnails) { base::HistogramTester histogram_tester; - RecordPageImpression({{TileSource::TOP_SITES, THUMBNAIL_FAILED, GURL()}, - {TileSource::SUGGESTIONS_SERVICE, THUMBNAIL, GURL()}, - {TileSource::POPULAR, THUMBNAIL, GURL()}}, + + RecordTileImpression(0, TileSource::TOP_SITES, THUMBNAIL_FAILED, GURL(), /*rappor_service=*/nullptr); - EXPECT_THAT(histogram_tester.GetAllSamples("NewTabPage.NumberOfTiles"), - ElementsAre(base::Bucket(/*min=*/3, /*count=*/1))); + RecordTileImpression(1, TileSource::SUGGESTIONS_SERVICE, THUMBNAIL, GURL(), + /*rappor_service=*/nullptr); + RecordTileImpression(2, TileSource::POPULAR, THUMBNAIL, GURL(), + /*rappor_service=*/nullptr); + EXPECT_THAT( histogram_tester.GetAllSamples("NewTabPage.SuggestionsImpression"), ElementsAre(base::Bucket(/*min=*/0, /*count=*/1), @@ -216,14 +232,15 @@ IsEmpty()); } -TEST(RecordPageImpressionTest, ShouldRecordRappor) { +TEST(RecordTileImpressionTest, ShouldRecordRappor) { rappor::TestRapporServiceImpl rappor_service; - RecordPageImpression( - {{TileSource::TOP_SITES, ICON_REAL, GURL("http://www.site1.com/")}, - {TileSource::TOP_SITES, ICON_COLOR, GURL("http://www.site2.com/")}, - {TileSource::TOP_SITES, ICON_DEFAULT, GURL("http://www.site3.com/")}}, - &rappor_service); + RecordTileImpression(0, TileSource::TOP_SITES, ICON_REAL, + GURL("http://www.site1.com/"), &rappor_service); + RecordTileImpression(1, TileSource::TOP_SITES, ICON_COLOR, + GURL("http://www.site2.com/"), &rappor_service); + RecordTileImpression(2, TileSource::TOP_SITES, ICON_DEFAULT, + GURL("http://www.site3.com/"), &rappor_service); EXPECT_EQ(3, rappor_service.GetReportsCount()); @@ -255,13 +272,13 @@ } } -TEST(RecordPageImpressionTest, ShouldNotRecordRapporForUnknownTileType) { +TEST(RecordTileImpressionTest, ShouldNotRecordRapporForUnknownTileType) { rappor::TestRapporServiceImpl rappor_service; - RecordPageImpression( - {{TileSource::TOP_SITES, ICON_REAL, GURL("http://www.s1.com/")}, - {TileSource::TOP_SITES, UNKNOWN_TILE_TYPE, GURL("http://www.s2.com/")}}, - &rappor_service); + RecordTileImpression(0, TileSource::TOP_SITES, ICON_REAL, + GURL("http://www.s1.com/"), &rappor_service); + RecordTileImpression(1, TileSource::TOP_SITES, UNKNOWN_TILE_TYPE, + GURL("http://www.s2.com/"), &rappor_service); // Unknown tile type shouldn't get reported. EXPECT_EQ(1, rappor_service.GetReportsCount());
diff --git a/components/printing/renderer/print_web_view_helper.cc b/components/printing/renderer/print_web_view_helper.cc index 21814d2..b740f5b 100644 --- a/components/printing/renderer/print_web_view_helper.cc +++ b/components/printing/renderer/print_web_view_helper.cc
@@ -581,7 +581,15 @@ blink::WebView::Create(nullptr, blink::kWebPageVisibilityStateVisible); web_view->GetSettings()->SetJavaScriptEnabled(true); - blink::WebFrameClient frame_client; + class HeaderAndFooterClient final : public blink::WebFrameClient { + public: + void FrameDetached(blink::WebLocalFrame* frame, + DetachType detach_type) override { + frame->FrameWidget()->Close(); + frame->Close(); + } + }; + HeaderAndFooterClient frame_client; blink::WebLocalFrame* frame = blink::WebLocalFrame::Create( blink::WebTreeScopeType::kDocument, &frame_client, nullptr, nullptr); web_view->SetMainFrame(frame); @@ -680,6 +688,8 @@ blink::WebSandboxFlags sandbox_flags, const blink::WebParsedFeaturePolicy& container_policy, const blink::WebFrameOwnerProperties& frame_owner_properties) override; + void FrameDetached(blink::WebLocalFrame* frame, + DetachType detach_type) override; std::unique_ptr<blink::WebURLLoader> CreateURLLoader() override; void CallOnReady(); @@ -848,6 +858,12 @@ return nullptr; } +void PrepareFrameAndViewForPrint::FrameDetached(blink::WebLocalFrame* frame, + DetachType detach_type) { + frame->FrameWidget()->Close(); + frame->Close(); +} + std::unique_ptr<blink::WebURLLoader> PrepareFrameAndViewForPrint::CreateURLLoader() { // TODO(yhirano): Stop using Platform::CreateURLLoader() here. @@ -887,7 +903,6 @@ if (owns_web_view_) { DCHECK(!frame->IsLoading()); owns_web_view_ = false; - frame->FrameWidget()->Close(); web_view->Close(); } }
diff --git a/content/browser/loader/DEPS b/content/browser/loader/DEPS index 51d8fdb..c6e43ce 100644 --- a/content/browser/loader/DEPS +++ b/content/browser/loader/DEPS
@@ -165,6 +165,7 @@ "+content/browser/streams/stream_registry.h", "+content/common/content_export.h", "+content/common/net/url_request_service_worker_data.h", + "+content/common/site_isolation_policy.h", "+content/public/browser/browser_thread.h", "+content/public/browser/navigation_ui_data.h", "+content/public/browser/plugin_service.h",
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index 548a9af..05d2f2cd 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -78,6 +78,7 @@ #include "content/common/resource_request.h" #include "content/common/resource_request_body_impl.h" #include "content/common/resource_request_completion_status.h" +#include "content/common/site_isolation_policy.h" #include "content/common/view_messages.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/global_request_id.h" @@ -168,6 +169,9 @@ // The interval for calls to ResourceDispatcherHostImpl::UpdateLoadStates const int kUpdateLoadStatesIntervalMsec = 250; +// The interval for calls to RecordOutstandingRequestsStats. +const int kRecordOutstandingRequestsStatsIntervalSec = 60; + // Maximum byte "cost" of all the outstanding requests for a renderer. // See declaration of |max_outstanding_requests_cost_per_process_| for details. // This bound is 25MB, which allows for around 6000 outstanding requests. @@ -360,7 +364,16 @@ FROM_HERE, base::Bind(&ResourceDispatcherHostImpl::OnInit, base::Unretained(this))); - update_load_states_timer_.reset(new base::RepeatingTimer()); + update_load_states_timer_ = base::MakeUnique<base::RepeatingTimer>(); + + // Monitor per-tab outstanding requests only if OOPIF is not enabled, because + // the routing id doesn't represent tabs in OOPIF modes. + if (!SiteIsolationPolicy::UseDedicatedProcessesForAllSites() && + !SiteIsolationPolicy::IsTopDocumentIsolationEnabled() && + !SiteIsolationPolicy::AreIsolatedOriginsEnabled()) { + record_outstanding_requests_stats_timer_ = + base::MakeUnique<base::RepeatingTimer>(); + } } // The default ctor is only used by unittests. It is reasonable to assume that @@ -371,6 +384,7 @@ ResourceDispatcherHostImpl::~ResourceDispatcherHostImpl() { DCHECK(outstanding_requests_stats_map_.empty()); + DCHECK(outstanding_requests_per_tab_map_.empty()); DCHECK(g_resource_dispatcher_host); DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); g_resource_dispatcher_host = NULL; @@ -589,13 +603,20 @@ } void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) { - // Make sure we have the load state monitor running. + // Make sure we have the load state monitors running. if (!update_load_states_timer_->IsRunning() && scheduler_->HasLoadingClients()) { update_load_states_timer_->Start( FROM_HERE, TimeDelta::FromMilliseconds(kUpdateLoadStatesIntervalMsec), this, &ResourceDispatcherHostImpl::UpdateLoadInfo); } + if (record_outstanding_requests_stats_timer_ && + !record_outstanding_requests_stats_timer_->IsRunning()) { + record_outstanding_requests_stats_timer_->Start( + FROM_HERE, + TimeDelta::FromSeconds(kRecordOutstandingRequestsStatsIntervalSec), + this, &ResourceDispatcherHostImpl::RecordOutstandingRequestsStats); + } } void ResourceDispatcherHostImpl::DidReceiveRedirect( @@ -784,10 +805,11 @@ is_shutdown_ = true; pending_loaders_.clear(); - // Make sure we shutdown the timer now, otherwise by the time our destructor + // Make sure we shutdown the timers now, otherwise by the time our destructor // runs if the timer is still running the Task is deleted twice (once by // the MessageLoop and the second time by RepeatingTimer). update_load_states_timer_.reset(); + record_outstanding_requests_stats_timer_.reset(); // Clear blocked requests if any left. // Note that we have to do this in 2 passes as we cannot call @@ -1919,6 +1941,18 @@ outstanding_requests_stats_map_[info.GetChildID()] = stats; } +void ResourceDispatcherHostImpl::IncrementOutstandingRequestsPerTab( + int count, + const ResourceRequestInfoImpl& info) { + auto key = std::make_pair(info.GetChildID(), info.GetRouteID()); + OutstandingRequestsPerTabMap::iterator entry = + outstanding_requests_per_tab_map_.insert(std::make_pair(key, 0)).first; + entry->second += count; + DCHECK_GE(entry->second, 0); + if (entry->second == 0) + outstanding_requests_per_tab_map_.erase(entry); +} + ResourceDispatcherHostImpl::OustandingRequestsStats ResourceDispatcherHostImpl::IncrementOutstandingRequestsMemory( int count, @@ -1954,6 +1988,8 @@ DCHECK_GE(stats.num_requests, 0); UpdateOutstandingRequestsStats(*info, stats); + IncrementOutstandingRequestsPerTab(count, *info); + if (num_in_flight_requests_ > largest_outstanding_request_count_seen_) { largest_outstanding_request_count_seen_ = num_in_flight_requests_; UMA_HISTOGRAM_COUNTS_1M( @@ -1969,6 +2005,14 @@ largest_outstanding_request_per_process_count_seen_); } + if (num_in_flight_requests_ > peak_outstanding_request_count_) + peak_outstanding_request_count_ = num_in_flight_requests_; + + if (HasRequestsFromMultipleActiveTabs() && + num_in_flight_requests_ > peak_outstanding_request_count_multitab_) { + peak_outstanding_request_count_multitab_ = num_in_flight_requests_; + } + return stats; } @@ -2498,6 +2542,23 @@ base::Bind(UpdateLoadStateOnUI, loader_delegate_, base::Passed(&infos))); } +void ResourceDispatcherHostImpl::RecordOutstandingRequestsStats() { + if (peak_outstanding_request_count_ != 0) { + UMA_HISTOGRAM_COUNTS_1M( + "Net.ResourceDispatcherHost.PeakOutstandingRequests", + peak_outstanding_request_count_); + peak_outstanding_request_count_ = num_in_flight_requests_; + } + + if (peak_outstanding_request_count_multitab_ != 0) { + UMA_HISTOGRAM_COUNTS_1M( + "Net.ResourceDispatcherHost.PeakOutstandingRequests.MultiTabLoading", + peak_outstanding_request_count_multitab_); + peak_outstanding_request_count_multitab_ = + HasRequestsFromMultipleActiveTabs() ? num_in_flight_requests_ : 0; + } +} + void ResourceDispatcherHostImpl::BlockRequestsForRoute( const GlobalFrameRoutingId& global_routing_id) { DCHECK(io_thread_task_runner_->BelongsToCurrentThread()); @@ -2707,4 +2768,20 @@ return handler; } +bool ResourceDispatcherHostImpl::HasRequestsFromMultipleActiveTabs() { + if (outstanding_requests_per_tab_map_.size() < 2) + return false; + + int active_tabs = 0; + for (auto iter = outstanding_requests_per_tab_map_.begin(); + iter != outstanding_requests_per_tab_map_.end(); ++iter) { + if (iter->second > 2) { + active_tabs++; + if (active_tabs >= 2) + return true; + } + } + return false; +} + } // namespace content
diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h index 3f5aa95..70f377e 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.h +++ b/content/browser/loader/resource_dispatcher_host_impl.h
@@ -457,6 +457,13 @@ int count, ResourceRequestInfoImpl* info); + // Called from IncrementOutstandingRequestsCount to update the per-tab + // request stats in |outstanding_requests_per_tab_map_|. + // TODO(ksakamoto): This is just for temporary metrics collection for the + // Loading Dispatcher v0 (crbug.com/723233), and will be removed soon. + void IncrementOutstandingRequestsPerTab(int count, + const ResourceRequestInfoImpl& info); + // Estimate how much heap space |request| will consume to run. static int CalculateApproximateMemoryCost(net::URLRequest* request); @@ -513,6 +520,10 @@ // Checks all pending requests and updates the load info if necessary. void UpdateLoadInfo(); + // Records statistics about outstanding requests since the last call, and + // reset the stats. + void RecordOutstandingRequestsStats(); + // Resumes or cancels (if |cancel_requests| is true) any blocked requests. void ProcessBlockedRequestsForRoute( const GlobalFrameRoutingId& global_routing_id, @@ -695,6 +706,10 @@ bool must_download, bool is_new_request); + // Returns true if there are two or more tabs that are not network 2-quiet + // (i.e. have at least three outstanding requests). + bool HasRequestsFromMultipleActiveTabs(); + LoaderMap pending_loaders_; // Collection of temp files downloaded for child processes via @@ -710,6 +725,10 @@ // not empty and at least one RenderViewHost is loading. std::unique_ptr<base::RepeatingTimer> update_load_states_timer_; + // A timer that periodically calls RecordOutstandingRequestsStats. + std::unique_ptr<base::RepeatingTimer> + record_outstanding_requests_stats_timer_; + // Request ID for browser initiated requests. request_ids generated by // child processes are counted up from 0, while browser created requests // start at -2 and go down from there. (We need to start at -2 because -1 is @@ -732,6 +751,14 @@ typedef std::map<int, OustandingRequestsStats> OutstandingRequestsStatsMap; OutstandingRequestsStatsMap outstanding_requests_stats_map_; + // Maps (child_id, route_id) to the number of outstanding requests. + // Used only when OOPIF is not enabled, since in OOPIF modes routing_id + // doesn't represent tabs. + // TODO(ksakamoto): This is just for temporary metrics collection for the + // Loading Dispatcher v0 (crbug.com/723233), and will be removed soon. + typedef std::map<std::pair<int, int>, int> OutstandingRequestsPerTabMap; + OutstandingRequestsPerTabMap outstanding_requests_per_tab_map_; + // |num_in_flight_requests_| is the total number of requests currently issued // summed across all renderers. int num_in_flight_requests_; @@ -763,6 +790,15 @@ // Largest number of outstanding requests seen so far in any single process. int largest_outstanding_request_per_process_count_seen_; + // Largest number of outstanding requests seen since the last call to + // RecordOutstandingRequestsStats. + int peak_outstanding_request_count_ = 0; + + // Largest number of outstanding requests seen while there are outstanding + // requests from two or more tabs, since the last call to + // RecordOutstandingRequestsStats. + int peak_outstanding_request_count_multitab_ = 0; + // Time of the last user gesture. Stored so that we can add a load // flag to requests occurring soon after a gesture to indicate they // may be because of explicit user action.
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 52ddbab..617f484 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -988,8 +988,6 @@ } if (browser_plugin_embedder_) browser_plugin_embedder_->CancelGuestDialogs(); - if (delegate_) - delegate_->HideValidationMessage(this); } void WebContentsImpl::ClosePage() { @@ -4696,6 +4694,9 @@ // Cancel any visible dialogs so they are not left dangling over the sad tab. CancelActiveAndPendingDialogs(); + if (delegate_) + delegate_->HideValidationMessage(this); + audio_stream_monitor_.RenderProcessGone(rvh->GetProcess()->GetID()); // Reset the loading progress. TODO(avi): What does it mean to have a
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc index fea1eb6..2f161b01 100644 --- a/content/browser/web_contents/web_contents_impl_browsertest.cc +++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -1467,78 +1467,4 @@ wc->SetJavaScriptDialogManagerForTesting(nullptr); } -class FormBubbleDelegate : public WebContentsDelegate { - public: - FormBubbleDelegate() = default; - - void WaitUntilShown() { - while (!is_visible_) { - message_loop_runner_ = new MessageLoopRunner; - message_loop_runner_->Run(); - } - } - - void WaitUntilHidden() { - while (is_visible_) { - message_loop_runner_ = new MessageLoopRunner; - message_loop_runner_->Run(); - } - } - - private: - void ShowValidationMessage(WebContents* web_contents, - const gfx::Rect& anchor_in_root_view, - const base::string16& main_text, - const base::string16& sub_text) override { - is_visible_ = true; - if (message_loop_runner_) - message_loop_runner_->Quit(); - } - - void HideValidationMessage(WebContents* web_contents) override { - is_visible_ = false; - if (message_loop_runner_) - message_loop_runner_->Quit(); - } - - bool is_visible_ = false; - scoped_refptr<MessageLoopRunner> message_loop_runner_; -}; - -IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, - NavigationHidesFormValidationBubble) { - ASSERT_TRUE(embedded_test_server()->Start()); - EXPECT_TRUE(NavigateToURL( - shell(), embedded_test_server()->GetURL("a.com", "/title1.html"))); - - // Start listening for requests to show or hide the form validation bubble. - WebContentsImpl* web_contents = - static_cast<WebContentsImpl*>(shell()->web_contents()); - FormBubbleDelegate bubble_delegate; - web_contents->SetDelegate(&bubble_delegate); - - // Trigger a form validation bubble and verify that the bubble is shown. - std::string script = R"( - var input_field = document.createElement('input'); - input_field.required = true; - var form = document.createElement('form'); - form.appendChild(input_field); - document.body.appendChild(form); - - setTimeout(function() { - input_field.setCustomValidity('Custom validity message'); - input_field.reportValidity(); - }, - 0); - )"; - ASSERT_TRUE(ExecuteScript(web_contents, script)); - bubble_delegate.WaitUntilShown(); - - // Navigate to another page and verify that the form validation bubble is - // hidden. - EXPECT_TRUE(NavigateToURL( - shell(), embedded_test_server()->GetURL("b.com", "/title2.html"))); - bubble_delegate.WaitUntilHidden(); -} - } // namespace content
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index 4d9cae32..0fc9075 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -382,8 +382,6 @@ (ProceduralBlock)callback; // Shows the Sync encryption passphrase (part of Settings). - (void)showSyncEncryptionPassphrase; -// Shows the Native Apps Settings UI (part of Settings). -- (void)showNativeAppsSettings; // Shows the Clear Browsing Data Settings UI (part of Settings). - (void)showClearBrowsingDataSettingsController; // Shows the Contextual search UI (part of Settings). @@ -1471,9 +1469,6 @@ case IDC_RESET_ALL_WEBVIEWS: [self.currentBVC resetAllWebViews]; break; - case IDC_SHOW_GOOGLE_APPS_SETTINGS: - [self showNativeAppsSettings]; - break; case IDC_SHOW_CLEAR_BROWSING_DATA_SETTINGS: [self showClearBrowsingDataSettingsController]; break; @@ -2143,18 +2138,6 @@ } copy]; } -- (void)showNativeAppsSettings { - if (_settingsNavigationController) - return; - _settingsNavigationController = - [SettingsNavigationController newNativeAppsController:_mainBrowserState - delegate:self]; - [[self topPresentedViewController] - presentViewController:_settingsNavigationController - animated:YES - completion:nil]; -} - - (void)closeSettingsAnimated:(BOOL)animated completion:(ProceduralBlock)completion { DCHECK(_settingsNavigationController);
diff --git a/ios/chrome/browser/content_suggestions/content_suggestions_mediator.mm b/ios/chrome/browser/content_suggestions/content_suggestions_mediator.mm index ccc45c18..e0dc77209 100644 --- a/ios/chrome/browser/content_suggestions/content_suggestions_mediator.mm +++ b/ios/chrome/browser/content_suggestions/content_suggestions_mediator.mm
@@ -431,7 +431,7 @@ if (mostVisited.size() && !self.recordedPageImpression) { self.recordedPageImpression = YES; - RecordPageImpression(mostVisited); + RecordImpression(mostVisited); } }
diff --git a/ios/chrome/browser/content_suggestions/mediator_util.h b/ios/chrome/browser/content_suggestions/mediator_util.h index 74cc22e2..f75d042 100644 --- a/ios/chrome/browser/content_suggestions/mediator_util.h +++ b/ios/chrome/browser/content_suggestions/mediator_util.h
@@ -61,8 +61,8 @@ // Creates and returns a SectionInfo for the Most Visited section. ContentSuggestionsSectionInformation* MostVisitedSectionInformation(); -// Records the page impression of the ntp tiles. -void RecordPageImpression(const std::vector<ntp_tiles::NTPTile>& mostVisited); +// Records the impression of the NTP and of all |mostVisited| tiles. +void RecordImpression(const std::vector<ntp_tiles::NTPTile>& mostVisited); // Converts a ntp_tiles::NTPTile |tile| to a ContentSuggestionsMostVisitedItem // with a |sectionInfo|.
diff --git a/ios/chrome/browser/content_suggestions/mediator_util.mm b/ios/chrome/browser/content_suggestions/mediator_util.mm index 3e02880e..53638396 100644 --- a/ios/chrome/browser/content_suggestions/mediator_util.mm +++ b/ios/chrome/browser/content_suggestions/mediator_util.mm
@@ -124,14 +124,14 @@ return sectionInfo; } -void RecordPageImpression(const ntp_tiles::NTPTilesVector& mostVisited) { - std::vector<ntp_tiles::metrics::TileImpression> tiles; +void RecordImpression(const ntp_tiles::NTPTilesVector& mostVisited) { + int index = 0; for (const ntp_tiles::NTPTile& ntpTile : mostVisited) { - tiles.emplace_back(ntpTile.source, ntp_tiles::UNKNOWN_TILE_TYPE, - ntpTile.url); + ntp_tiles::metrics::RecordTileImpression( + index++, ntpTile.source, ntp_tiles::UNKNOWN_TILE_TYPE, ntpTile.url, + GetApplicationContext()->GetRapporServiceImpl()); } - ntp_tiles::metrics::RecordPageImpression( - tiles, GetApplicationContext()->GetRapporServiceImpl()); + ntp_tiles::metrics::RecordPageImpression(mostVisited.size()); } ContentSuggestionsMostVisitedItem* ConvertNTPTile(
diff --git a/ios/chrome/browser/ui/commands/ios_command_ids.h b/ios/chrome/browser/ui/commands/ios_command_ids.h index 4c3115d..751932e6 100644 --- a/ios/chrome/browser/ui/commands/ios_command_ids.h +++ b/ios/chrome/browser/ui/commands/ios_command_ids.h
@@ -58,7 +58,6 @@ #define IDC_RESET_ALL_WEBVIEWS 40928 #define IDC_SHARE_PAGE 40929 #define IDC_BACK_FORWARD_IN_TAB_HISTORY 40930 -#define IDC_SHOW_GOOGLE_APPS_SETTINGS 40931 #define IDC_SHOW_PRIVACY_SETTINGS 40934 #define IDC_HIDE_SETTINGS_AND_SHOW_PRIVACY_SETTINGS 40935 #define IDC_REPORT_AN_ISSUE 40936
diff --git a/ios/chrome/browser/ui/ntp/google_landing_mediator.mm b/ios/chrome/browser/ui/ntp/google_landing_mediator.mm index 72227e7..0cebfb3 100644 --- a/ios/chrome/browser/ui/ntp/google_landing_mediator.mm +++ b/ios/chrome/browser/ui/ntp/google_landing_mediator.mm
@@ -259,13 +259,13 @@ if (data.size() && !_recordedPageImpression) { _recordedPageImpression = YES; - std::vector<ntp_tiles::metrics::TileImpression> tiles; + int index = 0; for (const ntp_tiles::NTPTile& ntpTile : data) { - tiles.emplace_back(ntpTile.source, ntp_tiles::UNKNOWN_TILE_TYPE, - ntpTile.url); + ntp_tiles::metrics::RecordTileImpression( + index++, ntpTile.source, ntp_tiles::UNKNOWN_TILE_TYPE, ntpTile.url, + GetApplicationContext()->GetRapporServiceImpl()); } - ntp_tiles::metrics::RecordPageImpression( - tiles, GetApplicationContext()->GetRapporServiceImpl()); + ntp_tiles::metrics::RecordPageImpression(data.size()); } }
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn index 6ae3b8d..8638120 100644 --- a/ios/chrome/browser/ui/settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -65,9 +65,6 @@ "import_data_collection_view_controller.mm", "material_cell_catalog_view_controller.h", "material_cell_catalog_view_controller.mm", - "native_apps_collection_view_controller.h", - "native_apps_collection_view_controller.mm", - "native_apps_collection_view_controller_private.h", "password_details_collection_view_controller.h", "password_details_collection_view_controller.mm", "physical_web_collection_view_controller.h", @@ -151,7 +148,6 @@ "//ios/chrome/browser/prefs", "//ios/chrome/browser/search_engines", "//ios/chrome/browser/signin", - "//ios/chrome/browser/store_kit", "//ios/chrome/browser/sync", "//ios/chrome/browser/translate", "//ios/chrome/browser/ui", @@ -198,7 +194,6 @@ libs = [ "CoreLocation.framework", "LocalAuthentication.framework", - "StoreKit.framework", "UIKit.framework", ] } @@ -256,7 +251,6 @@ "dataplan_usage_collection_view_controller_unittest.mm", "do_not_track_collection_view_controller_unittest.mm", "import_data_collection_view_controller_unittest.mm", - "native_apps_collection_view_controller_unittest.mm", "password_details_collection_view_controller_unittest.mm", "physical_web_collection_view_controller_unittest.mm", "privacy_collection_view_controller_unittest.mm",
diff --git a/ios/chrome/browser/ui/settings/cells/BUILD.gn b/ios/chrome/browser/ui/settings/cells/BUILD.gn index de546429..37b2570 100644 --- a/ios/chrome/browser/ui/settings/cells/BUILD.gn +++ b/ios/chrome/browser/ui/settings/cells/BUILD.gn
@@ -18,8 +18,6 @@ "encryption_item.mm", "import_data_multiline_detail_cell.h", "import_data_multiline_detail_cell.mm", - "native_app_item.h", - "native_app_item.mm", "passphrase_error_item.h", "passphrase_error_item.mm", "password_details_item.h", @@ -56,7 +54,6 @@ "copied_to_chrome_item_unittest.mm", "encryption_item_unittest.mm", "import_data_multiline_detail_cell_unittest.mm", - "native_app_item_unittest.mm", "passphrase_error_item_unittest.mm", "password_details_item_unittest.mm", "sync_switch_item_unittest.mm",
diff --git a/ios/chrome/browser/ui/settings/cells/native_app_item.h b/ios/chrome/browser/ui/settings/cells/native_app_item.h deleted file mode 100644 index b03afcf..0000000 --- a/ios/chrome/browser/ui/settings/cells/native_app_item.h +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_CELLS_NATIVE_APP_ITEM_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_CELLS_NATIVE_APP_ITEM_H_ - -#import <UIKit/UIKit.h> - -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" -#import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h" - -@class MDCButton; - -typedef NS_ENUM(NSInteger, NativeAppItemState) { - NativeAppItemSwitchOff, - NativeAppItemSwitchOn, - NativeAppItemInstall, -}; - -// Item to display and interact with a Native App. -@interface NativeAppItem : CollectionViewItem - -// The display name of the app. -@property(nonatomic, copy) NSString* name; - -// The icon of the app. -@property(nonatomic, strong) UIImage* icon; - -// The state of the item: -// - NativeAppItemSwitchOff: displays a switch set to OFF; -// - NativeAppItemSwitchOn: displays a switch set to ON; -// - NativeAppItemInstall: displays an INSTALL button; -@property(nonatomic, assign) NativeAppItemState state; - -@end - -// Cell class associated to NativeAppItem. -@interface NativeAppCell : MDCCollectionViewCell - -// Label for the app name. -@property(nonatomic, strong, readonly) UILabel* nameLabel; - -// Image view for the app icon. -@property(nonatomic, strong, readonly) UIImageView* iconImageView; - -// Accessory controls. switchControl is available after calling -// -updateWithState: with NativeAppItemSwitch{On|Off}, while installButton is -// available after calling -updateWithState: with NativeAppItemInstall. -@property(nonatomic, strong, readonly) UISwitch* switchControl; -@property(nonatomic, strong, readonly) MDCButton* installButton; - -// Updates the accessory view according to the given |state|. -- (void)updateWithState:(NativeAppItemState)state; - -@end - -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_CELLS_NATIVE_APP_ITEM_H_
diff --git a/ios/chrome/browser/ui/settings/cells/native_app_item.mm b/ios/chrome/browser/ui/settings/cells/native_app_item.mm deleted file mode 100644 index c0c0d3f..0000000 --- a/ios/chrome/browser/ui/settings/cells/native_app_item.mm +++ /dev/null
@@ -1,192 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/settings/cells/native_app_item.h" - -#import <QuartzCore/QuartzCore.h> - -#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" -#include "ios/chrome/grit/ios_strings.h" -#import "ios/third_party/material_components_ios/src/components/Buttons/src/MaterialButtons.h" -#import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" -#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" -#include "ui/base/l10n/l10n_util_mac.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { - -// Padding used on the leading and trailing edges of the cell. -const CGFloat kHorizontalPadding = 16; - -// Icon rounded corner radius. -const CGFloat kIconCornerRadius = 5.088; - -// Icon size. -const CGFloat kIconSize = 29; - -// Placeholder icon for native app cells. -UIImage* PlaceholderIcon() { - return [UIImage imageNamed:@"app_icon_placeholder"]; -} - -} // namespace - -@implementation NativeAppItem - -@synthesize name = _name; -@synthesize icon = _icon; -@synthesize state = _state; - -- (instancetype)initWithType:(NSInteger)type { - self = [super initWithType:type]; - if (self) { - self.cellClass = [NativeAppCell class]; - } - return self; -} - -#pragma mark CollectionViewItem - -- (void)configureCell:(NativeAppCell*)cell { - [super configureCell:cell]; - cell.nameLabel.text = self.name; - if (self.icon) { - cell.iconImageView.image = self.icon; - } - [cell updateWithState:self.state]; -} - -@end - -@implementation NativeAppCell - -@synthesize nameLabel = _nameLabel; -@synthesize iconImageView = _iconImageView; -@synthesize switchControl = _switchControl; -@synthesize installButton = _installButton; - -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - UIView* contentView = self.contentView; - self.isAccessibilityElement = YES; - - _iconImageView = [[UIImageView alloc] init]; - _iconImageView.translatesAutoresizingMaskIntoConstraints = NO; - _iconImageView.image = PlaceholderIcon(); - _iconImageView.layer.cornerRadius = kIconCornerRadius; - _iconImageView.layer.masksToBounds = YES; - self.layer.shouldRasterize = YES; - self.layer.rasterizationScale = [[UIScreen mainScreen] scale]; - [contentView addSubview:_iconImageView]; - - _nameLabel = [[UILabel alloc] init]; - _nameLabel.translatesAutoresizingMaskIntoConstraints = NO; - [contentView addSubview:_nameLabel]; - - _nameLabel.font = [[MDCTypography fontLoader] mediumFontOfSize:14]; - _nameLabel.textColor = [[MDCPalette greyPalette] tint900]; - - _switchControl = [[UISwitch alloc] init]; - _switchControl.onTintColor = [[MDCPalette cr_bluePalette] tint500]; - - _installButton = [[MDCFlatButton alloc] init]; - _installButton.translatesAutoresizingMaskIntoConstraints = NO; - _installButton.customTitleColor = [[MDCPalette cr_bluePalette] tint500]; - [_installButton - setTitle:l10n_util::GetNSString(IDS_IOS_GOOGLE_APPS_INSTALL_BUTTON) - forState:UIControlStateNormal]; - [_installButton setTitle:@"" forState:UIControlStateDisabled]; - _installButton.accessibilityHint = l10n_util::GetNSString( - IDS_IOS_GOOGLE_APPS_INSTALL_BUTTON_ACCESSIBILITY_HINT); - - // Set up the constraints. - [NSLayoutConstraint activateConstraints:@[ - [_iconImageView.leadingAnchor - constraintEqualToAnchor:contentView.leadingAnchor - constant:kHorizontalPadding], - [_iconImageView.trailingAnchor - constraintEqualToAnchor:_nameLabel.leadingAnchor - constant:-kHorizontalPadding], - [_iconImageView.widthAnchor constraintEqualToConstant:kIconSize], - [_iconImageView.heightAnchor constraintEqualToConstant:kIconSize], - [_nameLabel.trailingAnchor - constraintEqualToAnchor:contentView.trailingAnchor - constant:-kHorizontalPadding], - [_iconImageView.centerYAnchor - constraintEqualToAnchor:contentView.centerYAnchor], - [_nameLabel.centerYAnchor - constraintEqualToAnchor:contentView.centerYAnchor], - [_installButton.widthAnchor constraintGreaterThanOrEqualToConstant:79], - [_installButton.widthAnchor constraintLessThanOrEqualToConstant:127], - ]]; - } - return self; -} - -- (void)updateWithState:(NativeAppItemState)state { - switch (state) { - case NativeAppItemSwitchOn: - self.switchControl.on = YES; - self.accessoryView = self.switchControl; - break; - case NativeAppItemSwitchOff: - self.switchControl.on = NO; - self.accessoryView = self.switchControl; - break; - case NativeAppItemInstall: - self.accessoryView = self.installButton; - break; - } -} - -- (void)prepareForReuse { - [super prepareForReuse]; - [self.switchControl removeTarget:nil - action:nil - forControlEvents:[self.switchControl allControlEvents]]; - self.switchControl.tag = 0; - [self.installButton removeTarget:nil - action:nil - forControlEvents:[self.installButton allControlEvents]]; - self.iconImageView.image = PlaceholderIcon(); - self.iconImageView.tag = 0; -} - -#pragma mark - UIAccessibility - -- (CGPoint)accessibilityActivationPoint { - // Activate over the accessory view. - CGRect accessoryViewFrame = UIAccessibilityConvertFrameToScreenCoordinates( - [self.accessoryView frame], self); - return CGPointMake(CGRectGetMidX(accessoryViewFrame), - CGRectGetMidY(accessoryViewFrame)); -} - -- (NSString*)accessibilityHint { - return [self.accessoryView accessibilityHint]; -} - -- (NSString*)accessibilityValue { - if (self.accessoryView == self.switchControl) { - if (self.switchControl.on) { - return [NSString - stringWithFormat:@"%@, %@", self.nameLabel.text, - l10n_util::GetNSString(IDS_IOS_SETTING_ON)]; - } else { - return [NSString - stringWithFormat:@"%@, %@", self.nameLabel.text, - l10n_util::GetNSString(IDS_IOS_SETTING_OFF)]; - } - } - - return [NSString stringWithFormat:@"%@, %@", self.nameLabel.text, - l10n_util::GetNSString( - IDS_IOS_GOOGLE_APPS_INSTALL_BUTTON)]; -} - -@end
diff --git a/ios/chrome/browser/ui/settings/cells/native_app_item_unittest.mm b/ios/chrome/browser/ui/settings/cells/native_app_item_unittest.mm deleted file mode 100644 index d83e1cb7..0000000 --- a/ios/chrome/browser/ui/settings/cells/native_app_item_unittest.mm +++ /dev/null
@@ -1,77 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/settings/cells/native_app_item.h" - -#import "ios/chrome/browser/ui/collection_view/cells/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" -#import "testing/gtest_mac.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { - -// Tests that the name, icon and state are honoured after a call to -// |configureCell:|. -TEST(NativeAppItemTest, ConfigureCell) { - NativeAppItem* item = [[NativeAppItem alloc] initWithType:0]; - NSString* text = @"Test Switch"; - UIImage* image = ios_internal::CollectionViewTestImage(); - - item.name = text; - item.icon = image; - - id cell = [[[item cellClass] alloc] init]; - ASSERT_TRUE([cell isMemberOfClass:[NativeAppCell class]]); - - NativeAppCell* appCell = static_cast<NativeAppCell*>(cell); - EXPECT_FALSE(appCell.nameLabel.text); - EXPECT_TRUE(appCell.iconImageView.image); - EXPECT_NE(image, appCell.iconImageView.image); - EXPECT_FALSE(appCell.accessoryView); - - [item configureCell:cell]; - EXPECT_NSEQ(text, appCell.nameLabel.text); - EXPECT_NSEQ(image, appCell.iconImageView.image); - EXPECT_EQ((UIView*)appCell.switchControl, appCell.accessoryView); - EXPECT_FALSE(appCell.switchControl.on); -} - -// Tests that the NativeAppItemSwitchOff configures the cell with a switch, -// turned off. -TEST(NativeAppItemTest, State_SwitchOff) { - NativeAppItem* item = [[NativeAppItem alloc] initWithType:0]; - item.state = NativeAppItemSwitchOff; - NativeAppCell* appCell = [[[item cellClass] alloc] init]; - [item configureCell:appCell]; - - EXPECT_EQ((UIView*)appCell.switchControl, appCell.accessoryView); - EXPECT_FALSE(appCell.switchControl.on); -} - -// Tests that the NativeAppItemSwitchOn configures the cell with a switch, -// turned on. -TEST(NativeAppItemTest, State_SwitchOn) { - NativeAppItem* item = [[NativeAppItem alloc] initWithType:0]; - item.state = NativeAppItemSwitchOn; - NativeAppCell* appCell = [[[item cellClass] alloc] init]; - [item configureCell:appCell]; - - EXPECT_EQ((UIView*)appCell.switchControl, appCell.accessoryView); - EXPECT_TRUE(appCell.switchControl.on); -} - -// Tests that the NativeAppItemInstall configures the cell with a button. -TEST(NativeAppItemTest, State_Install) { - NativeAppItem* item = [[NativeAppItem alloc] initWithType:0]; - item.state = NativeAppItemInstall; - NativeAppCell* appCell = [[[item cellClass] alloc] init]; - [item configureCell:appCell]; - - EXPECT_EQ((UIView*)appCell.installButton, appCell.accessoryView); -} - -} // namespace
diff --git a/ios/chrome/browser/ui/settings/material_cell_catalog_view_controller.mm b/ios/chrome/browser/ui/settings/material_cell_catalog_view_controller.mm index 608b04b..9afd756 100644 --- a/ios/chrome/browser/ui/settings/material_cell_catalog_view_controller.mm +++ b/ios/chrome/browser/ui/settings/material_cell_catalog_view_controller.mm
@@ -35,7 +35,6 @@ #import "ios/chrome/browser/ui/payments/cells/price_item.h" #import "ios/chrome/browser/ui/settings/cells/account_signin_item.h" #import "ios/chrome/browser/ui/settings/cells/autofill_data_item.h" -#import "ios/chrome/browser/ui/settings/cells/native_app_item.h" #import "ios/chrome/browser/ui/settings/cells/sync_switch_item.h" #import "ios/chrome/browser/ui/settings/cells/text_and_error_item.h" #import "ios/chrome/browser/ui/uikit_ui_util.h" @@ -218,21 +217,6 @@ [model addItem:[self syncSwitchItem] toSectionWithIdentifier:SectionIdentifierSwitchCell]; - // Native app cells. - [model addSectionWithIdentifier:SectionIdentifierNativeAppCell]; - NativeAppItem* fooApp = [[NativeAppItem alloc] initWithType:ItemTypeApp]; - fooApp.name = @"App Foo"; - fooApp.state = NativeAppItemSwitchOff; - [model addItem:fooApp toSectionWithIdentifier:SectionIdentifierNativeAppCell]; - NativeAppItem* barApp = [[NativeAppItem alloc] initWithType:ItemTypeApp]; - barApp.name = @"App Bar"; - barApp.state = NativeAppItemSwitchOn; - [model addItem:barApp toSectionWithIdentifier:SectionIdentifierNativeAppCell]; - NativeAppItem* bazApp = [[NativeAppItem alloc] initWithType:ItemTypeApp]; - bazApp.name = @"App Baz Qux Bla Bug Lorem ipsum dolor sit amet"; - bazApp.state = NativeAppItemInstall; - [model addItem:bazApp toSectionWithIdentifier:SectionIdentifierNativeAppCell]; - // Autofill cells. [model addSectionWithIdentifier:SectionIdentifierAutofill]; [model addItem:[self autofillItemWithMainAndTrailingText]
diff --git a/ios/chrome/browser/ui/settings/native_apps_collection_view_controller.h b/ios/chrome/browser/ui/settings/native_apps_collection_view_controller.h deleted file mode 100644 index 9e8db3e..0000000 --- a/ios/chrome/browser/ui/settings/native_apps_collection_view_controller.h +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_NATIVE_APPS_COLLECTION_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_NATIVE_APPS_COLLECTION_VIEW_CONTROLLER_H_ - -#import "ios/chrome/browser/store_kit/store_kit_launcher.h" -#import "ios/chrome/browser/ui/settings/settings_root_collection_view_controller.h" - -namespace net { -class URLRequestContextGetter; -} // namespace net - -// Settings view controller that displays the list of native apps that Chrome -// can launch given a specific URL. From this view controller, native apps can -// be installed if they are not present on the device. If they are present, a -// switch lets the user opt-in to open automatically related links. -// Icons for apps are static resources on a server and are therefore retrieved -// and displayed asynchronously. -@interface NativeAppsCollectionViewController - : SettingsRootCollectionViewController<StoreKitLauncher> - -// Designated initializer. |requestContextGetter| is kept as a weak reference, -// therefore must outlive the initialized instance. -- (id)initWithURLRequestContextGetter: - (net::URLRequestContextGetter*)requestContextGetter; - -@end - -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_NATIVE_APPS_COLLECTION_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/native_apps_collection_view_controller.mm b/ios/chrome/browser/ui/settings/native_apps_collection_view_controller.mm deleted file mode 100644 index 68602f5..0000000 --- a/ios/chrome/browser/ui/settings/native_apps_collection_view_controller.mm +++ /dev/null
@@ -1,405 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/settings/native_apps_collection_view_controller.h" -#import "ios/chrome/browser/ui/settings/native_apps_collection_view_controller_private.h" - -#import <StoreKit/StoreKit.h> - -#include "base/logging.h" -#import "base/mac/foundation_util.h" -#include "base/memory/ptr_util.h" -#include "base/metrics/histogram_macros.h" -#include "base/metrics/user_metrics.h" -#include "base/metrics/user_metrics_action.h" -#include "base/strings/sys_string_conversions.h" -#include "base/threading/sequenced_worker_pool.h" -#include "components/image_fetcher/ios/ios_image_data_fetcher_wrapper.h" -#import "ios/chrome/browser/installation_notifier.h" -#import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h" -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_footer_item.h" -#import "ios/chrome/browser/ui/collection_view/collection_view_model.h" -#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" -#import "ios/chrome/browser/ui/settings/cells/native_app_item.h" -#import "ios/chrome/browser/ui/settings/settings_utils.h" -#import "ios/chrome/common/string_util.h" -#include "ios/chrome/grit/ios_strings.h" -#import "ios/public/provider/chrome/browser/chrome_browser_provider.h" -#import "ios/public/provider/chrome/browser/native_app_launcher/native_app_metadata.h" -#import "ios/public/provider/chrome/browser/native_app_launcher/native_app_whitelist_manager.h" -#import "ios/third_party/material_components_ios/src/components/Buttons/src/MaterialButtons.h" -#include "ios/web/public/web_thread.h" -#include "ui/base/l10n/l10n_util.h" -#include "url/gurl.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -const NSInteger kTagShift = 1000; - -namespace { - -typedef NS_ENUM(NSInteger, SectionIdentifier) { - SectionIdentifierLearnMore = kSectionIdentifierEnumZero, - SectionIdentifierApps, -}; - -typedef NS_ENUM(NSInteger, ItemType) { - ItemTypeApp = kItemTypeEnumZero, - ItemTypeLearnMore, -}; - -} // namespace - -@interface NativeAppsCollectionViewController ()< - SKStoreProductViewControllerDelegate> { - std::unique_ptr<image_fetcher::IOSImageDataFetcherWrapper> _imageFetcher; - NSArray* _nativeAppsInSettings; - BOOL _userDidSomething; -} - -// List of the native apps visible in Settings. -@property(nonatomic, copy) NSArray* appsInSettings; - -// Delegate for App-Store-related operations. -@property(nonatomic, weak) id<StoreKitLauncher> storeKitLauncher; - -// Sets up the list of visible apps based on |nativeAppWhitelistManager|, which -// serves as datasource for this controller. Apps from -// |nativeAppWhitelistManager| are stored in |_nativeAppsInSettings| and -// |-reloadData| is sent to the receiver. -- (void)configureWithNativeAppWhiteListManager: - (id<NativeAppWhitelistManager>)nativeAppWhitelistManager; - -// Returns a new Native App collection view item for the metadata at |index| in -// |_nativeAppsInSettings|. -- (CollectionViewItem*)nativeAppItemAtIndex:(NSUInteger)index; - -// Target method for the auto open in app switch. -// Called when an auto-open-in-app switch is toggled. -- (void)autoOpenInAppChanged:(UISwitch*)switchControl; - -// Called when an Install button is being tapped. -- (void)installApp:(UIButton*)button; - -// Called when an app with the registered scheme is opened. -- (void)appDidInstall:(NSNotification*)notification; - -// Returns the app at |index| in the list of visible apps. -- (id<NativeAppMetadata>)nativeAppAtIndex:(NSUInteger)index; - -// Records a user action in UMA under NativeAppLauncher.Settings. -// If this method is not called during the lifetime of the view, -// |settings::kNativeAppsActionDidNothing| is recorded in UMA. -- (void)recordUserAction:(settings::NativeAppsAction)action; - -@end - -@implementation NativeAppsCollectionViewController - -@synthesize storeKitLauncher = _storeKitLauncher; - -- (id)initWithURLRequestContextGetter: - (net::URLRequestContextGetter*)requestContextGetter { - self = [super initWithStyle:CollectionViewControllerStyleAppBar]; - if (self) { - _imageFetcher = base::MakeUnique<image_fetcher::IOSImageDataFetcherWrapper>( - requestContextGetter, web::WebThread::GetBlockingPool()); - base::RecordAction(base::UserMetricsAction("MobileGALOpenSettings")); - _storeKitLauncher = self; - - [self loadModel]; - } - return self; -} - -- (void)dealloc { - [[InstallationNotifier sharedInstance] unregisterForNotifications:self]; - if (!_userDidSomething) - [self recordUserAction:settings::kNativeAppsActionDidNothing]; -} - -#pragma mark - View lifecycle - -- (void)viewDidLoad { - self.title = l10n_util::GetNSString(IDS_IOS_GOOGLE_APPS_SM_SETTINGS); - [self configureWithNativeAppWhiteListManager: - ios::GetChromeBrowserProvider()->GetNativeAppWhitelistManager()]; - - [super viewDidLoad]; -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - [[InstallationNotifier sharedInstance] checkNow]; - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(reloadData) - name:UIApplicationDidBecomeActiveNotification - object:nil]; -} - -- (void)viewDidDisappear:(BOOL)animated { - [super viewDidDisappear:animated]; - [[NSNotificationCenter defaultCenter] - removeObserver:self - name:UIApplicationDidBecomeActiveNotification - object:nil]; -} - -#pragma mark - CollectionViewController - -- (void)loadModel { - [super loadModel]; - CollectionViewModel* model = self.collectionViewModel; - NSUInteger appsCount = [_nativeAppsInSettings count]; - - [model addSectionWithIdentifier:SectionIdentifierLearnMore]; - [model addItem:[self learnMoreItem] - toSectionWithIdentifier:SectionIdentifierLearnMore]; - - [model addSectionWithIdentifier:SectionIdentifierApps]; - - for (NSUInteger i = 0; i < appsCount; i++) { - [model addItem:[self nativeAppItemAtIndex:i] - toSectionWithIdentifier:SectionIdentifierApps]; - } -} - -- (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView - cellForItemAtIndexPath:(NSIndexPath*)indexPath { - UICollectionViewCell* cell = - [super collectionView:collectionView cellForItemAtIndexPath:indexPath]; - if ([self.collectionViewModel - sectionIdentifierForSection:indexPath.section] == - SectionIdentifierApps) { - NativeAppCell* appCell = base::mac::ObjCCastStrict<NativeAppCell>(cell); - [self configureNativeAppCell:appCell atIndexPath:indexPath]; - } - return cell; -} - -#pragma mark - MDCCollectionViewStylingDelegate - -- (CGFloat)collectionView:(nonnull UICollectionView*)collectionView - cellHeightAtIndexPath:(nonnull NSIndexPath*)indexPath { - CollectionViewItem* item = - [self.collectionViewModel itemAtIndexPath:indexPath]; - switch (item.type) { - case ItemTypeLearnMore: - return [MDCCollectionViewCell - cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds) - forItem:item]; - case ItemTypeApp: - return MDCCellDefaultOneLineWithAvatarHeight; - default: - return MDCCellDefaultOneLineHeight; - } -} - -- (void)configureNativeAppCell:(NativeAppCell*)appCell - atIndexPath:(NSIndexPath*)indexPath { - appCell.switchControl.tag = [self tagForIndexPath:indexPath]; - [appCell.switchControl addTarget:self - action:@selector(autoOpenInAppChanged:) - forControlEvents:UIControlEventValueChanged]; - appCell.installButton.tag = [self tagForIndexPath:indexPath]; - [appCell.installButton addTarget:self - action:@selector(installApp:) - forControlEvents:UIControlEventTouchUpInside]; - CollectionViewItem* item = - [self.collectionViewModel itemAtIndexPath:indexPath]; - NativeAppItem* appItem = base::mac::ObjCCastStrict<NativeAppItem>(item); - if (!appItem.icon) { - // Fetch the real icon. - __weak NativeAppsCollectionViewController* weakSelf = self; - id<NativeAppMetadata> metadata = [self nativeAppAtIndex:indexPath.item]; - [metadata fetchSmallIconWithImageFetcher:_imageFetcher.get() - completionBlock:^(UIImage* image) { - - NativeAppsCollectionViewController* strongSelf = - weakSelf; - if (!image || !strongSelf) - return; - appItem.icon = image; - [strongSelf.collectionView - reloadItemsAtIndexPaths:@[ indexPath ]]; - }]; - } -} - -- (CollectionViewItem*)learnMoreItem { - NSString* learnMoreText = - l10n_util::GetNSString(IDS_IOS_GOOGLE_APPS_SM_SECTION_HEADER); - CollectionViewFooterItem* learnMoreItem = - [[CollectionViewFooterItem alloc] initWithType:ItemTypeLearnMore]; - learnMoreItem.text = learnMoreText; - return learnMoreItem; -} - -#pragma mark - SKStoreProductViewControllerDelegate methods - -- (void)productViewControllerDidFinish: - (SKStoreProductViewController*)viewController { - [self dismissViewControllerAnimated:YES completion:nil]; -} - -#pragma mark - StoreKitLauncher methods - -- (void)openAppStore:(NSString*)appId { - // Reported crashes show that -openAppStore: had been called with - // a nil |appId|, but opening AppStore is meaningful only if the |appId| is - // not nil, so be defensive and early return if |appId| is nil. - if (![appId length]) - return; - NSDictionary* product = - @{SKStoreProductParameterITunesItemIdentifier : appId}; - SKStoreProductViewController* storeViewController = - [[SKStoreProductViewController alloc] init]; - [storeViewController setDelegate:self]; - [storeViewController loadProductWithParameters:product completionBlock:nil]; - [self presentViewController:storeViewController animated:YES completion:nil]; -} - -#pragma mark - MDCCollectionViewStylingDelegate - -// MDCCollectionViewStylingDelegate protocol is implemented so that cells don't -// display ink on touch. -- (BOOL)collectionView:(nonnull UICollectionView*)collectionView - hidesInkViewAtIndexPath:(nonnull NSIndexPath*)indexPath { - return YES; -} - -- (MDCCollectionViewCellStyle)collectionView:(UICollectionView*)collectionView - cellStyleForSection:(NSInteger)section { - NSInteger sectionIdentifier = - [self.collectionViewModel sectionIdentifierForSection:section]; - switch (sectionIdentifier) { - case SectionIdentifierLearnMore: - // Display the Learn More footer in the default style with no "card" UI - // and no section padding. - return MDCCollectionViewCellStyleDefault; - default: - return self.styler.cellStyle; - } -} - -- (BOOL)collectionView:(UICollectionView*)collectionView - shouldHideItemBackgroundAtIndexPath:(NSIndexPath*)indexPath { - NSInteger sectionIdentifier = - [self.collectionViewModel sectionIdentifierForSection:indexPath.section]; - switch (sectionIdentifier) { - case SectionIdentifierLearnMore: - // Display the Learn More footer without any background image or - // shadowing. - return YES; - default: - return NO; - } -} -#pragma mark - Private methods - -- (void)autoOpenInAppChanged:(UISwitch*)switchControl { - NSInteger index = [self indexPathForTag:switchControl.tag].item; - id<NativeAppMetadata> metadata = [self nativeAppAtIndex:index]; - DCHECK([metadata isInstalled]); - BOOL autoOpenOn = switchControl.on; - metadata.shouldAutoOpenLinks = autoOpenOn; - [self recordUserAction:(autoOpenOn - ? settings::kNativeAppsActionTurnedAutoOpenOn - : settings::kNativeAppsActionTurnedAutoOpenOff)]; -} - -- (void)installApp:(UIButton*)button { - [self recordUserAction:settings::kNativeAppsActionClickedInstall]; - NSInteger index = [self indexPathForTag:button.tag].item; - id<NativeAppMetadata> metadata = [self nativeAppAtIndex:index]; - DCHECK(![metadata isInstalled]); - [metadata updateCounterWithAppInstallation]; - - // Register to get a notification when the app is installed. - [[InstallationNotifier sharedInstance] - registerForInstallationNotifications:self - withSelector:@selector(appDidInstall:) - forScheme:[metadata anyScheme]]; - [self.storeKitLauncher openAppStore:[metadata appId]]; -} - -- (void)appDidInstall:(NSNotification*)notification { - // The name of the notification is the scheme of the new app installed. - GURL url(base::SysNSStringToUTF8([notification name]) + ":"); - DCHECK(url.is_valid()); - NSUInteger matchingAppIndex = [_nativeAppsInSettings - indexOfObjectPassingTest:^(id obj, NSUInteger idx, BOOL* stop) { - id<NativeAppMetadata> metadata = - static_cast<id<NativeAppMetadata>>(obj); - return [metadata canOpenURL:url]; - }]; - [[self nativeAppAtIndex:matchingAppIndex] setShouldAutoOpenLinks:YES]; - [self reloadData]; -} - -- (void)configureWithNativeAppWhiteListManager: - (id<NativeAppWhitelistManager>)nativeAppWhitelistManager { - NSArray* allApps = [nativeAppWhitelistManager - filteredAppsUsingBlock:^(const id<NativeAppMetadata> app, BOOL* stop) { - return [app isGoogleOwnedApp]; - }]; - [self setAppsInSettings:allApps]; - [self reloadData]; -} - -- (id<NativeAppMetadata>)nativeAppAtIndex:(NSUInteger)index { - id<NativeAppMetadata> metadata = [_nativeAppsInSettings objectAtIndex:index]; - DCHECK([metadata conformsToProtocol:@protocol(NativeAppMetadata)]); - return metadata; -} - -- (void)recordUserAction:(settings::NativeAppsAction)action { - _userDidSomething = YES; - UMA_HISTOGRAM_ENUMERATION("NativeAppLauncher.Settings", action, - settings::kNativeAppsActionCount); -} - -- (CollectionViewItem*)nativeAppItemAtIndex:(NSUInteger)index { - id<NativeAppMetadata> metadata = [self nativeAppAtIndex:index]; - // Determine the state of the cell. - NativeAppItemState state; - if ([metadata isInstalled]) { - state = [metadata shouldAutoOpenLinks] ? NativeAppItemSwitchOn - : NativeAppItemSwitchOff; - } else { - state = NativeAppItemInstall; - } - NativeAppItem* appItem = [[NativeAppItem alloc] initWithType:ItemTypeApp]; - appItem.name = [metadata appName]; - appItem.state = state; - return appItem; -} - -- (NSArray*)appsInSettings { - return _nativeAppsInSettings; -} - -- (void)setAppsInSettings:(NSArray*)apps { - _nativeAppsInSettings = [apps copy]; -} - -- (NSInteger)tagForIndexPath:(NSIndexPath*)indexPath { - DCHECK(indexPath.section == - [self.collectionViewModel - sectionForSectionIdentifier:SectionIdentifierApps]); - return indexPath.item + kTagShift; -} - -- (NSIndexPath*)indexPathForTag:(NSInteger)shiftedTag { - NSInteger unshiftedTag = shiftedTag - kTagShift; - return [NSIndexPath - indexPathForItem:unshiftedTag - inSection:[self.collectionViewModel - sectionForSectionIdentifier:SectionIdentifierApps]]; -} - -@end
diff --git a/ios/chrome/browser/ui/settings/native_apps_collection_view_controller_private.h b/ios/chrome/browser/ui/settings/native_apps_collection_view_controller_private.h deleted file mode 100644 index 1e098aee..0000000 --- a/ios/chrome/browser/ui/settings/native_apps_collection_view_controller_private.h +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_NATIVE_APPS_COLLECTION_VIEW_CONTROLLER_PRIVATE_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_NATIVE_APPS_COLLECTION_VIEW_CONTROLLER_PRIVATE_H_ - -#import "ios/chrome/browser/ui/settings/native_apps_collection_view_controller.h" - -// This file is a private header for NativeAppsCollectionViewController. -// It exposes private details for testing purposes. - -namespace settings { - -// User actions. -typedef enum { - kNativeAppsActionDidNothing, - kNativeAppsActionClickedInstall, - kNativeAppsActionTurnedDefaultBrowserOn, - kNativeAppsActionTurnedDefaultBrowserOff, - kNativeAppsActionTurnedAutoOpenOn, - kNativeAppsActionTurnedAutoOpenOff, - kNativeAppsActionCount, -} NativeAppsAction; - -} // namespace settings - -// Arbitrary value to shift indices (from 0 to N), to a range that doesn't -// include 0, in order to not mistake the default value (0) with the first -// index. That way, an invalid (or default) tag value can be detected. -// That means that all app cells have a tag computed by adding their index and -// this shift. -extern const NSInteger kTagShift; - -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_NATIVE_APPS_COLLECTION_VIEW_CONTROLLER_PRIVATE_H_
diff --git a/ios/chrome/browser/ui/settings/native_apps_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/native_apps_collection_view_controller_unittest.mm deleted file mode 100644 index 25a75dc..0000000 --- a/ios/chrome/browser/ui/settings/native_apps_collection_view_controller_unittest.mm +++ /dev/null
@@ -1,251 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/settings/native_apps_collection_view_controller.h" -#import "ios/chrome/browser/ui/settings/native_apps_collection_view_controller_private.h" - -#include <memory> - -#include "base/compiler_specific.h" -#import "base/ios/block_types.h" -#include "base/test/histogram_tester.h" -#include "base/threading/thread_task_runner_handle.h" -#import "ios/chrome/browser/ui/collection_view/collection_view_controller_test.h" -#import "ios/chrome/browser/ui/settings/cells/native_app_item.h" -#import "ios/public/provider/chrome/browser/native_app_launcher/fake_native_app_metadata.h" -#import "ios/public/provider/chrome/browser/native_app_launcher/fake_native_app_whitelist_manager.h" -#include "ios/web/public/test/test_web_thread_bundle.h" -#include "net/url_request/url_request_test_util.h" -#include "testing/gtest/include/gtest/gtest.h" -#import "testing/gtest_mac.h" -#import "third_party/ocmock/OCMock/OCMock.h" -#include "ui/base/l10n/l10n_util.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface NativeAppsCollectionViewController (Testing) -@property(nonatomic, retain) NSArray* appsInSettings; -@property(nonatomic, assign) id<StoreKitLauncher> storeKitLauncher; -- (void)configureWithNativeAppWhiteListManager: - (id<NativeAppWhitelistManager>)nativeAppWhitelistManager; -- (void)autoOpenInAppChanged:(UISwitch*)switchControl; -- (void)installApp:(UIButton*)button; -- (void)recordUserAction:(settings::NativeAppsAction)action; -- (void)appDidInstall:(NSNotification*)note; -- (id<NativeAppMetadata>)nativeAppAtIndex:(NSUInteger)index; -@end - -@interface MockNativeAppWhitelistManager : FakeNativeAppWhitelistManager -@end - -@implementation MockNativeAppWhitelistManager - -- (id)init { - self = [super init]; - if (self) { - FakeNativeAppMetadata* app1 = [[FakeNativeAppMetadata alloc] init]; - [app1 setAppName:@"App1"]; - [app1 setAppId:@"1"]; - [app1 setGoogleOwnedApp:YES]; - - FakeNativeAppMetadata* app2 = [[FakeNativeAppMetadata alloc] init]; - [app2 setAppName:@"App2"]; - [app2 setAppId:@"2"]; - [app2 setGoogleOwnedApp:YES]; - - FakeNativeAppMetadata* app3 = [[FakeNativeAppMetadata alloc] init]; - [app3 setAppName:@"App3"]; - [app3 setAppId:@"3"]; - [app3 setGoogleOwnedApp:YES]; - - FakeNativeAppMetadata* notOwnedApp = [[FakeNativeAppMetadata alloc] init]; - [notOwnedApp setAppName:@"NotOwnedApp"]; - [notOwnedApp setAppId:@"999"]; - [notOwnedApp setGoogleOwnedApp:NO]; - - [self setAppList:@[ app1, app2, notOwnedApp, app3 ] - tldList:nil - acceptStoreIDs:nil]; - } - return self; -} - -@end - -@interface MockStoreKitLauncher : NSObject<StoreKitLauncher> -@end - -@implementation MockStoreKitLauncher -- (void)openAppStore:(id<NativeAppMetadata>)metadata { -} -@end - -namespace { - -class NativeAppsCollectionViewControllerTest - : public CollectionViewControllerTest { - protected: - void SetUp() override { - CollectionViewControllerTest::SetUp(); - request_context_getter_ = new net::TestURLRequestContextGetter( - base::ThreadTaskRunnerHandle::Get()); - NativeAppsCollectionViewController* native_apps_controller = - static_cast<NativeAppsCollectionViewController*>(controller()); - - mock_whitelist_manager_ = [[MockNativeAppWhitelistManager alloc] init]; - [native_apps_controller - configureWithNativeAppWhiteListManager:mock_whitelist_manager_]; - } - - CollectionViewController* InstantiateController() override { - DCHECK(request_context_getter_.get()); - return [[NativeAppsCollectionViewController alloc] - initWithURLRequestContextGetter:request_context_getter_.get()]; - } - - // Runs the block and checks that the |action| (and only the action) has been - // recorded. - void ExpectUserActionAfterBlock(settings::NativeAppsAction action, - ProceduralBlock block) { - std::unique_ptr<base::HistogramTester> histogram_tester( - new base::HistogramTester()); - block(); - histogram_tester->ExpectUniqueSample("NativeAppLauncher.Settings", action, - 1); - } - - // Adds a mocked app of class MockNativeAppMetadata at the end of the apps' - // list. - void AddMockedApp() { - NativeAppsCollectionViewController* native_apps_controller = - static_cast<NativeAppsCollectionViewController*>(controller()); - // Add a mock app at the end of the app list. - NSMutableArray* apps = - [NSMutableArray arrayWithArray:[native_apps_controller appsInSettings]]; - ASSERT_GT([apps count], 0U); - FakeNativeAppMetadata* installed_app = [[FakeNativeAppMetadata alloc] init]; - [installed_app setAppName:@"App4"]; - [installed_app setAppId:@"4"]; - [installed_app setGoogleOwnedApp:YES]; - [installed_app resetInfobarHistory]; - [installed_app unsetShouldAutoOpenLinks]; - [installed_app setInstalled:YES]; - [apps addObject:installed_app]; - [native_apps_controller setAppsInSettings:apps]; - } - - // Checks that the object's state is consistent with the represented app - // metadata at |index| in |section|. - void CheckNativeAppItem(NSUInteger section, NSUInteger index) { - NativeAppsCollectionViewController* native_apps_controller = - static_cast<NativeAppsCollectionViewController*>(controller()); - id<NativeAppMetadata> metadata = - [native_apps_controller nativeAppAtIndex:index]; - NativeAppItem* item = GetCollectionViewItem(section, index); - EXPECT_TRUE(item); - EXPECT_NSEQ([metadata appName], item.name); - if ([metadata isInstalled]) { - if ([metadata shouldAutoOpenLinks]) - EXPECT_EQ(NativeAppItemSwitchOn, item.state); - else - EXPECT_EQ(NativeAppItemSwitchOff, item.state); - } else { - EXPECT_EQ(NativeAppItemInstall, item.state); - } - } - - web::TestWebThreadBundle thread_bundle_; - scoped_refptr<net::URLRequestContextGetter> request_context_getter_; - MockNativeAppWhitelistManager* mock_whitelist_manager_; -}; - -// Tests the integrity of the loaded model: section titles, sections and rows, -// along with checking that objects are correctly set up and appear in the -// correct order. -TEST_F(NativeAppsCollectionViewControllerTest, TestModel) { - NativeAppsCollectionViewController* native_apps_controller = - static_cast<NativeAppsCollectionViewController*>(controller()); - CheckController(); - EXPECT_EQ(2, NumberOfSections()); - - // As many rows as there are apps. - NSInteger apps_count = [[native_apps_controller appsInSettings] count]; - EXPECT_EQ(apps_count, NumberOfItemsInSection(1)); - for (NSInteger i = 0; i < apps_count; i++) { - CheckNativeAppItem(1, i); - } -} - -// Tests that native app metadata are correctly updated when the user toggles -// switches. It checks that the appropriate UMA is sent for this user action. -TEST_F(NativeAppsCollectionViewControllerTest, AutoOpenInAppChanged) { - NativeAppsCollectionViewController* native_apps_controller = - static_cast<NativeAppsCollectionViewController*>(controller()); - AddMockedApp(); - // Make sure the last app is installed. - NSInteger last_index = [[native_apps_controller appsInSettings] count] - 1; - id<NativeAppMetadata> last_app = - [native_apps_controller nativeAppAtIndex:last_index]; - ASSERT_TRUE([last_app isInstalled]); - - EXPECT_FALSE([last_app shouldAutoOpenLinks]); - UISwitch* switch_from_cell = [[UISwitch alloc] init]; - switch_from_cell.on = YES; - switch_from_cell.tag = kTagShift + last_index; - - ExpectUserActionAfterBlock(settings::kNativeAppsActionTurnedAutoOpenOn, ^{ - [native_apps_controller autoOpenInAppChanged:switch_from_cell]; - EXPECT_TRUE([last_app shouldAutoOpenLinks]); - }); - - switch_from_cell.on = NO; - - ExpectUserActionAfterBlock(settings::kNativeAppsActionTurnedAutoOpenOff, ^{ - [native_apps_controller autoOpenInAppChanged:switch_from_cell]; - EXPECT_FALSE([last_app shouldAutoOpenLinks]); - }); -} - -// Tests that the App Store is launched when the user clicks on an Install -// button. It checks that the appropriate UMA is sent for this user action. -TEST_F(NativeAppsCollectionViewControllerTest, InstallApp) { - NativeAppsCollectionViewController* native_apps_controller = - static_cast<NativeAppsCollectionViewController*>(controller()); - id<StoreKitLauncher> real_opener = [native_apps_controller storeKitLauncher]; - id<StoreKitLauncher> mockLauncher = [[MockStoreKitLauncher alloc] init]; - [native_apps_controller setStoreKitLauncher:mockLauncher]; - UIButton* button_from_cell = [UIButton buttonWithType:UIButtonTypeCustom]; - button_from_cell.tag = kTagShift; - id mock_button = [OCMockObject partialMockForObject:button_from_cell]; - ExpectUserActionAfterBlock(settings::kNativeAppsActionClickedInstall, ^{ - [native_apps_controller installApp:mock_button]; - }); - - [mock_button verify]; - - [native_apps_controller setStoreKitLauncher:real_opener]; -} - -// Tests that native app metadata are correctly updated when the related app has -// been installed. -TEST_F(NativeAppsCollectionViewControllerTest, AppDidInstall) { - NativeAppsCollectionViewController* native_apps_controller = - static_cast<NativeAppsCollectionViewController*>(controller()); - AddMockedApp(); - // Make sure the last app can open any URL. - id<NativeAppMetadata> last_app = - [[native_apps_controller appsInSettings] lastObject]; - ASSERT_TRUE([last_app canOpenURL:GURL()]); - - EXPECT_FALSE([last_app shouldAutoOpenLinks]); - [native_apps_controller - appDidInstall:[NSNotification notificationWithName:@"App4" object:nil]]; - EXPECT_TRUE([last_app shouldAutoOpenLinks]); - - [last_app unsetShouldAutoOpenLinks]; -} - -} // namespace
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.h b/ios/chrome/browser/ui/settings/settings_navigation_controller.h index 3f917fe..2afb19a 100644 --- a/ios/chrome/browser/ui/settings/settings_navigation_controller.h +++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.h
@@ -79,13 +79,6 @@ delegate:(id<SettingsNavigationControllerDelegate>) delegate; -// Creates a new NativeAppsCollectionViewController and the chrome around it. -// |browserState| is used to personalize some settings aspects and should not be -// nil. |delegate| may be nil. -+ (SettingsNavigationController*) -newNativeAppsController:(ios::ChromeBrowserState*)browserState - delegate:(id<SettingsNavigationControllerDelegate>)delegate; - // Creates a new ClearBrowsingDataCollectionViewController and the chrome around // it. // |browserState| is used to personalize some settings aspects and should not be
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm index d3c885f..56309540 100644 --- a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
@@ -23,7 +23,6 @@ #import "ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/contextual_search_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/import_data_collection_view_controller.h" -#import "ios/chrome/browser/ui/settings/native_apps_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/save_passwords_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/settings_utils.h" @@ -223,18 +222,6 @@ } + (SettingsNavigationController*) -newNativeAppsController:(ios::ChromeBrowserState*)browserState - delegate:(id<SettingsNavigationControllerDelegate>)delegate { - UIViewController* controller = [[NativeAppsCollectionViewController alloc] - initWithURLRequestContextGetter:browserState->GetRequestContext()]; - SettingsNavigationController* nc = [[SettingsNavigationController alloc] - initWithRootViewController:controller - browserState:browserState - delegate:delegate]; - return nc; -} - -+ (SettingsNavigationController*) newSavePasswordsController:(ios::ChromeBrowserState*)browserState delegate:(id<SettingsNavigationControllerDelegate>)delegate { UIViewController* controller = [[SavePasswordsCollectionViewController alloc]
diff --git a/ios/shared/chrome/browser/ui/browser_list/BUILD.gn b/ios/shared/chrome/browser/ui/browser_list/BUILD.gn index 489be46..692a147a 100644 --- a/ios/shared/chrome/browser/ui/browser_list/BUILD.gn +++ b/ios/shared/chrome/browser/ui/browser_list/BUILD.gn
@@ -15,6 +15,7 @@ "browser_list_session_service_factory.mm", "browser_list_session_service_impl.h", "browser_list_session_service_impl.mm", + "browser_user_data.h", "browser_web_state_list_delegate.h", "browser_web_state_list_delegate.mm", ]
diff --git a/ios/shared/chrome/browser/ui/browser_list/browser.h b/ios/shared/chrome/browser/ui/browser_list/browser.h index ef6cbb00..213f8d1 100644 --- a/ios/shared/chrome/browser/ui/browser_list/browser.h +++ b/ios/shared/chrome/browser/ui/browser_list/browser.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/macros.h" +#include "base/supports_user_data.h" class WebStateList; class WebStateListDelegate; @@ -21,10 +22,10 @@ // Browser holds the state backing a collection of Tabs and the attached // UI elements (Tab strip, ...). -class Browser { +class Browser : public base::SupportsUserData { public: explicit Browser(ios::ChromeBrowserState* browser_state); - ~Browser(); + ~Browser() override; WebStateList& web_state_list() { return *web_state_list_.get(); } const WebStateList& web_state_list() const { return *web_state_list_.get(); }
diff --git a/ios/shared/chrome/browser/ui/browser_list/browser_user_data.h b/ios/shared/chrome/browser/ui/browser_list/browser_user_data.h new file mode 100644 index 0000000..15562a3 --- /dev/null +++ b/ios/shared/chrome/browser/ui/browser_list/browser_user_data.h
@@ -0,0 +1,74 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_USER_DATA_H_ +#define IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_USER_DATA_H_ + +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "base/supports_user_data.h" +#import "ios/shared/chrome/browser/ui/browser_list/browser.h" + +// A base class for classes attached to, and scoped to, the lifetime of a +// Browser. For example: +// +// --- in foo.h --- +// class Foo : public BrowserUserData<Foo> { +// public: +// ~Foo() override; +// // ... more public stuff here ... +// private: +// explicit Foo(Browser* browser); +// friend class BrowserUserData<Foo>; +// // ... more private stuff here ... +// } +// --- in foo.mm --- +// DEFINE_BROWSER_USER_DATA_KEY(Foo); +// +template <typename T> +class BrowserUserData : public base::SupportsUserData::Data { + public: + // Creates an object of type T, and attaches it to the specified Browser. + // If an instance is already attached, does nothing. + static void CreateForBrowser(Browser* browser) { + DCHECK(browser); + if (!FromBrowser(browser)) { + browser->SetUserData(UserDataKey(), base::WrapUnique(new T(browser))); + } + } + + // Retrieves the instance of type T that was attached to the specified + // Browser (via CreateForBrowser above) and returns it. If no + // instance of the type was attached, returns nullptr. + static T* FromBrowser(Browser* browser) { + return static_cast<T*>(browser->GetUserData(UserDataKey())); + } + static const T* FromBrowser(const Browser* browser) { + return static_cast<const T*>(browser->GetUserData(UserDataKey())); + } + // Removes the instance attached to the specified WebState. + static void RemoveFromBrowser(Browser* browser) { + browser->RemoveUserData(UserDataKey()); + } + + protected: + static inline void* UserDataKey() { return &kLocatorKey; } + + private: + // The user data key. + static int kLocatorKey; +}; + +// The macro to define the locator key. This key should be defined in the +// implementation file of the derived class. +// +// The "= 0" is surprising, but is required to effect a definition rather than +// a declaration. Without it, this would be merely a declaration of a template +// specialization. (C++98: 14.7.3.15; C++11: 14.7.3.13) +// +#define DEFINE_BROWSER_USER_DATA_KEY(TYPE) \ + template <> \ + int BrowserUserData<TYPE>::kLocatorKey = 0 + +#endif // IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_USER_DATA_H_
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 4e30c10..42dea08 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -938,7 +938,7 @@ # Ref tests that needs investigation. crbug.com/404597 [ Mac ] fast/css3-text/css3-text-justify/text-justify-crash.html [ Failure ] -crbug.com/404597 fast/forms/long-text-in-input.html [ Failure ] +crbug.com/404597 fast/forms/long-text-in-input.html [ Skip ] # Web Components related tests (Shadow DOM, Custom Elements) failures. crbug.com/505364 external/wpt/shadow-dom/untriaged/styles/test-003.html [ Failure ] @@ -2665,10 +2665,10 @@ crbug.com/703533 [ Mac ] shapedetection/detection-security-test.html [ Crash Pass Timeout ] # Sheriff failures 2017-05-11 -crbug.com/724027 [ Linux ] http/tests/security/contentSecurityPolicy/directive-parsing-03.html [ Failure Pass Timeout ] -crbug.com/724027 [ Linux ] http/tests/security/contentSecurityPolicy/source-list-parsing-04.html [ Failure Pass Timeout ] -crbug.com/724027 [ Linux ] virtual/mojo-loading/http/tests/security/contentSecurityPolicy/directive-parsing-03.html [ Failure Pass Timeout ] -crbug.com/724027 [ Linux ] virtual/mojo-loading/http/tests/security/contentSecurityPolicy/source-list-parsing-04.html [ Failure Pass Timeout ] +crbug.com/724027 http/tests/security/contentSecurityPolicy/directive-parsing-03.html [ Skip ] +crbug.com/724027 http/tests/security/contentSecurityPolicy/source-list-parsing-04.html [ Skip ] +crbug.com/724027 virtual/mojo-loading/http/tests/security/contentSecurityPolicy/directive-parsing-03.html [ Skip ] +crbug.com/724027 virtual/mojo-loading/http/tests/security/contentSecurityPolicy/source-list-parsing-04.html [ Skip ] # Sheriff failures 2017-05-16 crbug.com/722212 fast/events/pointerevents/mouse-pointer-event-properties.html [ Failure Timeout Pass ] @@ -2831,3 +2831,66 @@ crbug.com/736177 [ Mac ] virtual/off-main-thread-fetch/http/tests/misc/acid2-pixel.html [ Failure Pass ] crbug.com/736177 [ Mac ] virtual/prefer_compositing_to_lcd_text/scrollbars/custom-scrollbar-with-incomplete-style.html [ Failure Pass ] crbug.com/736177 [ Mac ] virtual/rootlayerscrolls/scrollbars/custom-scrollbar-with-incomplete-style.html [ Failure Pass ] + +crbug.com/734762 [ Mac Debug ] inspector-protocol/timeline/page-frames.js [ Failure ] + +crbug.com/736255 [ Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-001.html [ Skip ] + +# These tests crash, fail or are flaky on Mac 10.9 +crbug.com/736257 [ Mac10.9 ] editing/selection/modify_move/move_left_right_character_in_mixed_bidi.html [ Skip ] +crbug.com/736257 [ Mac10.9 ] external/wpt/css/css-writing-modes-3/bidi-isolate-override-007.html [ Skip ] +crbug.com/736257 [ Mac10.9 ] fast/text-autosizing/tables/css-table-single-cell-lots-of-text.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text-autosizing/tables/nested-table-wrapping.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text-autosizing/tables/nested-tables.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text-autosizing/tables/table-for-layout.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text-autosizing/tables/wide-specified-width.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/atsui-pointtooffset-calls-cg.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/atsui-rtl-override-selection.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/basic/011.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/basic/013.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/ellipsis-at-edge-of-rtl-text-in-ltr-flow.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/ellipsis-ltr-text-in-ltr-flow-underline-composition.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/ellipsis-rtl-text-in-ltr-flow.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/emphasis-complex.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/fallback-for-custom-font.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/font-fallback.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/font-features/caps-native-synthesis.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/font-initial.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/font-weight.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/international/bidi-AN-after-L.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/international/bidi-CS-after-AN.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/international/bidi-L2-run-reordering.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/international/bidi-LDB-2-CSS.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/international/bidi-LDB-2-formatting-characters.html [ Skip ] +crbug.com/736257 [ Mac10.9 ] fast/text/international/bidi-ignored-for-first-child-inline.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/international/bidi-layout-across-linebreak.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/international/bidi-neutral-directionality-paragraph-start.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/international/bidi-neutral-run.html [ Skip ] +crbug.com/736257 [ Mac10.9 ] fast/text/international/hebrew-vowels.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/international/hindi-spacing.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/international/mixed-directionality-selection.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/international/rtl-white-space-pre-wrap.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/international/unicode-bidi-plaintext.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/justified-selection-at-edge.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/justified-selection.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/justify-ideograph-complex.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/justify-ideograph-simple.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/midword-break-after-breakable-char.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/place-ellipsis-in-inline-blocks-align-center.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/place-mixed-ellipsis-in-inline-blocks-align-left-2.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/place-rtl-ellipsis-in-inline-blocks-align-left.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/reset-emptyRun.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/should-use-atsui.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/wbr-styled.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/whitespace/001.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/whitespace/005.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/whitespace/006.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/whitespace/011.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/whitespace/016.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/whitespace/021.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/whitespace/027.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/whitespace/028.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/whitespace/030.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/whitespace/span-in-word-space-causes-overflow.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] fast/text/word-break.html [ Failure Pass ] +crbug.com/736257 [ Mac10.9 ] inspector/elements/bidi-dom-tree.html [ Skip ]
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn index eefc614..a98fa7a 100644 --- a/third_party/WebKit/Source/core/BUILD.gn +++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1227,6 +1227,7 @@ "dom/ElementTest.cpp", "dom/ElementVisibilityObserverTest.cpp", "dom/IdleDeadlineTest.cpp", + "dom/IntersectionObserverTest.cpp", "dom/LayoutTreeBuilderTraversalTest.cpp", "dom/MockScriptElementBase.h", "dom/ModulatorTest.cpp", @@ -1235,6 +1236,7 @@ "dom/NodeTest.cpp", "dom/NthIndexCacheTest.cpp", "dom/RangeTest.cpp", + "dom/ResizeObserverTest.cpp", "dom/ScriptModuleResolverImplTest.cpp", "dom/ScriptRunnerTest.cpp", "dom/ScriptedAnimationControllerTest.cpp", @@ -1260,19 +1262,32 @@ "dom/custom/CustomElementTestHelpers.h", "dom/custom/CustomElementUpgradeSorterTest.cpp", "dom/shadow/FlatTreeTraversalTest.cpp", + "dom/shadow/ShadowDOMV0Test.cpp", "dom/shadow/SlotScopedTraversalTest.cpp", "editing/CaretDisplayItemClientTest.cpp", + "editing/TextFinderTest.cpp", "events/EventPathTest.cpp", "events/EventTargetTest.cpp", "events/PointerEventFactoryTest.cpp", "events/TouchEventTest.cpp", + "events/WebInputEventConversionTest.cpp", "exported/WebAssociatedURLLoaderImplTest.cpp", + "exported/WebDocumentTest.cpp", "exported/WebDragDataTest.cpp", "exported/WebElementTest.cpp", + "exported/WebFrameSerializerTest.cpp", "exported/WebNodeTest.cpp", + "exported/WebRangeTest.cpp", + "exported/WebScopedWindowFocusAllowedIndicatorTest.cpp", + "exported/WebSearchableFormDataTest.cpp", + "exported/WebSelectorTest.cpp", + "exported/WebUserGestureTokenTest.cpp", + "exported/WebViewTest.cpp", "fileapi/FileListTest.cpp", "fileapi/FileTest.cpp", + "frame/BrowserControlsTest.cpp", "frame/DOMTimerTest.cpp", + "frame/FrameSerializerTest.cpp", "frame/FrameTest.cpp", "frame/FrameTestHelpers.cpp", "frame/FrameTestHelpers.h", @@ -1283,6 +1298,7 @@ "frame/RootFrameViewportTest.cpp", "frame/SubresourceIntegrityTest.cpp", "frame/UseCounterTest.cpp", + "frame/VisualViewportTest.cpp", "frame/csp/CSPDirectiveListTest.cpp", "frame/csp/CSPSourceTest.cpp", "frame/csp/ContentSecurityPolicyTest.cpp", @@ -1326,6 +1342,7 @@ "html/parser/AtomicHTMLTokenTest.cpp", "html/parser/CSSPreloadScannerTest.cpp", "html/parser/CompactHTMLTokenTest.cpp", + "html/parser/HTMLDocumentParserLoadingTest.cpp", "html/parser/HTMLDocumentParserTest.cpp", "html/parser/HTMLEntityParserTest.cpp", "html/parser/HTMLParserIdiomsTest.cpp", @@ -1400,6 +1417,7 @@ "layout/svg/LayoutSVGRootTest.cpp", "loader/BaseFetchContextTest.cpp", "loader/DocumentLoadTimingTest.cpp", + "loader/DocumentLoaderTest.cpp", "loader/FrameFetchContextTest.cpp", "loader/LinkLoaderTest.cpp", "loader/MixedContentCheckerTest.cpp", @@ -1428,6 +1446,7 @@ "page/PrintContextTest.cpp", "page/WindowFeaturesTest.cpp", "page/scrolling/ScrollStateTest.cpp", + "page/scrolling/ScrollingCoordinatorTest.cpp", "page/scrolling/SnapCoordinatorTest.cpp", "paint/BoxPaintInvalidatorTest.cpp", "paint/FirstMeaningfulPaintDetectorTest.cpp",
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index 8b987e68..96f33e2 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -3250,6 +3250,8 @@ return; if (load_event_progress_ <= kUnloadEventInProgress) { + if (GetPage()) + GetPage()->WillUnloadDocument(*this); Element* current_focused_element = FocusedElement(); if (isHTMLInputElement(current_focused_element)) toHTMLInputElement(*current_focused_element).EndEditing();
diff --git a/third_party/WebKit/Source/core/dom/DocumentTest.cpp b/third_party/WebKit/Source/core/dom/DocumentTest.cpp index 582986e..6ebc468 100644 --- a/third_party/WebKit/Source/core/dom/DocumentTest.cpp +++ b/third_party/WebKit/Source/core/dom/DocumentTest.cpp
@@ -294,8 +294,12 @@ MockValidationMessageClient() { Reset(); } void Reset() { show_validation_message_was_called = false; + will_unload_document_was_called = false; + document_detached_was_called = false; } bool show_validation_message_was_called; + bool will_unload_document_was_called; + bool document_detached_was_called; // ValidationMessageClient functions. void ShowValidationMessage(const Element& anchor, @@ -309,6 +313,12 @@ bool IsValidationMessageVisible(const Element& anchor) override { return true; } + void WillUnloadDocument(const Document&) override { + will_unload_document_was_called = true; + } + void DocumentDetached(const Document&) override { + document_detached_was_called = true; + } void WillBeDestroyed() override {} // DEFINE_INLINE_VIRTUAL_TRACE() { ValidationMessageClient::trace(visitor); } @@ -816,6 +826,8 @@ // prepareForCommit() unloads the document, and shutdown. GetDocument().GetFrame()->PrepareForCommit(); + EXPECT_TRUE(mock_client->will_unload_document_was_called); + EXPECT_TRUE(mock_client->document_detached_was_called); // Unload handler tried to show a validation message, but it should fail. EXPECT_FALSE(mock_client->show_validation_message_was_called);
diff --git a/third_party/WebKit/Source/web/tests/IntersectionObserverTest.cpp b/third_party/WebKit/Source/core/dom/IntersectionObserverTest.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/IntersectionObserverTest.cpp rename to third_party/WebKit/Source/core/dom/IntersectionObserverTest.cpp
diff --git a/third_party/WebKit/Source/web/tests/ResizeObserverTest.cpp b/third_party/WebKit/Source/core/dom/ResizeObserverTest.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/ResizeObserverTest.cpp rename to third_party/WebKit/Source/core/dom/ResizeObserverTest.cpp
diff --git a/third_party/WebKit/Source/web/tests/ShadowDOMV0Test.cpp b/third_party/WebKit/Source/core/dom/shadow/ShadowDOMV0Test.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/ShadowDOMV0Test.cpp rename to third_party/WebKit/Source/core/dom/shadow/ShadowDOMV0Test.cpp
diff --git a/third_party/WebKit/Source/web/tests/TextFinderTest.cpp b/third_party/WebKit/Source/core/editing/TextFinderTest.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/TextFinderTest.cpp rename to third_party/WebKit/Source/core/editing/TextFinderTest.cpp
diff --git a/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp b/third_party/WebKit/Source/core/events/WebInputEventConversionTest.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp rename to third_party/WebKit/Source/core/events/WebInputEventConversionTest.cpp
diff --git a/third_party/WebKit/Source/core/exported/DEPS b/third_party/WebKit/Source/core/exported/DEPS index 09e1f4ec..7925eccdb 100644 --- a/third_party/WebKit/Source/core/exported/DEPS +++ b/third_party/WebKit/Source/core/exported/DEPS
@@ -3,4 +3,8 @@ # exported. "+core/exported", "+public/web", + # We do not want any new dependencies on Web(Local|Remote)FrameBase.h until + # we resolve the control layer. + "+core/frame/WebLocalFrameBase.h", + "+core/frame/WebRemoteFrameBase.h" ]
diff --git a/third_party/WebKit/Source/web/tests/WebDocumentTest.cpp b/third_party/WebKit/Source/core/exported/WebDocumentTest.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/WebDocumentTest.cpp rename to third_party/WebKit/Source/core/exported/WebDocumentTest.cpp
diff --git a/third_party/WebKit/Source/web/tests/WebFrameSerializerTest.cpp b/third_party/WebKit/Source/core/exported/WebFrameSerializerTest.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/WebFrameSerializerTest.cpp rename to third_party/WebKit/Source/core/exported/WebFrameSerializerTest.cpp
diff --git a/third_party/WebKit/Source/web/tests/WebRangeTest.cpp b/third_party/WebKit/Source/core/exported/WebRangeTest.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/WebRangeTest.cpp rename to third_party/WebKit/Source/core/exported/WebRangeTest.cpp
diff --git a/third_party/WebKit/Source/web/tests/WebScopedWindowFocusAllowedIndicatorTest.cpp b/third_party/WebKit/Source/core/exported/WebScopedWindowFocusAllowedIndicatorTest.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/WebScopedWindowFocusAllowedIndicatorTest.cpp rename to third_party/WebKit/Source/core/exported/WebScopedWindowFocusAllowedIndicatorTest.cpp
diff --git a/third_party/WebKit/Source/web/tests/WebSearchableFormDataTest.cpp b/third_party/WebKit/Source/core/exported/WebSearchableFormDataTest.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/WebSearchableFormDataTest.cpp rename to third_party/WebKit/Source/core/exported/WebSearchableFormDataTest.cpp
diff --git a/third_party/WebKit/Source/web/tests/WebSelectorTest.cpp b/third_party/WebKit/Source/core/exported/WebSelectorTest.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/WebSelectorTest.cpp rename to third_party/WebKit/Source/core/exported/WebSelectorTest.cpp
diff --git a/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp b/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp index fdc6f8b..bcd9557 100644 --- a/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp +++ b/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp
@@ -188,8 +188,6 @@ main_frame_->DataSource()->SetServiceWorkerNetworkProvider( client_->CreateServiceWorkerNetworkProvider()); main_script_loader_ = WorkerScriptLoader::Create(); - main_script_loader_->SetRequestContext( - WebURLRequest::kRequestContextSharedWorker); loading_document_ = main_frame_->GetFrame()->GetDocument(); WebURLRequest::FetchRequestMode fetch_request_mode = @@ -202,7 +200,8 @@ } main_script_loader_->LoadAsynchronously( - *loading_document_.Get(), url_, fetch_request_mode, + *loading_document_.Get(), url_, + WebURLRequest::kRequestContextSharedWorker, fetch_request_mode, fetch_credentials_mode, creation_address_space_, Bind(&WebSharedWorkerImpl::DidReceiveScriptLoaderResponse, WTF::Unretained(this)),
diff --git a/third_party/WebKit/Source/web/tests/WebUserGestureTokenTest.cpp b/third_party/WebKit/Source/core/exported/WebUserGestureTokenTest.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/WebUserGestureTokenTest.cpp rename to third_party/WebKit/Source/core/exported/WebUserGestureTokenTest.cpp
diff --git a/third_party/WebKit/Source/web/tests/WebViewTest.cpp b/third_party/WebKit/Source/core/exported/WebViewTest.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/WebViewTest.cpp rename to third_party/WebKit/Source/core/exported/WebViewTest.cpp
diff --git a/third_party/WebKit/Source/web/tests/BrowserControlsTest.cpp b/third_party/WebKit/Source/core/frame/BrowserControlsTest.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/BrowserControlsTest.cpp rename to third_party/WebKit/Source/core/frame/BrowserControlsTest.cpp
diff --git a/third_party/WebKit/Source/web/tests/FrameSerializerTest.cpp b/third_party/WebKit/Source/core/frame/FrameSerializerTest.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/FrameSerializerTest.cpp rename to third_party/WebKit/Source/core/frame/FrameSerializerTest.cpp
diff --git a/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp b/third_party/WebKit/Source/core/frame/VisualViewportTest.cpp similarity index 99% rename from third_party/WebKit/Source/web/tests/VisualViewportTest.cpp rename to third_party/WebKit/Source/core/frame/VisualViewportTest.cpp index 606ec76..edcb604ce 100644 --- a/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp +++ b/third_party/WebKit/Source/core/frame/VisualViewportTest.cpp
@@ -1114,10 +1114,7 @@ x, y, std::string(negation ? "is" : "isn't") + " at expected location [" + - PrintToString(x) + - ", " + - PrintToString(y) + - "]") { + PrintToString(x) + ", " + PrintToString(y) + "]") { return arg.mouse_position.x == x && arg.mouse_position.y == y; }
diff --git a/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.cpp b/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.cpp index 4bf34611..add9daf 100644 --- a/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.cpp +++ b/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.cpp
@@ -257,6 +257,10 @@ View()->RequestDecode(image, std::move(callback)); } +DEFINE_TRACE(WebFrameWidgetBase) { + visitor->Trace(current_drag_data_); +} + // TODO(665924): Remove direct dispatches of mouse events from // PointerLockController, instead passing them through EventHandler. void WebFrameWidgetBase::PointerLockMouseEvent(
diff --git a/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.h b/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.h index ddbc9c6..dd5494c 100644 --- a/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.h +++ b/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.h
@@ -9,6 +9,7 @@ #include "core/clipboard/DataObject.h" #include "core/dom/UserGestureIndicator.h" #include "platform/graphics/paint/PaintImage.h" +#include "platform/heap/Handle.h" #include "platform/wtf/Assertions.h" #include "public/platform/WebCoalescedInputEvent.h" #include "public/platform/WebDragData.h" @@ -28,8 +29,11 @@ struct WebPoint; class CORE_EXPORT WebFrameWidgetBase - : public NON_EXPORTED_BASE(WebFrameWidget) { + : public GarbageCollectedFinalized<WebFrameWidgetBase>, + public NON_EXPORTED_BASE(WebFrameWidget) { public: + virtual ~WebFrameWidgetBase() {} + virtual bool ForSubframe() const = 0; virtual void ScheduleAnimation() = 0; virtual CompositorWorkerProxyClient* CreateCompositorWorkerProxyClient() = 0; @@ -91,6 +95,8 @@ void RequestDecode(const PaintImage&, std::unique_ptr<WTF::Function<void(bool)>> callback); + DECLARE_VIRTUAL_TRACE(); + protected: enum DragAction { kDragEnter, kDragOver }; @@ -111,8 +117,11 @@ // the page is shutting down, but will be valid at all other times. Page* GetPage() const; + // Helper function to process events while pointer locked. + void PointerLockMouseEvent(const WebCoalescedInputEvent&); + // A copy of the web drop data object we received from the browser. - Persistent<DataObject> current_drag_data_; + Member<DataObject> current_drag_data_; bool doing_drag_and_drop_ = false; @@ -124,9 +133,6 @@ // current drop target in this WebView (the drop target can accept the drop). WebDragOperation drag_operation_ = kWebDragOperationNone; - // Helper function to process events while pointer locked. - void PointerLockMouseEvent(const WebCoalescedInputEvent&); - private: void CancelDrag(); LocalFrame* FocusedLocalFrameInWidget() const;
diff --git a/third_party/WebKit/Source/core/frame/WebViewFrameWidget.cpp b/third_party/WebKit/Source/core/frame/WebViewFrameWidget.cpp index aa88b008..4e574b6 100644 --- a/third_party/WebKit/Source/core/frame/WebViewFrameWidget.cpp +++ b/third_party/WebKit/Source/core/frame/WebViewFrameWidget.cpp
@@ -13,7 +13,10 @@ WebViewFrameWidget::WebViewFrameWidget(WebWidgetClient& client, WebViewBase& web_view, WebLocalFrameBase& main_frame) - : client_(&client), web_view_(&web_view), main_frame_(&main_frame) { + : client_(&client), + web_view_(&web_view), + main_frame_(&main_frame), + self_keep_alive_(this) { main_frame_->SetFrameWidget(this); web_view_->SetCompositorVisibility(true); } @@ -33,8 +36,7 @@ // Note: this intentionally does not forward to WebView::close(), to make it // easier to untangle the cleanup logic later. - - delete this; + self_keep_alive_.Clear(); } WebSize WebViewFrameWidget::Size() { @@ -253,4 +255,9 @@ return web_view_->CoreHitTestResultAt(point); } +DEFINE_TRACE(WebViewFrameWidget) { + visitor->Trace(main_frame_); + WebFrameWidgetBase::Trace(visitor); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/WebViewFrameWidget.h b/third_party/WebKit/Source/core/frame/WebViewFrameWidget.h index 100ca0e..1538173a 100644 --- a/third_party/WebKit/Source/core/frame/WebViewFrameWidget.h +++ b/third_party/WebKit/Source/core/frame/WebViewFrameWidget.h
@@ -9,6 +9,7 @@ #include "core/frame/WebFrameWidgetBase.h" #include "core/frame/WebLocalFrameBase.h" #include "platform/heap/Handle.h" +#include "platform/heap/SelfKeepAlive.h" #include "platform/wtf/Noncopyable.h" #include "platform/wtf/RefPtr.h" @@ -107,10 +108,14 @@ WebWidgetClient* Client() const override { return client_; } HitTestResult CoreHitTestResultAt(const WebPoint&) override; + DECLARE_VIRTUAL_TRACE(); + private: WebWidgetClient* client_; RefPtr<WebViewBase> web_view_; - Persistent<WebLocalFrameBase> main_frame_; + Member<WebLocalFrameBase> main_frame_; + + SelfKeepAlive<WebViewFrameWidget> self_keep_alive_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/HTMLFormControlElementTest.cpp b/third_party/WebKit/Source/core/html/HTMLFormControlElementTest.cpp index 11b697b0..470da5e 100644 --- a/third_party/WebKit/Source/core/html/HTMLFormControlElementTest.cpp +++ b/third_party/WebKit/Source/core/html/HTMLFormControlElementTest.cpp
@@ -41,6 +41,8 @@ return anchor_ == &anchor; } + void WillUnloadDocument(const Document&) override {} + void DocumentDetached(const Document&) override {} void WillBeDestroyed() override {} DEFINE_INLINE_VIRTUAL_TRACE() { visitor->Trace(anchor_);
diff --git a/third_party/WebKit/Source/web/tests/HTMLDocumentParserLoadingTest.cpp b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParserLoadingTest.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/HTMLDocumentParserLoadingTest.cpp rename to third_party/WebKit/Source/core/html/parser/HTMLDocumentParserLoadingTest.cpp
diff --git a/third_party/WebKit/Source/web/tests/DocumentLoaderTest.cpp b/third_party/WebKit/Source/core/loader/DocumentLoaderTest.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/DocumentLoaderTest.cpp rename to third_party/WebKit/Source/core/loader/DocumentLoaderTest.cpp
diff --git a/third_party/WebKit/Source/core/page/Page.cpp b/third_party/WebKit/Source/core/page/Page.cpp index 38312cd3..4a08302 100644 --- a/third_party/WebKit/Source/core/page/Page.cpp +++ b/third_party/WebKit/Source/core/page/Page.cpp
@@ -253,9 +253,16 @@ main_frame_ = main_frame; } +void Page::WillUnloadDocument(const Document& document) { + if (validation_message_client_) + validation_message_client_->WillUnloadDocument(document); +} + void Page::DocumentDetached(Document* document) { pointer_lock_controller_->DocumentDetached(document); context_menu_controller_->DocumentDetached(document); + if (validation_message_client_) + validation_message_client_->DocumentDetached(*document); hosts_using_features_.DocumentDetached(*document); }
diff --git a/third_party/WebKit/Source/core/page/Page.h b/third_party/WebKit/Source/core/page/Page.h index 6af63ad9..ccaea49b 100644 --- a/third_party/WebKit/Source/core/page/Page.h +++ b/third_party/WebKit/Source/core/page/Page.h
@@ -152,6 +152,7 @@ return ToLocalFrame(main_frame_); } + void WillUnloadDocument(const Document&); void DocumentDetached(Document*); bool OpenedByDOM() const;
diff --git a/third_party/WebKit/Source/core/page/ValidationMessageClient.h b/third_party/WebKit/Source/core/page/ValidationMessageClient.h index 667f927..396f4b5 100644 --- a/third_party/WebKit/Source/core/page/ValidationMessageClient.h +++ b/third_party/WebKit/Source/core/page/ValidationMessageClient.h
@@ -32,6 +32,7 @@ namespace blink { +class Document; class Element; class ValidationMessageClient : public GarbageCollectedMixin { @@ -55,6 +56,9 @@ // is visible. virtual bool IsValidationMessageVisible(const Element& anchor) = 0; + virtual void WillUnloadDocument(const Document&) = 0; + virtual void DocumentDetached(const Document&) = 0; + virtual void WillBeDestroyed() = 0; DEFINE_INLINE_VIRTUAL_TRACE() {}
diff --git a/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.cpp b/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.cpp index 575f9bf..f2e3c3b 100644 --- a/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.cpp +++ b/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.cpp
@@ -115,6 +115,16 @@ return current_anchor_ == &anchor; } +void ValidationMessageClientImpl::WillUnloadDocument(const Document& document) { + if (current_anchor_ && current_anchor_->GetDocument() == document) + HideValidationMessage(*current_anchor_); +} + +void ValidationMessageClientImpl::DocumentDetached(const Document& document) { + DCHECK(!current_anchor_ || current_anchor_->GetDocument() != document) + << "willUnloadDocument() should be called beforehand."; +} + void ValidationMessageClientImpl::CheckAnchorStatus(TimerBase*) { DCHECK(current_anchor_); if (MonotonicallyIncreasingTime() >= finish_time_ || !CurrentView()) {
diff --git a/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.h b/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.h index 1b61b2c..0816472 100644 --- a/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.h +++ b/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.h
@@ -63,6 +63,8 @@ TextDirection sub_message_dir) override; void HideValidationMessage(const Element& anchor) override; bool IsValidationMessageVisible(const Element& anchor) override; + void WillUnloadDocument(const Document&) override; + void DocumentDetached(const Document&) override; void WillBeDestroyed() override; // PopupOpeningObserver function
diff --git a/third_party/WebKit/Source/web/tests/ScrollingCoordinatorTest.cpp b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinatorTest.cpp similarity index 100% rename from third_party/WebKit/Source/web/tests/ScrollingCoordinatorTest.cpp rename to third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinatorTest.cpp
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerBase.cpp b/third_party/WebKit/Source/core/workers/InProcessWorkerBase.cpp index f737b142..2b5e1f7 100644 --- a/third_party/WebKit/Source/core/workers/InProcessWorkerBase.cpp +++ b/third_party/WebKit/Source/core/workers/InProcessWorkerBase.cpp
@@ -61,7 +61,8 @@ script_loader_ = WorkerScriptLoader::Create(); script_loader_->LoadAsynchronously( - *context, script_url, fetch_request_mode, fetch_credentials_mode, + *context, script_url, WebURLRequest::kRequestContextWorker, + fetch_request_mode, fetch_credentials_mode, context->GetSecurityContext().AddressSpace(), WTF::Bind(&InProcessWorkerBase::OnResponse, WrapPersistent(this)), WTF::Bind(&InProcessWorkerBase::OnFinished, WrapPersistent(this)));
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp index f080592..4a3768d 100644 --- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
@@ -192,9 +192,8 @@ for (const KURL& complete_url : completed_urls) { RefPtr<WorkerScriptLoader> script_loader(WorkerScriptLoader::Create()); - script_loader->SetRequestContext(WebURLRequest::kRequestContextScript); script_loader->LoadSynchronously( - execution_context, complete_url, + execution_context, complete_url, WebURLRequest::kRequestContextScript, execution_context.GetSecurityContext().AddressSpace()); // If the fetching attempt failed, throw a NetworkError exception and
diff --git a/third_party/WebKit/Source/core/workers/WorkerScriptLoader.cpp b/third_party/WebKit/Source/core/workers/WorkerScriptLoader.cpp index 2e0e5139..53423ca 100644 --- a/third_party/WebKit/Source/core/workers/WorkerScriptLoader.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerScriptLoader.cpp
@@ -51,7 +51,6 @@ WorkerScriptLoader::WorkerScriptLoader() : response_callback_(nullptr), finished_callback_(nullptr), - request_context_(WebURLRequest::kRequestContextWorker), response_address_space_(kWebAddressSpacePublic) {} WorkerScriptLoader::~WorkerScriptLoader() { @@ -66,11 +65,16 @@ void WorkerScriptLoader::LoadSynchronously( ExecutionContext& execution_context, const KURL& url, + WebURLRequest::RequestContext request_context, WebAddressSpace creation_address_space) { url_ = url; execution_context_ = &execution_context; - ResourceRequest request(CreateResourceRequest(creation_address_space)); + ResourceRequest request(url); + request.SetHTTPMethod(HTTPNames::GET); + request.SetExternalRequestStateFromRequestorAddressSpace( + creation_address_space); + request.SetRequestContext(request_context); request.SetFetchCredentialsMode(WebURLRequest::kFetchCredentialsModeInclude); SECURITY_DCHECK(execution_context.IsWorkerGlobalScope()); @@ -91,6 +95,7 @@ void WorkerScriptLoader::LoadAsynchronously( ExecutionContext& execution_context, const KURL& url, + WebURLRequest::RequestContext request_context, WebURLRequest::FetchRequestMode fetch_request_mode, WebURLRequest::FetchCredentialsMode fetch_credentials_mode, WebAddressSpace creation_address_space, @@ -102,7 +107,11 @@ url_ = url; execution_context_ = &execution_context; - ResourceRequest request(CreateResourceRequest(creation_address_space)); + ResourceRequest request(url); + request.SetHTTPMethod(HTTPNames::GET); + request.SetExternalRequestStateFromRequestorAddressSpace( + creation_address_space); + request.SetRequestContext(request_context); request.SetFetchCredentialsMode(fetch_credentials_mode); ThreadableLoaderOptions options; @@ -128,16 +137,6 @@ return response_url_; } -ResourceRequest WorkerScriptLoader::CreateResourceRequest( - WebAddressSpace creation_address_space) { - ResourceRequest request(url_); - request.SetHTTPMethod(HTTPNames::GET); - request.SetRequestContext(request_context_); - request.SetExternalRequestStateFromRequestorAddressSpace( - creation_address_space); - return request; -} - void WorkerScriptLoader::DidReceiveResponse( unsigned long identifier, const ResourceResponse& response,
diff --git a/third_party/WebKit/Source/core/workers/WorkerScriptLoader.h b/third_party/WebKit/Source/core/workers/WorkerScriptLoader.h index 9dea16d..e4be86e 100644 --- a/third_party/WebKit/Source/core/workers/WorkerScriptLoader.h +++ b/third_party/WebKit/Source/core/workers/WorkerScriptLoader.h
@@ -62,11 +62,13 @@ void LoadSynchronously(ExecutionContext&, const KURL&, + WebURLRequest::RequestContext, WebAddressSpace); // Note that callbacks could be invoked before loadAsynchronously() returns. void LoadAsynchronously(ExecutionContext&, const KURL&, + WebURLRequest::RequestContext, WebURLRequest::FetchRequestMode, WebURLRequest::FetchCredentialsMode, WebAddressSpace, @@ -117,17 +119,12 @@ void DidFail(const ResourceError&) override; void DidFailRedirectCheck() override; - void SetRequestContext(WebURLRequest::RequestContext request_context) { - request_context_ = request_context; - } - private: friend class WTF::RefCounted<WorkerScriptLoader>; WorkerScriptLoader(); ~WorkerScriptLoader() override; - ResourceRequest CreateResourceRequest(WebAddressSpace); void NotifyError(); void NotifyFinished(); @@ -152,7 +149,6 @@ unsigned long identifier_ = 0; long long app_cache_id_ = 0; std::unique_ptr<Vector<char>> cached_metadata_; - WebURLRequest::RequestContext request_context_; Persistent<ContentSecurityPolicy> content_security_policy_; Persistent<ExecutionContext> execution_context_; WebAddressSpace response_address_space_;
diff --git a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp index f7b78ee..3d3b5cf1 100644 --- a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp +++ b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp
@@ -331,10 +331,9 @@ main_frame_->DataSource()->SetServiceWorkerNetworkProvider( worker_context_client_->CreateServiceWorkerNetworkProvider()); main_script_loader_ = WorkerScriptLoader::Create(); - main_script_loader_->SetRequestContext( - WebURLRequest::kRequestContextServiceWorker); main_script_loader_->LoadAsynchronously( *main_frame_->GetFrame()->GetDocument(), worker_start_data_.script_url, + WebURLRequest::kRequestContextServiceWorker, WebURLRequest::kFetchRequestModeSameOrigin, WebURLRequest::kFetchCredentialsModeSameOrigin, worker_start_data_.address_space, nullptr,
diff --git a/third_party/WebKit/Source/web/BUILD.gn b/third_party/WebKit/Source/web/BUILD.gn index bc18d10..f719686 100644 --- a/third_party/WebKit/Source/web/BUILD.gn +++ b/third_party/WebKit/Source/web/BUILD.gn
@@ -84,20 +84,16 @@ sources = [ # FIXME: Move the tests from web/tests/ to appropriate places. # crbug.com/353585 + "tests/AccessibilityObjectModelTest.cpp", - "tests/BrowserControlsTest.cpp", "tests/ChromeClientImplTest.cpp", "tests/CompositorWorkerTest.cpp", "tests/DeferredLoadingTest.cpp", - "tests/DocumentLoaderTest.cpp", "tests/DocumentLoadingRenderingTest.cpp", "tests/FakeWebPlugin.cpp", "tests/FakeWebPlugin.h", - "tests/FrameSerializerTest.cpp", - "tests/HTMLDocumentParserLoadingTest.cpp", "tests/HTMLImportSheetsTest.cpp", "tests/ImeOnFocusTest.cpp", - "tests/IntersectionObserverTest.cpp", "tests/KeyboardTest.cpp", "tests/LayoutGeometryMapTest.cpp", "tests/LinkElementLoadingTest.cpp", @@ -109,41 +105,27 @@ "tests/NGInlineLayoutTest.cpp", "tests/PrerenderingTest.cpp", "tests/ProgrammaticScrollTest.cpp", - "tests/ResizeObserverTest.cpp", "tests/RootScrollerTest.cpp", "tests/RunAllTests.cpp", "tests/ScreenWakeLockTest.cpp", "tests/ScrollMetricsTest.cpp", "tests/ScrollbarsTest.cpp", - "tests/ScrollingCoordinatorTest.cpp", - "tests/ShadowDOMV0Test.cpp", "tests/SmoothScrollTest.cpp", "tests/SpinLockTest.cpp", - "tests/TextFinderTest.cpp", "tests/TextSelectionRepaintTest.cpp", "tests/TimerPerfTest.cpp", "tests/TouchActionTest.cpp", "tests/ViewportTest.cpp", "tests/VirtualTimeTest.cpp", - "tests/VisualViewportTest.cpp", "tests/WebDocumentSubresourceFilterTest.cpp", - "tests/WebDocumentTest.cpp", "tests/WebFrameSerializerSanitizationTest.cpp", - "tests/WebFrameSerializerTest.cpp", "tests/WebFrameTest.cpp", "tests/WebHelperPluginTest.cpp", "tests/WebImageTest.cpp", - "tests/WebInputEventConversionTest.cpp", "tests/WebMeaningfulLayoutsTest.cpp", "tests/WebPluginContainerTest.cpp", - "tests/WebRangeTest.cpp", - "tests/WebScopedWindowFocusAllowedIndicatorTest.cpp", - "tests/WebSearchableFormDataTest.cpp", - "tests/WebSelectorTest.cpp", "tests/WebURLRequestTest.cpp", "tests/WebURLResponseTest.cpp", - "tests/WebUserGestureTokenTest.cpp", - "tests/WebViewTest.cpp", "tests/WindowProxyTest.cpp", "tests/scheduler/ActiveConnectionThrottlingTest.cpp", "tests/scheduler/FrameThrottlingTest.cpp",
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp index 8078818..ef725e4e 100644 --- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp +++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
@@ -139,6 +139,7 @@ DEFINE_TRACE(WebFrameWidgetImpl) { visitor->Trace(local_root_); visitor->Trace(mouse_capture_node_); + WebFrameWidgetBase::Trace(visitor); } // WebWidget ------------------------------------------------------------------
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.h b/third_party/WebKit/Source/web/WebFrameWidgetImpl.h index 1802aa3..a3290d9 100644 --- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.h +++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.h
@@ -62,10 +62,8 @@ using WebFrameWidgetsSet = PersistentHeapHashSet<WeakMember<WebFrameWidgetImpl>>; -class WebFrameWidgetImpl final - : public GarbageCollectedFinalized<WebFrameWidgetImpl>, - public WebFrameWidgetBase, - public PageWidgetEventHandler { +class WebFrameWidgetImpl final : public WebFrameWidgetBase, + public PageWidgetEventHandler { public: static WebFrameWidgetImpl* Create(WebWidgetClient*, WebLocalFrame*);
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp index e13db07d..07bff0e 100644 --- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp +++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -1581,7 +1581,6 @@ blink::InterfaceRegistry* interface_registry) : WebLocalFrameBase(scope), local_frame_client_impl_(LocalFrameClientImpl::Create(this)), - frame_widget_(0), client_(client), autofill_client_(0), input_events_scale_factor_for_emulation_(1), @@ -1619,6 +1618,7 @@ visitor->Trace(local_frame_client_impl_); visitor->Trace(frame_); visitor->Trace(dev_tools_agent_); + visitor->Trace(frame_widget_); visitor->Trace(text_finder_); visitor->Trace(print_context_); visitor->Trace(context_menu_node_);
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.h b/third_party/WebKit/Source/web/WebLocalFrameImpl.h index 1d4fd88d..cf6c29b 100644 --- a/third_party/WebKit/Source/web/WebLocalFrameImpl.h +++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.h
@@ -485,7 +485,7 @@ // This is set if the frame is the root of a local frame tree, and requires a // widget for layout. - WebFrameWidgetBase* frame_widget_; + Member<WebFrameWidgetBase> frame_widget_; WebFrameClient* client_; WebAutofillClient* autofill_client_;
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 16c1736..fb56385 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -39635,6 +39635,17 @@ </summary> </histogram> +<histogram name="Net.ResourceDispatcherHost.PeakOutstandingRequests" + units="requests"> + <owner>ksakamoto@chromium.org</owner> + <summary> + The largest number of outstanding requests handled by the resource + dispatcher host, during the last sample interval (60 seconds). Not logged if + there are no outstanding requests in the interval. This metric is temporary + for the Loading Dispatcher v0 (crbug.com/723233), and will be removed soon. + </summary> +</histogram> + <histogram name="Net.ResourceLoader.ExpectedContentSizeResult" enum="ResourceLoaderExpectedContentSizeResult"> <owner>maksim.sisov@intel.com</owner> @@ -44849,10 +44860,14 @@ <histogram name="NewTabPage.NumberOfTiles"> <owner>treib@chromium.org</owner> <summary> - The number of tiles that are displayed on the NTP, no matter if they are - thumbnails, gray tiles, or external tiles. Recorded before reloading the - suggestions, navigating to a URL, switching tabs, changing the active window - or closing the tab/shutting down Chrome. + The number of tiles that are on the NTP, no matter if they are thumbnails, + gray tiles, or external tiles. Recorded before reloading the suggestions, + navigating to a URL, switching tabs, changing the active window or closing + the tab/shutting down Chrome. The sum of this histogram does not have to + equal to the total count of tile impressions (such as the total count in + NewTabPage.TileType). The reason is that not all tiles have to be impressed + initially (e.g., the second row of tiles may be initially out of sight on + iOS). </summary> </histogram> @@ -90487,6 +90502,12 @@ <affected-histogram name="ModuleIntegrityVerification.Difference"/> </histogram_suffixes> +<histogram_suffixes name="MultiTabLoading" separator="."> + <suffix name="MultiTabLoading" label="There were multiple loading tabs."/> + <affected-histogram + name="Net.ResourceDispatcherHost.PeakOutstandingRequests"/> +</histogram_suffixes> + <histogram_suffixes name="NatType" separator="."> <suffix name="NoNAT"/> <suffix name="UnknownNAT"/>