diff --git a/DEPS b/DEPS index 762c7e5..308a11b 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '5ad721e94682b51b9f773d95704f11990468fef6', + 'skia_revision': '875218ebd816eb8931c64c5018ce2dc9bc8fd695', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '00805bbf75fb604986fb77d223060d97f3b03ad1', + 'v8_revision': '1539c3a15a256290a6a2f1afcb6afc9d226ceda3', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -232,7 +232,7 @@ Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067', 'src/third_party/webrtc': - Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '3ceef5c9c324cd6cd3090e1ce0d53ccd33763681', # commit position 16807 + Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '44c51851dbdaeb2cab8be7348ecf89cb72c13510', # commit position 16820 'src/third_party/openmax_dl': Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' + Var('openmax_dl_revision'),
diff --git a/android_webview/common/crash_reporter/OWNERS b/android_webview/common/crash_reporter/OWNERS new file mode 100644 index 0000000..38324cc --- /dev/null +++ b/android_webview/common/crash_reporter/OWNERS
@@ -0,0 +1 @@ +per-file crash_keys*=rsesek@chromium.org
diff --git a/android_webview/common/crash_reporter/aw_microdump_crash_reporter.cc b/android_webview/common/crash_reporter/aw_microdump_crash_reporter.cc index 6d5e33d9..44c3b7c 100644 --- a/android_webview/common/crash_reporter/aw_microdump_crash_reporter.cc +++ b/android_webview/common/crash_reporter/aw_microdump_crash_reporter.cc
@@ -168,20 +168,23 @@ client->set_crash_signal_fd(crash_signal_fd); } ::crash_reporter::SetCrashReporterClient(client); - breakpad::SetShouldSanitizeDumps(true); + breakpad::SanitizationInfo sanitization_info; + sanitization_info.should_sanitize_dumps = true; #if !defined(COMPONENT_BUILD) - breakpad::SetSkipDumpIfPrincipalMappingNotReferenced( - reinterpret_cast<uintptr_t>(&EnableCrashReporter)); -#endif + sanitization_info.skip_dump_if_principal_mapping_not_referenced = true; + sanitization_info.address_within_principal_mapping = + reinterpret_cast<uintptr_t>(&EnableCrashReporter); +#endif // defined(COMPONENT_BUILD) bool is_browser_process = process_type.empty() || process_type == breakpad::kWebViewSingleProcessType || process_type == breakpad::kBrowserProcessType; if (is_browser_process) { - breakpad::InitCrashReporter(""); + breakpad::InitCrashReporter("", sanitization_info); } else { - breakpad::InitNonBrowserCrashReporterForAndroid(process_type); + breakpad::InitNonBrowserCrashReporterForAndroid(process_type, + sanitization_info); } g_enabled = true; }
diff --git a/android_webview/native/aw_metrics_service_client_impl.cc b/android_webview/native/aw_metrics_service_client_impl.cc index 7566b51..d1ab432a 100644 --- a/android_webview/native/aw_metrics_service_client_impl.cc +++ b/android_webview/native/aw_metrics_service_client_impl.cc
@@ -14,6 +14,7 @@ #include "components/metrics/call_stack_profile_metrics_provider.h" #include "components/metrics/enabled_state_provider.h" #include "components/metrics/gpu/gpu_metrics_provider.h" +#include "components/metrics/metrics_log_uploader.h" #include "components/metrics/metrics_pref_names.h" #include "components/metrics/metrics_service.h" #include "components/metrics/metrics_state_manager.h" @@ -204,10 +205,12 @@ AwMetricsServiceClientImpl::CreateUploader( const std::string& server_url, const std::string& mime_type, + metrics::MetricsLogUploader::MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete) { return std::unique_ptr<::metrics::MetricsLogUploader>( - new metrics::NetMetricsLogUploader( - request_context_, server_url, mime_type, on_upload_complete)); + new metrics::NetMetricsLogUploader(request_context_, server_url, + mime_type, service_type, + on_upload_complete)); } base::TimeDelta AwMetricsServiceClientImpl::GetStandardUploadInterval() {
diff --git a/android_webview/native/aw_metrics_service_client_impl.h b/android_webview/native/aw_metrics_service_client_impl.h index 75242ad..1d5ca2f 100644 --- a/android_webview/native/aw_metrics_service_client_impl.h +++ b/android_webview/native/aw_metrics_service_client_impl.h
@@ -12,6 +12,7 @@ #include "base/lazy_instance.h" #include "base/macros.h" +#include "components/metrics/metrics_log_uploader.h" namespace metrics { class MetricsStateManager; @@ -55,6 +56,7 @@ std::unique_ptr<metrics::MetricsLogUploader> CreateUploader( const std::string& server_url, const std::string& mime_type, + metrics::MetricsLogUploader::MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete) override; base::TimeDelta GetStandardUploadInterval() override;
diff --git a/base/trace_event/memory_infra_background_whitelist.cc b/base/trace_event/memory_infra_background_whitelist.cc index 9230fe5..b45eec6 100644 --- a/base/trace_event/memory_infra_background_whitelist.cc +++ b/base/trace_event/memory_infra_background_whitelist.cc
@@ -32,6 +32,7 @@ "ProcessMemoryMetrics", "Skia", "Sql", + "URLRequestContext", "V8Isolate", "WinHeap", "SyncDirectory", @@ -61,6 +62,17 @@ "malloc", "malloc/allocated_objects", "malloc/metadata_fragmentation_caches", + "net/http_network_session_0x?", + "net/http_network_session_0x?/quic_stream_factory", + "net/http_network_session_0x?/socket_pool", + "net/http_network_session_0x?/spdy_session_pool", + "net/http_network_session_0x?/stream_factory", + "net/sdch_manager_0x?", + "net/ssl_session_cache", + "net/url_request_context_0x?", + "net/url_request_context_0x?/http_cache", + "net/url_request_context_0x?/http_network_session", + "net/url_request_context_0x?/sdch_manager", "web_cache/Image_resources", "web_cache/CSS stylesheet_resources", "web_cache/Script_resources",
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 3a95db3..6f50b97 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -649,13 +649,6 @@ # non-component builds, will ensure the export symbol table is correct. ":verify_chrome_framework_order", ] - - # Only official builds that include Widevine need the widevine - # signature file. - if (is_chrome_branded && enable_pepper_cdms) { - sources += [ "$root_out_dir/$chrome_framework_name.sig" ] - public_deps += [ ":sign_chrome_framework_for_widevine" ] - } } action("clean_up_old_versions") { @@ -869,25 +862,12 @@ ":widevine_cdm_library_copy", "//third_party/widevine/cdm:widevinecdmadapter", ] - - # Signatures are only generated for official chrome. - if (is_chrome_branded) { - sources += [ - "$root_out_dir/$widevine_cdm_path/widevinecdmadapter.plugin.sig", - "$root_out_dir/libwidevinecdm.dylib.sig", - ] - public_deps += [ ":sign_cdm_adapter_for_widevine" ] - } } copy("widevine_cdm_library_copy") { sources = [ "$root_out_dir/$widevine_cdm_path/libwidevinecdm.dylib", ] - if (is_chrome_branded) { - sources += - [ "$root_out_dir/$widevine_cdm_path/libwidevinecdm.dylib.sig" ] - } outputs = [ "$root_out_dir/{{source_file_part}}", ] @@ -907,25 +887,6 @@ "//third_party/widevine/cdm:widevine_cdm_manifest", ] } - - widevine_sign_file("sign_cdm_adapter_for_widevine") { - file = "$root_out_dir/$widevine_cdm_path/widevinecdmadapter.plugin" - deps = [ - "//third_party/widevine/cdm:widevinecdmadapter", - ] - } - - widevine_sign_file("sign_chrome_framework_for_widevine") { - file = "$root_out_dir/$chrome_framework_name.framework/" - if (defined(chrome_framework_version)) { - file += "Versions/$chrome_framework_version/" - } - file += "$chrome_framework_name" - signature_file = "$root_out_dir/$chrome_framework_name.sig" - deps = [ - ":chrome_framework", - ] - } } group("widevine_cdm_library") {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/ContextMenuManager.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/ContextMenuManager.java index 101a74c..4078a2c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/ContextMenuManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/ContextMenuManager.java
@@ -185,7 +185,7 @@ mDelegate.openItem(WindowOpenDisposition.NEW_WINDOW); return true; case ID_OPEN_IN_NEW_TAB: - mDelegate.openItem(WindowOpenDisposition.NEW_FOREGROUND_TAB); + mDelegate.openItem(WindowOpenDisposition.NEW_BACKGROUND_TAB); return true; case ID_OPEN_IN_INCOGNITO_TAB: mDelegate.openItem(WindowOpenDisposition.OFF_THE_RECORD);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java index ebbbd514..7e0fe007 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -137,13 +137,6 @@ } /** - * Object that registered through the {@link NewTabPageManager}, and that will be notified when - * the {@link NewTabPage} is destroyed. - * @see NewTabPageManager#addDestructionObserver(DestructionObserver) - */ - public interface DestructionObserver { void onDestroy(); } - - /** * Handles user interaction with the fakebox (the URL bar in the NTP). */ public interface FakeboxDelegate {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java index f584026..53d8d2f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -35,13 +35,13 @@ import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ntp.LogoBridge.Logo; import org.chromium.chrome.browser.ntp.LogoBridge.LogoObserver; -import org.chromium.chrome.browser.ntp.NewTabPage.DestructionObserver; import org.chromium.chrome.browser.ntp.NewTabPage.OnSearchBoxScrollListener; import org.chromium.chrome.browser.ntp.cards.CardsVariationParameters; import org.chromium.chrome.browser.ntp.cards.NewTabPageAdapter; import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.suggestions.DestructionObserver; import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate; import org.chromium.chrome.browser.suggestions.Tile; import org.chromium.chrome.browser.suggestions.TileGridLayout; @@ -229,10 +229,13 @@ } }); + OfflinePageBridge offlinePageBridge = + OfflinePageBridge.getForProfile(Profile.getLastUsedProfile()); + mTileGridLayout = (TileGridLayout) mNewTabPageLayout.findViewById(R.id.tile_grid_layout); mTileGridLayout.setMaxRows(getMaxTileRows(searchProviderHasLogo)); mTileGroup = new TileGroup(mActivity, mManager, mContextMenuManager, mTileGroupDelegate, - /* observer = */ this, getTileTitleLines()); + /* observer = */ this, offlinePageBridge, getTileTitleLines()); mSearchProviderLogoView = (LogoView) mNewTabPageLayout.findViewById(R.id.search_provider_logo); @@ -249,8 +252,7 @@ // Set up snippets NewTabPageAdapter newTabPageAdapter = new NewTabPageAdapter(mManager, mNewTabPageLayout, - mUiConfig, OfflinePageBridge.getForProfile(Profile.getLastUsedProfile()), - mContextMenuManager, /* tileGroupDelegate = */ null); + mUiConfig, offlinePageBridge, mContextMenuManager, /* tileGroupDelegate = */ null); mRecyclerView.setAdapter(newTabPageAdapter); int scrollOffset; @@ -879,6 +881,12 @@ } @Override + public void onTileOfflineBadgeVisibilityChanged(Tile tile) { + mTileGridLayout.updateOfflineBadge(tile); + mSnapshotTileGridChanged = true; + } + + @Override public void onLoadTaskAdded() { mPendingLoadTasks++; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java index aad8ce4..676f009c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
@@ -85,7 +85,8 @@ mRoot.addChild(mAboveTheFold); } if (tileGroupDelegate != null) { - mRoot.addChild(new TileGrid(uiDelegate, mContextMenuManager, tileGroupDelegate)); + mRoot.addChild(new TileGrid( + uiDelegate, mContextMenuManager, tileGroupDelegate, offlinePageBridge)); } mRoot.addChildren(mSections, mSigninPromo, mAllDismissed, mFooter); if (mAboveTheFoldView == null
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SectionList.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SectionList.java index 24bc8c0..2f3fe25 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SectionList.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SectionList.java
@@ -6,7 +6,6 @@ import org.chromium.base.Log; import org.chromium.base.VisibleForTesting; -import org.chromium.chrome.browser.ntp.NewTabPage.DestructionObserver; import org.chromium.chrome.browser.ntp.snippets.CategoryInt; import org.chromium.chrome.browser.ntp.snippets.CategoryStatus; import org.chromium.chrome.browser.ntp.snippets.CategoryStatus.CategoryStatusEnum; @@ -15,6 +14,7 @@ import org.chromium.chrome.browser.ntp.snippets.SnippetsBridge; import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; +import org.chromium.chrome.browser.suggestions.DestructionObserver; import org.chromium.chrome.browser.suggestions.SuggestionsRanker; import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java index b4777bc..9b858c98 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java
@@ -15,13 +15,13 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; import org.chromium.chrome.browser.ntp.ContextMenuManager; -import org.chromium.chrome.browser.ntp.NewTabPage.DestructionObserver; import org.chromium.chrome.browser.preferences.ChromePreferenceManager; import org.chromium.chrome.browser.signin.AccountSigninActivity; import org.chromium.chrome.browser.signin.SigninAccessPoint; import org.chromium.chrome.browser.signin.SigninManager; import org.chromium.chrome.browser.signin.SigninManager.SignInAllowedObserver; import org.chromium.chrome.browser.signin.SigninManager.SignInStateObserver; +import org.chromium.chrome.browser.suggestions.DestructionObserver; import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate; import org.chromium.chrome.browser.widget.displaystyle.UiConfig; @@ -64,7 +64,7 @@ } /** - * @returns a {@link DestructionObserver} observer that updates the visibility of the signin + * @return a {@link DestructionObserver} observer that updates the visibility of the signin * promo and unregisters itself when the New Tab Page is destroyed. */ @Nullable
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java index 0581597..6675201 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.ntp.cards; import android.support.annotation.CallSuper; +import android.support.annotation.Nullable; import org.chromium.base.Callback; import org.chromium.base.Log; @@ -16,9 +17,8 @@ import org.chromium.chrome.browser.ntp.snippets.SnippetArticleViewHolder; import org.chromium.chrome.browser.ntp.snippets.SnippetsBridge; import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource; -import org.chromium.chrome.browser.offlinepages.ClientId; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; -import org.chromium.chrome.browser.offlinepages.OfflinePageItem; +import org.chromium.chrome.browser.suggestions.SuggestionsOfflineModelObserver; import org.chromium.chrome.browser.suggestions.SuggestionsRanker; import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate; @@ -39,8 +39,7 @@ private final Delegate mDelegate; private final SuggestionsCategoryInfo mCategoryInfo; - private final OfflinePageBridge mOfflinePageBridge; - private final OfflinePageBridge.OfflinePageModelObserver mOfflinePageObserver; + private final OfflineModelObserver mOfflineModelObserver; // Children private final SectionHeader mHeader; @@ -75,7 +74,6 @@ SuggestionsCategoryInfo info) { mDelegate = delegate; mCategoryInfo = info; - mOfflinePageBridge = offlinePageBridge; mHeader = new SectionHeader(info.getTitle()); mSuggestionsList = new SuggestionsList(uiDelegate, ranker, info); @@ -84,33 +82,8 @@ mProgressIndicator = new ProgressItem(); addChildren(mHeader, mSuggestionsList, mStatus, mMoreButton, mProgressIndicator); - mOfflinePageObserver = - new OfflinePageBridge.OfflinePageModelObserver() { - @Override - public void offlinePageModelLoaded() { - updateAllSnippetOfflineAvailability(); - } - - @Override - public void offlinePageAdded(OfflinePageItem addedPage) { - updateAllSnippetOfflineAvailability(); - } - - @Override - public void offlinePageDeleted(long offlineId, ClientId clientId) { - for (SnippetArticle article : mSuggestionsList) { - if (article.requiresExactOfflinePage()) continue; - Long articleOfflineId = article.getOfflinePageOfflineId(); - if (articleOfflineId == null) continue; - if (articleOfflineId.longValue() != offlineId) continue; - // The old value cannot be simply removed without a request to the - // model, because there may be an older offline page for the same - // URL. - updateSnippetOfflineAvailability(article); - } - } - }; - mOfflinePageBridge.addObserver(mOfflinePageObserver); + mOfflineModelObserver = new OfflineModelObserver(offlinePageBridge); + uiDelegate.addDestructionObserver(mOfflineModelObserver); mStatus.setVisible(!hasSuggestions()); } @@ -234,7 +207,7 @@ @Override @CallSuper public void detach() { - mOfflinePageBridge.removeObserver(mOfflinePageObserver); + mOfflineModelObserver.onDestroy(); super.detach(); } @@ -417,37 +390,12 @@ for (SnippetArticle article : suggestions) { if (!article.requiresExactOfflinePage()) { - updateSnippetOfflineAvailability(article); + mOfflineModelObserver.updateOfflinableSuggestionAvailability(article); } } } - private void updateSnippetOfflineAvailability(final SnippetArticle article) { - // This method is not applicable to articles for which the exact offline id must specified. - assert !article.requiresExactOfflinePage(); - if (!mOfflinePageBridge.isOfflinePageModelLoaded()) return; - // TabId is relevant only for recent tab offline pages, which we do not handle here, so we - // do not care about tab id. - mOfflinePageBridge.selectPageForOnlineUrl( - article.mUrl, /*tabId=*/0, new Callback<OfflinePageItem>() { - @Override - public void onResult(OfflinePageItem item) { - mSuggestionsList.updateSuggestionOfflineId( - article, item == null ? null : item.getOfflineId()); - } - }); - } - /** - * Checks which SnippetArticles are available offline and updates them with offline id of the - * matched offline page. - */ - private void updateAllSnippetOfflineAvailability() { - for (final SnippetArticle article : mSuggestionsList) { - if (article.requiresExactOfflinePage()) continue; - updateSnippetOfflineAvailability(article); - } - } /** Lets the {@link SuggestionsSection} know when a suggestion fetch has been started. */ public void onFetchStarted() { @@ -513,4 +461,20 @@ SectionHeader getHeaderItemForTesting() { return mHeader; } + + private class OfflineModelObserver extends SuggestionsOfflineModelObserver<SnippetArticle> { + public OfflineModelObserver(OfflinePageBridge bridge) { + super(bridge); + } + + @Override + public void onSuggestionOfflineIdChanged(SnippetArticle suggestion, @Nullable Long id) { + mSuggestionsList.updateSuggestionOfflineId(suggestion, id); + } + + @Override + public Iterable<SnippetArticle> getOfflinableSuggestions() { + return mSuggestionsList; + } + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java index 7c9db0e06..96409080 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java
@@ -6,12 +6,14 @@ import android.graphics.Bitmap; import android.support.annotation.Nullable; +import org.chromium.chrome.browser.suggestions.OfflinableSuggestion; + import java.io.File; /** * Represents the data for an article card on the NTP. */ -public class SnippetArticle { +public class SnippetArticle implements OfflinableSuggestion { /** The category of this article. */ public final int mCategory; @@ -170,10 +172,7 @@ setOfflinePageOfflineId(offlinePageId); } - /** - * @return whether a snippet has to be matched with the exact offline page or with the most - * recent offline page found by the snippet's URL. - */ + @Override public boolean requiresExactOfflinePage() { return isDownload() || isRecentTab(); } @@ -201,15 +200,17 @@ setOfflinePageOfflineId(offlinePageId); } - /** Sets offline id of the corresponding to the snippet offline page. Null to clear.*/ + @Override + public String getUrl() { + return mUrl; + } + + @Override public void setOfflinePageOfflineId(@Nullable Long offlineId) { mOfflinePageOfflineId = offlineId; } - /** - * Gets offline id of the corresponding to the snippet offline page. - * Null if there is no corresponding offline page. - */ + @Override @Nullable public Long getOfflinePageOfflineId() { return mOfflinePageOfflineId;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java index 87dee41..68f0ca8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java
@@ -8,12 +8,12 @@ import org.chromium.base.Callback; import org.chromium.base.annotations.CalledByNative; -import org.chromium.chrome.browser.ntp.NewTabPage.DestructionObserver; import org.chromium.chrome.browser.ntp.NewTabPageUma; import org.chromium.chrome.browser.ntp.cards.ActionItem; import org.chromium.chrome.browser.ntp.cards.SuggestionsCategoryInfo; import org.chromium.chrome.browser.ntp.snippets.CategoryStatus.CategoryStatusEnum; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.suggestions.DestructionObserver; import org.chromium.chrome.browser.suggestions.SuggestionsMetricsReporter; import org.chromium.chrome.browser.suggestions.SuggestionsRanker;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java index f2f42ff6..48065c7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java
@@ -426,6 +426,7 @@ * Returns via callback any urls in <code>urls</code> for which there exist offline pages. * * TODO(http://crbug.com/598006): Add metrics for preventing UI jank. + * TODO(http://crbug.com/693514): Now unused in production code. Can be removed. */ public void checkPagesExistOffline(Set<String> urls, Callback<Set<String>> callback) { String[] urlArray = urls.toArray(new String[urls.size()]);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java index 328686f..946645c5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -236,8 +236,9 @@ private final Handler mHandler = new Handler(); private final WebContents mWebContents; + private final String mSchemelessOriginForPaymentApp; + private final String mOriginForDisplay; private final String mMerchantName; - private final String mOrigin; private final byte[][] mCertificateChain; private final AddressEditor mAddressEditor; private final CardEditor mCardEditor; @@ -334,9 +335,13 @@ mWebContents = webContents; + mSchemelessOriginForPaymentApp = UrlFormatter.formatUrlForSecurityDisplay( + mWebContents.getLastCommittedUrl(), false /* omit scheme for payment apps. */); + + mOriginForDisplay = UrlFormatter.formatUrlForSecurityDisplay( + mWebContents.getLastCommittedUrl(), true /* include scheme in display */); + mMerchantName = webContents.getTitle(); - mOrigin = - UrlFormatter.formatUrlForSecurityDisplay(mWebContents.getLastCommittedUrl(), true); mCertificateChain = CertificateChainHelper.getCertificateChain(mWebContents); mApps = new ArrayList<>(); @@ -433,7 +438,7 @@ mUI = new PaymentRequestUI(activity, this, mRequestShipping, mRequestPayerName || mRequestPayerPhone || mRequestPayerEmail, mMerchantSupportsAutofillPaymentInstruments, - !PaymentPreferencesUtil.isPaymentCompleteOnce(), mMerchantName, mOrigin, + !PaymentPreferencesUtil.isPaymentCompleteOnce(), mMerchantName, mOriginForDisplay, new ShippingStrings(mShippingType)); final FaviconHelper faviconHelper = new FaviconHelper(); @@ -615,7 +620,8 @@ // so a fast response from a non-autofill payment app at the front of the app list does not // cause NOT_SUPPORTED payment rejection. for (Map.Entry<PaymentApp, Map<String, PaymentMethodData>> q : queryApps.entrySet()) { - q.getKey().getInstruments(q.getValue(), mOrigin, mCertificateChain, this); + q.getKey().getInstruments( + q.getValue(), mSchemelessOriginForPaymentApp, mCertificateChain, this); } } @@ -1133,9 +1139,9 @@ } } - instrument.invokePaymentApp(mMerchantName, mOrigin, mCertificateChain, - Collections.unmodifiableMap(methodData), mRawTotal, mRawLineItems, - Collections.unmodifiableMap(modifiers), this); + instrument.invokePaymentApp(mMerchantName, mSchemelessOriginForPaymentApp, + mCertificateChain, Collections.unmodifiableMap(methodData), mRawTotal, + mRawLineItems, Collections.unmodifiableMap(modifiers), this); recordSuccessFunnelHistograms("PayClicked"); return !(instrument instanceof AutofillPaymentInstrument); @@ -1221,14 +1227,14 @@ public void canMakePayment() { if (mClient == null) return; - CanMakePaymentQuery query = sCanMakePaymentQueries.get(mOrigin); + CanMakePaymentQuery query = sCanMakePaymentQueries.get(mSchemelessOriginForPaymentApp); if (query == null) { query = new CanMakePaymentQuery(mMethodData.keySet()); - sCanMakePaymentQueries.put(mOrigin, query); + sCanMakePaymentQueries.put(mSchemelessOriginForPaymentApp, query); mHandler.postDelayed(new Runnable() { @Override public void run() { - sCanMakePaymentQueries.remove(mOrigin); + sCanMakePaymentQueries.remove(mSchemelessOriginForPaymentApp); } }, CAN_MAKE_PAYMENT_QUERY_PERIOD_MS); } @@ -1369,7 +1375,7 @@ } } - CanMakePaymentQuery query = sCanMakePaymentQueries.get(mOrigin); + CanMakePaymentQuery query = sCanMakePaymentQueries.get(mSchemelessOriginForPaymentApp); if (query != null) query.setResponse(mCanMakePayment); // The list of payment instruments is ready to display.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/DestructionObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/DestructionObserver.java new file mode 100644 index 0000000..2b95775c --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/DestructionObserver.java
@@ -0,0 +1,12 @@ +// 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. + +package org.chromium.chrome.browser.suggestions; + +/** + * Object that is registered through the {@link SuggestionsUiDelegate}, and that will be notified + * when its owner is destroyed. + * @see SuggestionsUiDelegate#addDestructionObserver(DestructionObserver) + */ +public interface DestructionObserver { void onDestroy(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/OfflinableSuggestion.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/OfflinableSuggestion.java new file mode 100644 index 0000000..732608e --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/OfflinableSuggestion.java
@@ -0,0 +1,28 @@ +// 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. + +package org.chromium.chrome.browser.suggestions; + +import android.support.annotation.Nullable; + +/** + * Exposes the data of a suggestion that can be saved offline. + */ +public interface OfflinableSuggestion { + /** @return The URL of this suggestion. */ + String getUrl(); + + /** Assigns an offline page id to the suggestion. Set to {@code null} to clear. */ + void setOfflinePageOfflineId(@Nullable Long offlineId); + + /** @return current offline id assigned to the suggestion, or {@code null} if there is none. */ + @Nullable + Long getOfflinePageOfflineId(); + + /** + * @return whether a suggestion has to be matched with the exact offline page or with the most + * recent offline page found by the suggestion's URL. + */ + boolean requiresExactOfflinePage(); +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetContent.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetContent.java index e6dfb124..ad72913 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetContent.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetContent.java
@@ -12,7 +12,6 @@ import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.NativePageHost; import org.chromium.chrome.browser.ntp.ContextMenuManager; -import org.chromium.chrome.browser.ntp.NewTabPage.DestructionObserver; import org.chromium.chrome.browser.ntp.cards.NewTabPageAdapter; import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView; import org.chromium.chrome.browser.ntp.snippets.SnippetsBridge;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegateImpl.java index 6969148..2fff2de 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegateImpl.java
@@ -96,7 +96,7 @@ if (article.isAssetDownload()) { assert windowOpenDisposition == WindowOpenDisposition.CURRENT_TAB || windowOpenDisposition == WindowOpenDisposition.NEW_WINDOW - || windowOpenDisposition == WindowOpenDisposition.NEW_FOREGROUND_TAB; + || windowOpenDisposition == WindowOpenDisposition.NEW_BACKGROUND_TAB; DownloadUtils.openFile( article.getAssetDownloadFile(), article.getAssetDownloadMimeType(), false); return; @@ -123,7 +123,7 @@ assert article.getOfflinePageOfflineId() != null; assert windowOpenDisposition == WindowOpenDisposition.CURRENT_TAB || windowOpenDisposition == WindowOpenDisposition.NEW_WINDOW - || windowOpenDisposition == WindowOpenDisposition.NEW_FOREGROUND_TAB; + || windowOpenDisposition == WindowOpenDisposition.NEW_BACKGROUND_TAB; loadUrlParams = OfflinePageUtils.getLoadUrlParamsForOpeningOfflineVersion( article.mUrl, article.getOfflinePageOfflineId()); // Extra headers are not read in loadUrl, but verbatim headers are. @@ -149,7 +149,7 @@ case WindowOpenDisposition.CURRENT_TAB: mHost.loadUrl(loadUrlParams); break; - case WindowOpenDisposition.NEW_FOREGROUND_TAB: + case WindowOpenDisposition.NEW_BACKGROUND_TAB: openUrlInNewTab(loadUrlParams, false); break; case WindowOpenDisposition.OFF_THE_RECORD:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsOfflineModelObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsOfflineModelObserver.java new file mode 100644 index 0000000..9cfb5bf --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsOfflineModelObserver.java
@@ -0,0 +1,97 @@ +// 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. + +package org.chromium.chrome.browser.suggestions; + +import android.support.annotation.Nullable; + +import org.chromium.base.Callback; +import org.chromium.chrome.browser.offlinepages.ClientId; +import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; +import org.chromium.chrome.browser.offlinepages.OfflinePageItem; + +/** + * Handles checking the offline state of suggestions and notifications about related changes. + * @param <T> type of suggestion to handle. Mostly a convenience parameter to avoid casts. + */ +public abstract class SuggestionsOfflineModelObserver<T extends OfflinableSuggestion> + extends OfflinePageBridge.OfflinePageModelObserver implements DestructionObserver { + private final OfflinePageBridge mOfflinePageBridge; + + /** + * Constructor for an offline model observer. It registers itself with the bridge, but the + * unregistration will have to be done by the caller, either directly or by registering the + * created observer as {@link DestructionObserver}. + * @param bridge source of the offline state data. + */ + public SuggestionsOfflineModelObserver(OfflinePageBridge bridge) { + mOfflinePageBridge = bridge; + mOfflinePageBridge.addObserver(this); + } + + @Override + public void onDestroy() { + mOfflinePageBridge.removeObserver(this); + } + + @Override + public void offlinePageModelLoaded() { + updateOfflinableSuggestionsAvailability(); + } + + @Override + public void offlinePageAdded(OfflinePageItem addedPage) { + updateOfflinableSuggestionsAvailability(); + } + + @Override + public void offlinePageDeleted(long offlineId, ClientId clientId) { + for (T suggestion : getOfflinableSuggestions()) { + if (suggestion.requiresExactOfflinePage()) continue; + + Long suggestionOfflineId = suggestion.getOfflinePageOfflineId(); + if (suggestionOfflineId == null) continue; + if (suggestionOfflineId != offlineId) continue; + + // The old value cannot be simply removed without a request to the + // model, because there may be an older offline page for the same + // URL. + updateOfflinableSuggestionAvailability(suggestion); + } + } + + public void updateOfflinableSuggestionsAvailability() { + for (T suggestion : getOfflinableSuggestions()) { + if (suggestion.requiresExactOfflinePage()) continue; + updateOfflinableSuggestionAvailability(suggestion); + } + } + + public void updateOfflinableSuggestionAvailability(final T suggestion) { + // This method is not applicable to articles for which the exact offline id must specified. + assert !suggestion.requiresExactOfflinePage(); + if (!mOfflinePageBridge.isOfflinePageModelLoaded()) return; + + // TabId is relevant only for recent tab offline pages, which we do not handle here, so we + // do not care about tab id. + mOfflinePageBridge.selectPageForOnlineUrl( + suggestion.getUrl(), /*tabId=*/0, new Callback<OfflinePageItem>() { + @Override + public void onResult(OfflinePageItem item) { + onSuggestionOfflineIdChanged( + suggestion, item == null ? null : item.getOfflineId()); + } + }); + } + + /** + * Called when the offline state of a suggestion is retrieved. + * @param suggestion the suggestion for which the offline state was checked. + * @param id the new offline id of the suggestion. + */ + public abstract void onSuggestionOfflineIdChanged(T suggestion, @Nullable Long id); + + /** Handle to the suggestions for which to observe changes. */ + public abstract Iterable<T> getOfflinableSuggestions(); +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsUiDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsUiDelegate.java index 64a68505a..0d6fbccd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsUiDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsUiDelegate.java
@@ -4,15 +4,11 @@ package org.chromium.chrome.browser.suggestions; -import org.chromium.base.Callback; import org.chromium.chrome.browser.favicon.FaviconHelper.FaviconImageCallback; import org.chromium.chrome.browser.favicon.FaviconHelper.IconAvailabilityCallback; import org.chromium.chrome.browser.favicon.LargeIconBridge.LargeIconCallback; -import org.chromium.chrome.browser.ntp.NewTabPage.DestructionObserver; import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource; -import java.util.Set; - /** * Interface between the suggestion surface and the rest of the browser. */ @@ -65,13 +61,4 @@ * Registers a {@link DestructionObserver}, notified when the New Tab Page goes away. */ void addDestructionObserver(DestructionObserver destructionObserver); - - // Offline - - /** - * Checks if the pages with the given URLs are available offline. - * @param pageUrls The URLs of the sites whose offline availability is requested. - * @param callback Fired when the results are available. - */ - void getUrlsAvailableOffline(Set<String> pageUrls, Callback<Set<String>> callback); } \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsUiDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsUiDelegateImpl.java index e5b5c47..02741c7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsUiDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsUiDelegateImpl.java
@@ -4,31 +4,19 @@ package org.chromium.chrome.browser.suggestions; -import android.net.Uri; -import android.os.SystemClock; import android.support.annotation.Nullable; -import org.chromium.base.Callback; -import org.chromium.base.ThreadUtils; -import org.chromium.base.metrics.RecordHistogram; -import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.NativePageHost; -import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.favicon.FaviconHelper; import org.chromium.chrome.browser.favicon.FaviconHelper.FaviconImageCallback; import org.chromium.chrome.browser.favicon.FaviconHelper.IconAvailabilityCallback; import org.chromium.chrome.browser.favicon.LargeIconBridge; import org.chromium.chrome.browser.favicon.LargeIconBridge.LargeIconCallback; -import org.chromium.chrome.browser.ntp.NewTabPage.DestructionObserver; import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource; -import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; import org.chromium.chrome.browser.profiles.Profile; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; /** * {@link SuggestionsUiDelegate} implementation. @@ -85,55 +73,6 @@ } @Override - public void getUrlsAvailableOffline( - Set<String> pageUrls, final Callback<Set<String>> callback) { - final Set<String> urlsAvailableOffline = new HashSet<>(); - if (mIsDestroyed || !isNtpOfflinePagesEnabled()) { - callback.onResult(urlsAvailableOffline); - return; - } - - HashSet<String> urlsToCheckForOfflinePage = new HashSet<>(); - - for (String pageUrl : pageUrls) { - if (isLocalUrl(pageUrl)) { - urlsAvailableOffline.add(pageUrl); - } else { - urlsToCheckForOfflinePage.add(pageUrl); - } - } - - final long offlineQueryStartTime = SystemClock.elapsedRealtime(); - - OfflinePageBridge offlinePageBridge = OfflinePageBridge.getForProfile(mProfile); - - // TODO(dewittj): Remove this code by making the NTP badging available after the NTP is - // fully loaded. - if (offlinePageBridge == null || !offlinePageBridge.isOfflinePageModelLoaded()) { - // Posting a task to avoid potential re-entrancy issues. - ThreadUtils.postOnUiThread(new Runnable() { - @Override - public void run() { - callback.onResult(urlsAvailableOffline); - } - }); - return; - } - - offlinePageBridge.checkPagesExistOffline( - urlsToCheckForOfflinePage, new Callback<Set<String>>() { - @Override - public void onResult(Set<String> urlsWithOfflinePages) { - urlsAvailableOffline.addAll(urlsWithOfflinePages); - callback.onResult(urlsAvailableOffline); - RecordHistogram.recordTimesHistogram("NewTabPage.OfflineUrlsLoadTime", - SystemClock.elapsedRealtime() - offlineQueryStartTime, - TimeUnit.MILLISECONDS); - } - }); - } - - @Override public SuggestionsSource getSuggestionsSource() { return mSuggestionsSource; } @@ -191,12 +130,4 @@ if (mLargeIconBridge == null) mLargeIconBridge = new LargeIconBridge(mProfile); return mLargeIconBridge; } - - private boolean isNtpOfflinePagesEnabled() { - return ChromeFeatureList.isEnabled(ChromeFeatureList.NTP_OFFLINE_PAGES_FEATURE_NAME); - } - - private boolean isLocalUrl(String url) { - return UrlConstants.FILE_SCHEME.equals(Uri.parse(url).getScheme()); - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/Tile.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/Tile.java index 6b9e3bf..067927d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/Tile.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/Tile.java
@@ -14,11 +14,10 @@ /** * Holds the details to populate a site suggestion tile. */ -public class Tile { +public class Tile implements OfflinableSuggestion { private final String mTitle; private final String mUrl; private final String mWhitelistIconPath; - private final boolean mOfflineAvailable; private final int mIndex; @NTPTileSourceEnum @@ -30,21 +29,22 @@ @Nullable private Drawable mIcon; + @Nullable + private Long mOfflinePageOfflineId; + /** * @param title The tile title. * @param url The site URL. * @param whitelistIconPath The path to the icon image file, if this is a whitelisted tile. * Empty otherwise. - * @param offlineAvailable Whether there is an offline copy of the URL available. * @param index The index of this tile in the list of tiles. * @param source The {@code NTPTileSource} that generated this tile. */ - public Tile(String title, String url, String whitelistIconPath, boolean offlineAvailable, - int index, @NTPTileSourceEnum int source) { + public Tile(String title, String url, String whitelistIconPath, int index, + @NTPTileSourceEnum int source) { mTitle = title; mUrl = url; mWhitelistIconPath = whitelistIconPath; - mOfflineAvailable = offlineAvailable; mIndex = index; mSource = source; } @@ -62,9 +62,9 @@ mType = tile.getType(); mIcon = tile.getIcon(); + mOfflinePageOfflineId = tile.mOfflinePageOfflineId; if (!tile.getTitle().equals(mTitle)) return true; - if (tile.isOfflineAvailable() != mOfflineAvailable) return true; if (tile.getIndex() != mIndex) return true; // Ignore the whitelist changes when we already have an icon, since we won't need to reload @@ -74,13 +74,27 @@ return false; } - /** - * @return The site URL of this tile. - */ + @Override public String getUrl() { return mUrl; } + @Override + public void setOfflinePageOfflineId(@Nullable Long offlineId) { + mOfflinePageOfflineId = offlineId; + } + + @Nullable + @Override + public Long getOfflinePageOfflineId() { + return mOfflinePageOfflineId; + } + + @Override + public boolean requiresExactOfflinePage() { + return false; + } + /** * @return The title of this tile. */ @@ -99,7 +113,7 @@ * @return Whether this tile is available offline. */ public boolean isOfflineAvailable() { - return mOfflineAvailable; + return getOfflinePageOfflineId() != null; } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGrid.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGrid.java index f282287..11f5d1e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGrid.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGrid.java
@@ -14,6 +14,7 @@ import org.chromium.chrome.browser.ntp.cards.ItemViewType; import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder; import org.chromium.chrome.browser.ntp.cards.OptionalLeaf; +import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; /** * The model and controller for a group of site suggestion tiles that will be rendered in a grid. @@ -38,10 +39,10 @@ private final TileGroup mTileGroup; public TileGrid(SuggestionsUiDelegate uiDelegate, ContextMenuManager contextMenuManager, - TileGroup.Delegate tileGroupDelegate) { + TileGroup.Delegate tileGroupDelegate, OfflinePageBridge offlinePageBridge) { mTileGroup = new TileGroup(ContextUtils.getApplicationContext(), uiDelegate, contextMenuManager, tileGroupDelegate, - /* observer = */ this, getTileTitleLines()); + /* observer = */ this, offlinePageBridge, getTileTitleLines()); mTileGroup.startObserving(getMaxTileRows() * MAX_TILE_COLUMNS); } @@ -74,6 +75,11 @@ } @Override + public void onTileOfflineBadgeVisibilityChanged(Tile tile) { + if (isVisible()) notifyItemChanged(0, new ViewHolder.UpdateOfflineBadgeCallback(tile)); + } + + @Override public void onLoadTaskAdded() {} @Override @@ -112,6 +118,10 @@ mLayout.updateIconView(tile); } + public void updateOfflineBadge(Tile tile) { + mLayout.updateOfflineBadge(tile); + } + /** * Callback to update the icon view for the view holder. */ @@ -128,5 +138,22 @@ ((ViewHolder) holder).updateIconView(mTile); } } + + /** + * Callback to update the offline badge for the view holder. + */ + public static class UpdateOfflineBadgeCallback extends PartialBindCallback { + private final Tile mTile; + + public UpdateOfflineBadgeCallback(Tile tile) { + mTile = tile; + } + + @Override + public void onResult(NewTabPageViewHolder holder) { + assert holder instanceof ViewHolder; + ((ViewHolder) holder).updateOfflineBadge(mTile); + } + } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGridLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGridLayout.java index 6a37c4ce..31d13d5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGridLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGridLayout.java
@@ -71,14 +71,17 @@ * @param tile The tile that holds the data to populate the tile view. */ public void updateIconView(Tile tile) { - int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { - TileView tileView = (TileView) getChildAt(i); - if (TextUtils.equals(tile.getUrl(), tileView.getUrl())) { - tileView.renderIcon(tile); - break; - } - } + TileView tileView = getTileView(tile.getUrl()); + if (tileView != null) tileView.renderIcon(tile); + } + + /** + * Updates the visibility of the offline badge on the child view with a matching URL. + * @param tile The tile that holds the data to populate the tile view. + */ + public void updateOfflineBadge(Tile tile) { + TileView tileView = getTileView(tile.getUrl()); + if (tileView != null) tileView.renderOfflineBadge(tile); } @Override @@ -148,4 +151,14 @@ setMeasuredDimension(totalWidth, resolveSize(totalHeight, heightMeasureSpec)); } + + /** @return A tile view associated to the provided URL, or {@code null} if none is found. */ + private TileView getTileView(String url) { + int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + TileView tileView = (TileView) getChildAt(i); + if (TextUtils.equals(url, tileView.getUrl())) return tileView; + } + return null; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroup.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroup.java index 15a6e8f..ceaa781 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroup.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroup.java
@@ -22,13 +22,14 @@ import android.view.ViewGroup; import org.chromium.base.ApiCompatibilityUtils; -import org.chromium.base.Callback; import org.chromium.base.Log; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.favicon.LargeIconBridge.LargeIconCallback; import org.chromium.chrome.browser.ntp.ContextMenuManager; import org.chromium.chrome.browser.ntp.ContextMenuManager.ContextMenuItemId; import org.chromium.chrome.browser.ntp.MostVisitedTileType; +import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; import org.chromium.chrome.browser.widget.RoundedIconGenerator; import org.chromium.ui.mojom.WindowOpenDisposition; @@ -93,6 +94,12 @@ void onTileIconChanged(Tile tile); /** + * Called when the visibility of a tile's offline badge has changed. + * @param tile The tile for which the visibility of the offline badge has changed. + */ + void onTileOfflineBadgeVisibilityChanged(Tile tile); + + /** * Called when an asynchronous loading task has started. */ void onLoadTaskAdded(); @@ -120,6 +127,13 @@ private final RoundedIconGenerator mIconGenerator; /** + * Access point to offline related features. Will be {@code null} when the badges are disabled. + * @see ChromeFeatureList#NTP_OFFLINE_PAGES_FEATURE_NAME + */ + @Nullable + private final OfflineModelObserver mOfflineModelObserver; + + /** * Source of truth for the tile data. Since the objects can change when the data is updated, * other objects should not hold references to them but keep track of the URL instead, and use * it to retrieve a {@link Tile}. @@ -138,7 +152,7 @@ */ public TileGroup(Context context, SuggestionsUiDelegate uiDelegate, ContextMenuManager contextMenuManager, Delegate tileGroupDelegate, Observer observer, - int titleLines) { + OfflinePageBridge offlinePageBridge, int titleLines) { mContext = context; mUiDelegate = uiDelegate; mContextMenuManager = contextMenuManager; @@ -156,29 +170,51 @@ ApiCompatibilityUtils.getColor(resources, R.color.default_favicon_background_color); mIconGenerator = new RoundedIconGenerator(mContext, desiredIconSizeDp, desiredIconSizeDp, ICON_CORNER_RADIUS_DP, iconColor, ICON_TEXT_SIZE_DP); + + if (ChromeFeatureList.isEnabled(ChromeFeatureList.NTP_OFFLINE_PAGES_FEATURE_NAME)) { + mOfflineModelObserver = new OfflineModelObserver(offlinePageBridge); + mUiDelegate.addDestructionObserver(mOfflineModelObserver); + } else { + mOfflineModelObserver = null; + } } @Override public void onMostVisitedURLsAvailable(final String[] titles, final String[] urls, final String[] whitelistIconPaths, final int[] sources) { - // If no tiles have been built yet, this is the initial load. Build the tiles immediately so - // the layout is stable during initial rendering. They can be - // replaced later if there are offline urls, but that will not affect the layout widths and - // heights. A stable layout enables reliable scroll position initialization. - if (!mHasReceivedData) { - buildTiles(titles, urls, whitelistIconPaths, null, sources); + boolean isInitialLoad = !mHasReceivedData; + mHasReceivedData = true; + + Tile[] newTiles = new Tile[titles.length]; + Set<String> addedUrls = new HashSet<>(); + boolean countChanged = isInitialLoad || mTiles.length != titles.length; + boolean dataChanged = countChanged; + for (int i = 0; i < titles.length; i++) { + assert urls[i] != null; // We assume everywhere that the url is not null. + + // TODO(dgn): Add UMA to track the cause of https://crbug.com/690926. Checking this + // should not even be necessary as the backend is supposed to send non dupes URLs. + if (addedUrls.contains(urls[i])) { + assert false : "Incoming NTP Tiles are not unique. Dupe on " + urls[i]; + continue; + } + + newTiles[i] = new Tile(titles[i], urls[i], whitelistIconPaths[i], i, sources[i]); + if (newTiles[i].importData(getTile(urls[i]))) dataChanged = true; + addedUrls.add(urls[i]); } - // TODO(https://crbug.com/607573): We should show offline-available content in a nonblocking - // way so that responsiveness of the NTP does not depend on ready availability of offline - // pages. - Set<String> urlSet = new HashSet<>(Arrays.asList(urls)); - mUiDelegate.getUrlsAvailableOffline(urlSet, new Callback<Set<String>>() { - @Override - public void onResult(Set<String> offlineUrls) { - buildTiles(titles, urls, whitelistIconPaths, offlineUrls, sources); - } - }); + if (!dataChanged) return; + + mTiles = newTiles; + + if (mOfflineModelObserver != null) { + mOfflineModelObserver.updateOfflinableSuggestionsAvailability(); + } + + if (countChanged) mObserver.onTileCountChanged(); + if (isInitialLoad) mObserver.onLoadTaskCompleted(); + mObserver.onTileDataChanged(); } @Override @@ -240,40 +276,6 @@ return mHasReceivedData; } - private void buildTiles(String[] titles, String[] urls, String[] whitelistIconPaths, - @Nullable Set<String> offlineUrls, int[] sources) { - boolean isInitialLoad = !mHasReceivedData; - mHasReceivedData = true; - - Tile[] newTiles = new Tile[titles.length]; - Set<String> addedUrls = new HashSet<>(); - boolean countChanged = isInitialLoad || mTiles.length != titles.length; - boolean dataChanged = countChanged; - for (int i = 0; i < titles.length; i++) { - assert urls[i] != null; // We assume everywhere that the url is not null. - - // TODO(dgn): Add UMA to track the cause of https://crbug.com/690926. Checking this - // should not even be necessary as the backend is supposed to send non dupes URLs. - if (addedUrls.contains(urls[i])) { - assert false : "Incoming NTP Tiles are not unique. Dupe on " + urls[i]; - continue; - } - - boolean offlineAvailable = offlineUrls != null && offlineUrls.contains(urls[i]); - newTiles[i] = new Tile( - titles[i], urls[i], whitelistIconPaths[i], offlineAvailable, i, sources[i]); - if (newTiles[i].importData(getTile(urls[i]))) dataChanged = true; - addedUrls.add(urls[i]); - } - - if (!dataChanged) return; - - mTiles = newTiles; - if (countChanged) mObserver.onTileCountChanged(); - if (isInitialLoad) mObserver.onLoadTaskCompleted(); - mObserver.onTileDataChanged(); - } - /** * Inflates a new tile view, initializes it, and loads an icon for it. * @param tile The tile that holds the data to populate the new tile view. @@ -417,4 +419,29 @@ mContextMenuManager.createContextMenu(contextMenu, view, this); } } + + private class OfflineModelObserver extends SuggestionsOfflineModelObserver<Tile> { + public OfflineModelObserver(OfflinePageBridge bridge) { + super(bridge); + } + + @Override + public void onSuggestionOfflineIdChanged(Tile suggestion, @Nullable Long id) { + // Retrieve a tile from the internal data, to make sure we don't update a stale object. + Tile tile = getTile(suggestion.getUrl()); + if (tile == null) return; + + boolean oldOfflineAvailable = tile.isOfflineAvailable(); + tile.setOfflinePageOfflineId(id); + + // Only notify to update the view if there will be a visible change. + if (oldOfflineAvailable == tile.isOfflineAvailable()) return; + mObserver.onTileOfflineBadgeVisibilityChanged(tile); + } + + @Override + public Iterable<Tile> getOfflinableSuggestions() { + return Arrays.asList(mTiles); + } + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileView.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileView.java index 0b498239..0c36d8e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileView.java
@@ -65,6 +65,11 @@ mIconView.setImageDrawable(tile.getIcon()); } + /** Shows or hides the offline badge to reflect the offline availability of the {@link Tile}. */ + public void renderOfflineBadge(Tile tile) { + mBadgeView.setVisibility(tile.isOfflineAvailable() ? VISIBLE : GONE); + } + /** Updates the view if there have been changes since the last time. */ public void updateIfDataChanged(Tile tile) { if (!isUpToDate(tile)) renderTile(tile); @@ -84,7 +89,7 @@ // callbacks and handlers use it to look up the data and notify the rest of the system. assert mUrl.equals(tile.getUrl()); mTitleView.setText(TitleUtil.getTitleForDisplay(tile.getTitle(), tile.getUrl())); - mBadgeView.setVisibility(tile.isOfflineAvailable() ? VISIBLE : GONE); + renderOfflineBadge(tile); renderIcon(tile); } }
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 73e6102..482ef77 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -926,11 +926,14 @@ "java/src/org/chromium/chrome/browser/snackbar/undo/UndoBarController.java", "java/src/org/chromium/chrome/browser/ssl/SecurityStateModel.java", "java/src/org/chromium/chrome/browser/suggestions/ContentSuggestionsActivity.java", + "java/src/org/chromium/chrome/browser/suggestions/DestructionObserver.java", "java/src/org/chromium/chrome/browser/suggestions/MostVisitedSites.java", "java/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetContent.java", "java/src/org/chromium/chrome/browser/suggestions/Tile.java", "java/src/org/chromium/chrome/browser/suggestions/TileGrid.java", "java/src/org/chromium/chrome/browser/suggestions/TileGridLayout.java", + "java/src/org/chromium/chrome/browser/suggestions/OfflinableSuggestion.java", + "java/src/org/chromium/chrome/browser/suggestions/SuggestionsOfflineModelObserver.java", "java/src/org/chromium/chrome/browser/suggestions/TileGroup.java", "java/src/org/chromium/chrome/browser/suggestions/TileGroupDelegateImpl.java", "java/src/org/chromium/chrome/browser/suggestions/TileView.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java index cc7666e..6ec28c3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java
@@ -11,7 +11,6 @@ import android.view.ViewGroup; import android.widget.FrameLayout; -import org.chromium.base.Callback; import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RetryOnFailure; @@ -20,12 +19,12 @@ import org.chromium.chrome.browser.favicon.FaviconHelper.FaviconImageCallback; import org.chromium.chrome.browser.favicon.FaviconHelper.IconAvailabilityCallback; import org.chromium.chrome.browser.favicon.LargeIconBridge.LargeIconCallback; -import org.chromium.chrome.browser.ntp.NewTabPage.DestructionObserver; import org.chromium.chrome.browser.ntp.cards.NewTabPageAdapter; import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView; import org.chromium.chrome.browser.ntp.cards.SuggestionsCategoryInfo; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.suggestions.DestructionObserver; import org.chromium.chrome.browser.suggestions.SuggestionsMetricsReporter; import org.chromium.chrome.browser.suggestions.SuggestionsNavigationDelegate; import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate; @@ -39,7 +38,6 @@ import java.io.IOException; import java.util.Arrays; -import java.util.Set; /** * Tests for the appearance of Article Snippets. @@ -231,11 +229,6 @@ } @Override - public void getUrlsAvailableOffline(Set<String> pageUrls, Callback<Set<String>> callback) { - throw new UnsupportedOperationException(); - } - - @Override public SuggestionsSource getSuggestionsSource() { return mSnippetsSource; }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/OWNERS new file mode 100644 index 0000000..78c3488 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/OWNERS
@@ -0,0 +1 @@ +file://chrome/android/java/src/org/chromium/chrome/browser/ntp/OWNERS
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetTest.java index 29e05233..19025322 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetTest.java
@@ -11,6 +11,7 @@ import android.support.v7.widget.RecyclerView.ViewHolder; import android.view.MotionEvent; +import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.browser.ntp.cards.ItemViewType; import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView; import org.chromium.chrome.test.BottomSheetTestCaseBase; @@ -42,6 +43,7 @@ super.tearDown(); } + @RetryOnFailure @MediumTest public void testContextMenu() throws InterruptedException { NewTabPageRecyclerView recyclerView =
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java index f63ea83..3ce31b2 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
@@ -54,7 +54,6 @@ import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.DisableHistogramsRule; import org.chromium.chrome.browser.ntp.ContextMenuManager; -import org.chromium.chrome.browser.ntp.NewTabPage.DestructionObserver; import org.chromium.chrome.browser.ntp.cards.SignInPromo.SigninObserver; import org.chromium.chrome.browser.ntp.snippets.CategoryInt; import org.chromium.chrome.browser.ntp.snippets.CategoryStatus; @@ -64,6 +63,7 @@ import org.chromium.chrome.browser.signin.SigninManager; import org.chromium.chrome.browser.signin.SigninManager.SignInAllowedObserver; import org.chromium.chrome.browser.signin.SigninManager.SignInStateObserver; +import org.chromium.chrome.browser.suggestions.DestructionObserver; import org.chromium.chrome.browser.suggestions.SuggestionsMetricsReporter; import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate; import org.chromium.chrome.test.util.browser.suggestions.ContentSuggestionsTestUtils.CategoryInfoBuilder;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SectionListTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SectionListTest.java index f9e2a34b..5227ae5 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SectionListTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SectionListTest.java
@@ -9,6 +9,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -29,11 +30,11 @@ import org.chromium.base.Callback; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.DisableHistogramsRule; -import org.chromium.chrome.browser.ntp.NewTabPage.DestructionObserver; import org.chromium.chrome.browser.ntp.snippets.CategoryInt; import org.chromium.chrome.browser.ntp.snippets.KnownCategories; import org.chromium.chrome.browser.ntp.snippets.SnippetArticle; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; +import org.chromium.chrome.browser.suggestions.DestructionObserver; import org.chromium.chrome.browser.suggestions.SuggestionsMetricsReporter; import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate; import org.chromium.chrome.test.util.browser.suggestions.ContentSuggestionsTestUtils.CategoryInfoBuilder; @@ -243,19 +244,20 @@ registerCategory(mSuggestionSource, CATEGORY1, 1); registerCategory(mSuggestionSource, new CategoryInfoBuilder(CATEGORY2).withViewAllAction().build(), 3); + SectionList sectionList = new SectionList(mUiDelegate, mOfflinePageBridge); bindViewHolders(sectionList); ArgumentCaptor<DestructionObserver> argument = ArgumentCaptor.forClass(DestructionObserver.class); - verify(mUiDelegate).addDestructionObserver(argument.capture()); + verify(mUiDelegate, atLeastOnce()).addDestructionObserver(argument.capture()); assertFalse(sectionList.isEmpty()); SuggestionsSection section = sectionList.getSectionForTesting(CATEGORY1); assertNotNull(section); // Now destroy the UI and thus notify the SectionList. - argument.getValue().onDestroy(); + for (DestructionObserver observer : argument.getAllValues()) observer.onDestroy(); // The section should be removed. assertTrue(sectionList.isEmpty()); // Verify that the section has been detached by notifying its parent about changes. If not
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/TileGroupTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/TileGroupTest.java index 34e27df6..fc193a7 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/TileGroupTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/TileGroupTest.java
@@ -6,7 +6,6 @@ import static junit.framework.TestCase.assertNotNull; -import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -16,30 +15,27 @@ import android.support.annotation.DimenRes; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentMatchers; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.annotation.Implements; import org.robolectric.annotation.RealObject; import org.robolectric.shadows.ShadowResources; -import org.chromium.base.Callback; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.browser.EnableFeatures; import org.chromium.chrome.browser.ntp.ContextMenuManager; import org.chromium.chrome.browser.ntp.cards.NodeParent; import org.chromium.chrome.browser.ntp.cards.SuggestionsSection; +import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; import org.chromium.testing.local.LocalRobolectricTestRunner; -import java.util.Collections; -import java.util.Set; - /** * Unit tests for {@link TileGroup}. */ @@ -50,6 +46,9 @@ private static final int TILE_TITLE_LINES = 1; private static final String[] URLS = {"https://www.google.com", "https://tellmedadjokes.com"}; + @Rule + public EnableFeatures.Processor mEnableFeatureProcessor = new EnableFeatures.Processor(); + @Mock private SuggestionsSection.Delegate mDelegate; @Mock @@ -58,6 +57,8 @@ private SuggestionsUiDelegate mUiDelegate; @Mock private TileGroup.Observer mTileGroupObserver; + @Mock + private OfflinePageBridge mOfflinePageBridge; private FakeTileGroupDelegate mTileGroupDelegate; @@ -69,10 +70,11 @@ } @Test + @EnableFeatures({ChromeFeatureList.NTP_OFFLINE_PAGES_FEATURE_NAME}) public void testInitialiseWithEmptyTileList() { TileGroup tileGroup = new TileGroup(RuntimeEnvironment.application, mUiDelegate, mock(ContextMenuManager.class), mTileGroupDelegate, mTileGroupObserver, - TILE_TITLE_LINES); + mOfflinePageBridge, TILE_TITLE_LINES); tileGroup.startObserving(MAX_TILES_TO_FETCH); notifyTileUrlsAvailable(); @@ -82,55 +84,19 @@ } @Test - public void testInitialiseWithOfflineUrl() { + @EnableFeatures({ChromeFeatureList.NTP_OFFLINE_PAGES_FEATURE_NAME}) + public void testInitialiseWithTileList() { TileGroup tileGroup = new TileGroup(RuntimeEnvironment.application, mUiDelegate, mock(ContextMenuManager.class), mTileGroupDelegate, mTileGroupObserver, - TILE_TITLE_LINES); + mOfflinePageBridge, TILE_TITLE_LINES); tileGroup.startObserving(MAX_TILES_TO_FETCH); - OfflineUrlsCallbackHandler callbackHandler = new OfflineUrlsCallbackHandler(); - doAnswer(callbackHandler) - .when(mUiDelegate) - .getUrlsAvailableOffline(ArgumentMatchers.<Set<String>>any(), - ArgumentMatchers.<Callback<Set<String>>>any()); - notifyTileUrlsAvailable(URLS); InOrder inOrder = inOrder(mTileGroupObserver); inOrder.verify(mTileGroupObserver).onTileCountChanged(); inOrder.verify(mTileGroupObserver).onLoadTaskCompleted(); inOrder.verify(mTileGroupObserver).onTileDataChanged(); - - callbackHandler.engage(Collections.singleton(URLS[1])); - - // Notification about the url that should be marked as offline. - inOrder.verify(mTileGroupObserver).onTileDataChanged(); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testInitialiseNoOfflineUrl() { - TileGroup tileGroup = new TileGroup(RuntimeEnvironment.application, mUiDelegate, - mock(ContextMenuManager.class), mTileGroupDelegate, mTileGroupObserver, - TILE_TITLE_LINES); - tileGroup.startObserving(MAX_TILES_TO_FETCH); - - OfflineUrlsCallbackHandler callbackHandler = new OfflineUrlsCallbackHandler(); - doAnswer(callbackHandler) - .when(mUiDelegate) - .getUrlsAvailableOffline(ArgumentMatchers.<Set<String>>any(), - ArgumentMatchers.<Callback<Set<String>>>any()); - - notifyTileUrlsAvailable(URLS); - - InOrder inOrder = inOrder(mTileGroupObserver); - inOrder.verify(mTileGroupObserver).onTileCountChanged(); - inOrder.verify(mTileGroupObserver).onLoadTaskCompleted(); - inOrder.verify(mTileGroupObserver).onTileDataChanged(); - - callbackHandler.engage(Collections.<String>emptySet()); - - // Triggering the offline callback does not cause updates because the data has not changed. inOrder.verifyNoMoreInteractions(); } @@ -145,29 +111,6 @@ titles, urls, whitelistIconPaths, sources); } - private static class OfflineUrlsCallbackHandler implements Answer<Void> { - private Callback<Set<String>> mCallback; - private Set<String> mCallbackArgument; - - @Override - public Void answer(InvocationOnMock invocation) throws Throwable { - mCallback = invocation.getArgument(1); - if (mCallbackArgument != null) invokeCallback(); - return null; - } - - public void engage(Set<String> callbackArgument) { - mCallbackArgument = callbackArgument; - if (mCallbackArgument != null && mCallback != null) invokeCallback(); - } - - private void invokeCallback() { - mCallback.onResult(mCallbackArgument); - mCallback = null; - mCallbackArgument = null; - } - } - private class FakeTileGroupDelegate implements TileGroup.Delegate { public MostVisitedSites.Observer mObserver;
diff --git a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc index 1f9269c..05bc04c 100644 --- a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc +++ b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc
@@ -16,6 +16,7 @@ #include "content/public/browser/web_contents.h" #include "jni/ContextualSearchSceneLayer_jni.h" #include "net/base/load_flags.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_request_context_getter.h" #include "ui/android/resources/resource_manager_impl.h" #include "ui/android/view_android.h" @@ -232,7 +233,8 @@ GURL gurl(thumbnail_url_); Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile); - fetcher_ = base::MakeUnique<chrome::BitmapFetcher>(gurl, this); + fetcher_ = base::MakeUnique<chrome::BitmapFetcher>(gurl, this, + NO_TRAFFIC_ANNOTATION_YET); fetcher_->Init( profile->GetRequestContext(), std::string(),
diff --git a/chrome/browser/android/ntp/content_suggestions_notifier_service.cc b/chrome/browser/android/ntp/content_suggestions_notifier_service.cc index 8d53c9b..9538cfc 100644 --- a/chrome/browser/android/ntp/content_suggestions_notifier_service.cc +++ b/chrome/browser/android/ntp/content_suggestions_notifier_service.cc
@@ -35,6 +35,7 @@ using params::ntp_snippets::kNotificationsFeature; using params::ntp_snippets::kNotificationsKeepWhenFrontmostParam; using params::ntp_snippets::kNotificationsUseSnippetAsTextParam; +using params::ntp_snippets::kNotificationsOpenToNTPParam; namespace { @@ -131,11 +132,14 @@ : base::Time::Max(); bool use_snippet = variations::GetVariationParamByFeatureAsBool( kNotificationsFeature, kNotificationsUseSnippetAsTextParam, false); + bool open_to_ntp = variations::GetVariationParamByFeatureAsBool( + kNotificationsFeature, kNotificationsOpenToNTPParam, false); service_->FetchSuggestionImage( suggestion->id(), base::Bind(&NotifyingObserver::ImageFetched, weak_ptr_factory_.GetWeakPtr(), suggestion->id(), - suggestion->url(), suggestion->title(), + open_to_ntp ? GURL("chrome://newtab") : suggestion->url(), + suggestion->title(), use_snippet ? suggestion->snippet_text() : suggestion->publisher_name(), timeout_at));
diff --git a/chrome/browser/android/offline_pages/background_loader_offliner.cc b/chrome/browser/android/offline_pages/background_loader_offliner.cc index 732a4eca..2bf511a6 100644 --- a/chrome/browser/android/offline_pages/background_loader_offliner.cc +++ b/chrome/browser/android/offline_pages/background_loader_offliner.cc
@@ -153,6 +153,12 @@ params.client_id = request.client_id(); params.proposed_offline_id = request.request_id(); params.is_background = true; + + // Pass in the original URL if it's different from last committed + // when redirects occur. + if (params.url != request.url()) + params.original_url = request.url(); + offline_page_model_->SavePage( params, std::move(archiver), base::Bind(&BackgroundLoaderOffliner::OnPageSaved,
diff --git a/chrome/browser/android/omnibox/answers_image_bridge.cc b/chrome/browser/android/omnibox/answers_image_bridge.cc index e21164e..fa08f54 100644 --- a/chrome/browser/android/omnibox/answers_image_bridge.cc +++ b/chrome/browser/android/omnibox/answers_image_bridge.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_android.h" #include "jni/AnswersImage_jni.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/android/java_bitmap.h" #include "url/gurl.h" @@ -75,7 +76,8 @@ std::string url; base::android::ConvertJavaStringToUTF8(env, java_url, &url); return bitmap_fetcher_service->RequestImage( - GURL(url), new AnswersImageObserverAndroid(env, java_callback)); + GURL(url), new AnswersImageObserverAndroid(env, java_callback), + NO_TRAFFIC_ANNOTATION_YET); } // static
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc index bc890bf..8dcfd51 100644 --- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc +++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
@@ -34,6 +34,7 @@ #include "components/sync/driver/sync_service_utils.h" #include "content/public/browser/notification_service.h" #include "extensions/features/features.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #if BUILDFLAG(ENABLE_EXTENSIONS) #include "chrome/browser/autocomplete/keyword_extensions_delegate_impl.h" @@ -249,7 +250,47 @@ BitmapFetcherService* image_service = BitmapFetcherServiceFactory::GetForBrowserContext(profile_); DCHECK(image_service); - image_service->Prefetch(url); + + // TODO(jdonnelly, rhalavati): Create a helper function with Callback to + // create annotation and pass it to image_service, merging this annotation and + // chrome/browser/ui/omnibox/chrome_omnibox_client.cc + net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("omnibox_prefetch_image", R"( + semantics { + sender: "Omnibox" + description: + "Chromium provides answers in the suggestion list for certain " + "queries that the user types in the omnibox. This request " + "retrieves a small image (for example, an icon illustrating the " + "current weather conditions) when this can add information to an " + "answer." + trigger: + "Change of results for the query typed by the user in the " + "omnibox." + data: + "The only data sent is the path to an image. No user data is " + "included, although some might be inferrable (e.g. whether the " + "weather is sunny or rainy in the user's current location) from " + "the name of the image in the path." + destination: WEBSITE + } + policy { + cookies_allowed: true + cookies_store: "user" + setting: + "You can enable or disable this feature via 'Use a prediction " + "service to help complete searches and URLs typed in the " + "address bar.' in Chromium's settings under Advanced. The " + "feature is enabled by default." + policy { + SearchSuggestEnabled { + policy_options {mode: MANDATORY} + value: false + } + } + })"); + + image_service->Prefetch(url, traffic_annotation); } void ChromeAutocompleteProviderClient::OnAutocompleteControllerResultReady(
diff --git a/chrome/browser/bitmap_fetcher/bitmap_fetcher.cc b/chrome/browser/bitmap_fetcher/bitmap_fetcher.cc index 35c5ab9..af9447a2 100644 --- a/chrome/browser/bitmap_fetcher/bitmap_fetcher.cc +++ b/chrome/browser/bitmap_fetcher/bitmap_fetcher.cc
@@ -11,10 +11,11 @@ namespace chrome { -BitmapFetcher::BitmapFetcher(const GURL& url, BitmapFetcherDelegate* delegate) - : url_(url), - delegate_(delegate) { -} +BitmapFetcher::BitmapFetcher( + const GURL& url, + BitmapFetcherDelegate* delegate, + const net::NetworkTrafficAnnotationTag& traffic_annotation) + : url_(url), delegate_(delegate), traffic_annotation_(traffic_annotation) {} BitmapFetcher::~BitmapFetcher() { } @@ -26,7 +27,8 @@ if (url_fetcher_ != NULL) return; - url_fetcher_ = net::URLFetcher::Create(url_, net::URLFetcher::GET, this); + url_fetcher_ = net::URLFetcher::Create(url_, net::URLFetcher::GET, this, + traffic_annotation_); url_fetcher_->SetRequestContext(request_context); url_fetcher_->SetReferrer(referrer); url_fetcher_->SetReferrerPolicy(referrer_policy);
diff --git a/chrome/browser/bitmap_fetcher/bitmap_fetcher.h b/chrome/browser/bitmap_fetcher/bitmap_fetcher.h index f6058cf0..a34ef5ab 100644 --- a/chrome/browser/bitmap_fetcher/bitmap_fetcher.h +++ b/chrome/browser/bitmap_fetcher/bitmap_fetcher.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_delegate.h" #include "chrome/browser/image_decoder.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_fetcher_delegate.h" #include "net/url_request/url_request.h" #include "url/gurl.h" @@ -28,7 +29,9 @@ class BitmapFetcher : public net::URLFetcherDelegate, public ImageDecoder::ImageRequest { public: - BitmapFetcher(const GURL& url, BitmapFetcherDelegate* delegate); + BitmapFetcher(const GURL& url, + BitmapFetcherDelegate* delegate, + const net::NetworkTrafficAnnotationTag& traffic_annotation); ~BitmapFetcher() override; const GURL& url() const { return url_; } @@ -74,6 +77,7 @@ std::unique_ptr<net::URLFetcher> url_fetcher_; const GURL url_; BitmapFetcherDelegate* const delegate_; + const net::NetworkTrafficAnnotationTag traffic_annotation_; DISALLOW_COPY_AND_ASSIGN(BitmapFetcher); };
diff --git a/chrome/browser/bitmap_fetcher/bitmap_fetcher_browsertest.cc b/chrome/browser/bitmap_fetcher/bitmap_fetcher_browsertest.cc index d4f1211..458a755f 100644 --- a/chrome/browser/bitmap_fetcher/bitmap_fetcher_browsertest.cc +++ b/chrome/browser/bitmap_fetcher/bitmap_fetcher_browsertest.cc
@@ -12,6 +12,7 @@ #include "content/public/test/test_utils.h" #include "net/base/load_flags.h" #include "net/http/http_status_code.h" +#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "net/url_request/test_url_fetcher_factory.h" #include "net/url_request/url_fetcher.h" #include "net/url_request/url_request_status.h" @@ -107,7 +108,7 @@ // Set up a delegate to wait for the callback. BitmapFetcherTestDelegate delegate(kAsyncCall); - BitmapFetcher fetcher(url, &delegate); + BitmapFetcher fetcher(url, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); url_fetcher_factory_->SetFakeResponse( url, image_string, net::HTTP_OK, net::URLRequestStatus::SUCCESS); @@ -141,7 +142,7 @@ BitmapFetcherTestDelegate delegate(kSyncCall); - BitmapFetcher fetcher(url, &delegate); + BitmapFetcher fetcher(url, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); fetcher.OnImageDecoded(image); @@ -160,7 +161,7 @@ // Set up a delegate to wait for the callback. BitmapFetcherTestDelegate delegate(kAsyncCall); - BitmapFetcher fetcher(url, &delegate); + BitmapFetcher fetcher(url, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); url_fetcher_factory_->SetFakeResponse(url, std::string(), @@ -183,7 +184,7 @@ IN_PROC_BROWSER_TEST_F(BitmapFetcherBrowserTest, HandleImageFailedTest) { GURL url("http://example.com/this-should-be-a-decode-failure"); BitmapFetcherTestDelegate delegate(kAsyncCall); - BitmapFetcher fetcher(url, &delegate); + BitmapFetcher fetcher(url, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); url_fetcher_factory_->SetFakeResponse(url, std::string("Not a real bitmap"), net::HTTP_OK,
diff --git a/chrome/browser/bitmap_fetcher/bitmap_fetcher_service.cc b/chrome/browser/bitmap_fetcher/bitmap_fetcher_service.cc index f1a2f9a..fcca01f 100644 --- a/chrome/browser/bitmap_fetcher/bitmap_fetcher_service.cc +++ b/chrome/browser/bitmap_fetcher/bitmap_fetcher_service.cc
@@ -83,7 +83,8 @@ BitmapFetcherService::RequestId BitmapFetcherService::RequestImage( const GURL& url, - Observer* observer) { + Observer* observer, + const net::NetworkTrafficAnnotationTag& traffic_annotation) { // Create a new request, assigning next available request ID. ++current_request_id_; if (current_request_id_ == REQUEST_ID_INVALID) @@ -111,22 +112,26 @@ return REQUEST_ID_INVALID; // Make sure there's a fetcher for this URL and attach to request. - const chrome::BitmapFetcher* fetcher = EnsureFetcherForUrl(url); + const chrome::BitmapFetcher* fetcher = + EnsureFetcherForUrl(url, traffic_annotation); request->set_fetcher(fetcher); requests_.push_back(request.release()); return requests_.back()->request_id(); } -void BitmapFetcherService::Prefetch(const GURL& url) { +void BitmapFetcherService::Prefetch( + const GURL& url, + const net::NetworkTrafficAnnotationTag& traffic_annotation) { if (url.is_valid()) - EnsureFetcherForUrl(url); + EnsureFetcherForUrl(url, traffic_annotation); } std::unique_ptr<chrome::BitmapFetcher> BitmapFetcherService::CreateFetcher( - const GURL& url) { + const GURL& url, + const net::NetworkTrafficAnnotationTag& traffic_annotation) { std::unique_ptr<chrome::BitmapFetcher> new_fetcher( - new chrome::BitmapFetcher(url, this)); + new chrome::BitmapFetcher(url, this, traffic_annotation)); new_fetcher->Init( content::BrowserContext::GetDefaultStoragePartition(context_)-> @@ -139,12 +144,14 @@ } const chrome::BitmapFetcher* BitmapFetcherService::EnsureFetcherForUrl( - const GURL& url) { + const GURL& url, + const net::NetworkTrafficAnnotationTag& traffic_annotation) { const chrome::BitmapFetcher* fetcher = FindFetcherForUrl(url); if (fetcher) return fetcher; - std::unique_ptr<chrome::BitmapFetcher> new_fetcher = CreateFetcher(url); + std::unique_ptr<chrome::BitmapFetcher> new_fetcher = + CreateFetcher(url, traffic_annotation); active_fetchers_.push_back(std::move(new_fetcher)); return active_fetchers_.back().get(); }
diff --git a/chrome/browser/bitmap_fetcher/bitmap_fetcher_service.h b/chrome/browser/bitmap_fetcher/bitmap_fetcher_service.h index b3bdcf2..8c8e355 100644 --- a/chrome/browser/bitmap_fetcher/bitmap_fetcher_service.h +++ b/chrome/browser/bitmap_fetcher/bitmap_fetcher_service.h
@@ -12,6 +12,7 @@ #include "base/memory/scoped_vector.h" #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_delegate.h" #include "components/keyed_service/core/keyed_service.h" +#include "net/traffic_annotation/network_traffic_annotation.h" namespace content { class BrowserContext; @@ -56,22 +57,30 @@ // downloaded one. // NOTE: The observer might be called back synchronously from RequestImage if // the image is already in the cache. - RequestId RequestImage(const GURL& url, Observer* observer); + RequestId RequestImage( + const GURL& url, + Observer* observer, + const net::NetworkTrafficAnnotationTag& traffic_annotation); // Start fetching the image at the given |url|. - void Prefetch(const GURL& url); + void Prefetch(const GURL& url, + const net::NetworkTrafficAnnotationTag& traffic_annotation); protected: // Create a bitmap fetcher for the given |url| and start it. Virtual method // so tests can override this for different behavior. - virtual std::unique_ptr<chrome::BitmapFetcher> CreateFetcher(const GURL& url); + virtual std::unique_ptr<chrome::BitmapFetcher> CreateFetcher( + const GURL& url, + const net::NetworkTrafficAnnotationTag& traffic_annotation); private: friend class BitmapFetcherServiceTest; // Gets the existing fetcher for |url| or constructs a new one if it doesn't // exist. - const chrome::BitmapFetcher* EnsureFetcherForUrl(const GURL& url); + const chrome::BitmapFetcher* EnsureFetcherForUrl( + const GURL& url, + const net::NetworkTrafficAnnotationTag& traffic_annotation); // Find a fetcher with a given |url|. Return NULL if none is found. const chrome::BitmapFetcher* FindFetcherForUrl(const GURL& url);
diff --git a/chrome/browser/bitmap_fetcher/bitmap_fetcher_service_unittest.cc b/chrome/browser/bitmap_fetcher/bitmap_fetcher_service_unittest.cc index 5c1bf07..b33b227 100644 --- a/chrome/browser/bitmap_fetcher/bitmap_fetcher_service_unittest.cc +++ b/chrome/browser/bitmap_fetcher/bitmap_fetcher_service_unittest.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h" #include "chrome/test/base/testing_profile.h" #include "content/public/test/test_browser_thread_bundle.h" +#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -48,8 +49,10 @@ // Create a fetcher, but don't start downloading. That allows side-stepping // the decode step, which requires a utility process. std::unique_ptr<chrome::BitmapFetcher> CreateFetcher( - const GURL& url) override { - return base::MakeUnique<chrome::BitmapFetcher>(url, this); + const GURL& url, + const net::NetworkTrafficAnnotationTag& traffic_annotation) override { + return base::MakeUnique<chrome::BitmapFetcher>(url, this, + traffic_annotation); } }; @@ -128,8 +131,8 @@ GURL invalid_url; ASSERT_FALSE(invalid_url.is_valid()); - BitmapFetcherService::RequestId request_id = - service_->RequestImage(invalid_url, new TestObserver(this)); + BitmapFetcherService::RequestId request_id = service_->RequestImage( + invalid_url, new TestObserver(this), TRAFFIC_ANNOTATION_FOR_TESTS); EXPECT_EQ(invalid_request_id, request_id); } @@ -141,18 +144,24 @@ TEST_F(BitmapFetcherServiceTest, OnlyFirstRequestCreatesFetcher) { EXPECT_EQ(0U, active_fetchers().size()); - service_->RequestImage(url1_, new TestObserver(this)); + service_->RequestImage(url1_, new TestObserver(this), + TRAFFIC_ANNOTATION_FOR_TESTS); EXPECT_EQ(1U, active_fetchers().size()); - service_->RequestImage(url1_, new TestObserver(this)); + service_->RequestImage(url1_, new TestObserver(this), + TRAFFIC_ANNOTATION_FOR_TESTS); EXPECT_EQ(1U, active_fetchers().size()); } TEST_F(BitmapFetcherServiceTest, CompletedFetchNotifiesAllObservers) { - service_->RequestImage(url1_, new TestObserver(this)); - service_->RequestImage(url1_, new TestObserver(this)); - service_->RequestImage(url1_, new TestObserver(this)); - service_->RequestImage(url1_, new TestObserver(this)); + service_->RequestImage(url1_, new TestObserver(this), + TRAFFIC_ANNOTATION_FOR_TESTS); + service_->RequestImage(url1_, new TestObserver(this), + TRAFFIC_ANNOTATION_FOR_TESTS); + service_->RequestImage(url1_, new TestObserver(this), + TRAFFIC_ANNOTATION_FOR_TESTS); + service_->RequestImage(url1_, new TestObserver(this), + TRAFFIC_ANNOTATION_FOR_TESTS); EXPECT_EQ(1U, active_fetchers().size()); EXPECT_EQ(4U, requests().size()); @@ -162,12 +171,16 @@ } TEST_F(BitmapFetcherServiceTest, CancelRequest) { - service_->RequestImage(url1_, new TestObserver(this)); - service_->RequestImage(url1_, new TestObserver(this)); - BitmapFetcherService::RequestId requestId = - service_->RequestImage(url2_, new TestObserver(this)); - service_->RequestImage(url1_, new TestObserver(this)); - service_->RequestImage(url1_, new TestObserver(this)); + service_->RequestImage(url1_, new TestObserver(this), + TRAFFIC_ANNOTATION_FOR_TESTS); + service_->RequestImage(url1_, new TestObserver(this), + TRAFFIC_ANNOTATION_FOR_TESTS); + BitmapFetcherService::RequestId requestId = service_->RequestImage( + url2_, new TestObserver(this), TRAFFIC_ANNOTATION_FOR_TESTS); + service_->RequestImage(url1_, new TestObserver(this), + TRAFFIC_ANNOTATION_FOR_TESTS); + service_->RequestImage(url1_, new TestObserver(this), + TRAFFIC_ANNOTATION_FOR_TESTS); EXPECT_EQ(5U, requests().size()); service_->CancelRequest(requestId); @@ -181,8 +194,10 @@ } TEST_F(BitmapFetcherServiceTest, FailedNullRequestsAreHandled) { - service_->RequestImage(url1_, new TestObserver(this)); - service_->RequestImage(url2_, new TestObserver(this)); + service_->RequestImage(url1_, new TestObserver(this), + TRAFFIC_ANNOTATION_FOR_TESTS); + service_->RequestImage(url2_, new TestObserver(this), + TRAFFIC_ANNOTATION_FOR_TESTS); EXPECT_EQ(0U, cache_size()); CompleteFetch(url1_); @@ -192,8 +207,10 @@ EXPECT_EQ(1U, cache_size()); } TEST_F(BitmapFetcherServiceTest, FailedRequestsDontEnterCache) { - service_->RequestImage(url1_, new TestObserver(this)); - service_->RequestImage(url2_, new TestObserver(this)); + service_->RequestImage(url1_, new TestObserver(this), + TRAFFIC_ANNOTATION_FOR_TESTS); + service_->RequestImage(url2_, new TestObserver(this), + TRAFFIC_ANNOTATION_FOR_TESTS); EXPECT_EQ(0U, cache_size()); CompleteFetch(url1_);
diff --git a/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.cc b/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.cc index 3ef7fddce..4c2aa11 100644 --- a/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.cc +++ b/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.cc
@@ -141,11 +141,6 @@ app_manager_->AddObserver(this); pref_change_registrar_.reset(new PrefChangeRegistrar()); pref_change_registrar_->Init(profile_->GetPrefs()); - // Try to start/stop kiosk app on policy compliance state change. - pref_change_registrar_->Add( - prefs::kArcPolicyCompliant, - base::Bind(&ArcKioskAppService::PreconditionsChanged, - base::Unretained(this))); notification_blocker_.reset(new ArcKioskNotificationBlocker()); PreconditionsChanged(); } @@ -159,9 +154,7 @@ if (app_id_.empty()) return; app_info_ = ArcAppListPrefs::Get(profile_)->GetApp(app_id_); - if (app_info_ && app_info_->ready && - profile_->GetPrefs()->GetBoolean(prefs::kArcPolicyCompliant) && - !maintenance_session_running_) { + if (app_info_ && app_info_->ready && !maintenance_session_running_) { if (!app_launcher_) app_launcher_ = base::MakeUnique<ArcKioskAppLauncher>( profile_, ArcAppListPrefs::Get(profile_), app_id_, this);
diff --git a/chrome/browser/chromeos/arc/policy/arc_policy_bridge.cc b/chrome/browser/chromeos/arc/policy/arc_policy_bridge.cc index df090969..9c9a8d0 100644 --- a/chrome/browser/chromeos/arc/policy/arc_policy_bridge.cc +++ b/chrome/browser/chromeos/arc/policy/arc_policy_bridge.cc
@@ -41,43 +41,7 @@ constexpr char kArcGlobalAppRestrictions[] = "globalAppRestrictions"; constexpr char kArcCaCerts[] = "caCerts"; -constexpr char kNonComplianceDetails[] = "nonComplianceDetails"; -constexpr char kNonComplianceReason[] = "nonComplianceReason"; constexpr char kPolicyCompliantJson[] = "{ \"policyCompliant\": true }"; -constexpr char kPolicyNonCompliantJson[] = "{ \"policyCompliant\": false }"; - -// Value from CloudDPS NonComplianceDetail.NonComplianceReason enum. -// Used to figure out whether to ignore non-compliance. -enum NonComplianceReason : int { - UNKNOWN = 0, - - // The API level of the device does not support the setting. - API_LEVEL = 1, - - // The admin type (profile owner, device owner, etc.) does not support the - // setting. - ADMIN_TYPE = 2, - - // The user has not taken required action to comply with the setting. - USER_ACTION = 3, - - // The setting has an invalid value. - INVALID_VALUE = 4, - - // A required application has not been (or cannot be) installed. - APP_NOT_INSTALLED = 5, - - // The policy is not supported by the version of CloudDPC on the device. - UNSUPPORTED = 6, -}; - -// ChromeOS should ignore some non-critical CloudDPC non-compliance reasons -// and proceed with starting ARC apps. -bool IgnoreNonComplianceReason(int reason) { - return reason == NonComplianceReason::API_LEVEL || - reason == NonComplianceReason::APP_NOT_INSTALLED || - reason == NonComplianceReason::UNSUPPORTED; -} // invert_bool_value: If the Chrome policy and the ARC policy with boolean value // have opposite semantics, set this to true so the bool is inverted before @@ -315,7 +279,9 @@ void OnReportComplianceParseFailure( const ArcPolicyBridge::ReportComplianceCallback& callback, const std::string& error) { - callback.Run(kPolicyNonCompliantJson); + // TODO(poromov@): Report to histogram. + DLOG(ERROR) << "Can't parse policy compliance report"; + callback.Run(kPolicyCompliantJson); } void UpdateFirstComplianceSinceSignInTiming( @@ -372,12 +338,6 @@ arc_bridge_service()->policy()->RemoveObserver(this); } -// static -void ArcPolicyBridge::RegisterProfilePrefs( - user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterBooleanPref(prefs::kArcPolicyCompliant, false); -} - void ArcPolicyBridge::OverrideIsManagedForTesting(bool is_managed) { is_managed_ = is_managed; } @@ -457,37 +417,12 @@ void ArcPolicyBridge::OnReportComplianceParseSuccess( const ArcPolicyBridge::ReportComplianceCallback& callback, std::unique_ptr<base::Value> parsed_json) { - const base::DictionaryValue* dict; - Profile* const profile = GetProfile(); - if (!profile || !parsed_json || !parsed_json->GetAsDictionary(&dict) || - !dict) { - callback.Run(kPolicyNonCompliantJson); - return; - } + // Always returns "compliant". + callback.Run(kPolicyCompliantJson); - // ChromeOS is 'compliant' with the report if all "nonComplianceDetails" - // entries have API_LEVEL, APP_NOT_INSTALLED or UNSUPPORTED reason. - bool compliant = true; - const base::ListValue* value = nullptr; - dict->GetList(kNonComplianceDetails, &value); - if (!dict->empty() && value && !value->empty()) { - for (const auto& entry : *value) { - const base::DictionaryValue* entry_dict; - int reason = 0; - // Get NonComplianceDetails.NonComplianceReason int enum value and check - // whether it shouldn't be ignored. - if (entry->GetAsDictionary(&entry_dict) && - entry_dict->GetInteger(kNonComplianceReason, &reason) && - !IgnoreNonComplianceReason(reason)) { - compliant = false; - break; - } - } - } - profile->GetPrefs()->SetBoolean(prefs::kArcPolicyCompliant, compliant); - callback.Run(compliant ? kPolicyCompliantJson : kPolicyNonCompliantJson); - - UpdateComplianceReportMetrics(dict); + const base::DictionaryValue* dict = nullptr; + if (parsed_json->GetAsDictionary(&dict)) + UpdateComplianceReportMetrics(dict); } void ArcPolicyBridge::UpdateComplianceReportMetrics(
diff --git a/chrome/browser/chromeos/arc/policy/arc_policy_bridge.h b/chrome/browser/chromeos/arc/policy/arc_policy_bridge.h index 4966c0a..51fa6d7 100644 --- a/chrome/browser/chromeos/arc/policy/arc_policy_bridge.h +++ b/chrome/browser/chromeos/arc/policy/arc_policy_bridge.h
@@ -46,8 +46,6 @@ policy::PolicyService* policy_service); ~ArcPolicyBridge() override; - static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); - void OverrideIsManagedForTesting(bool is_managed); // InstanceHolder<mojom::PolicyInstance>::Observer overrides.
diff --git a/chrome/browser/chromeos/arc/policy/arc_policy_bridge_unittest.cc b/chrome/browser/chromeos/arc/policy/arc_policy_bridge_unittest.cc index d2c2acf..59fc751 100644 --- a/chrome/browser/chromeos/arc/policy/arc_policy_bridge_unittest.cc +++ b/chrome/browser/chromeos/arc/policy/arc_policy_bridge_unittest.cc
@@ -57,7 +57,6 @@ "]}"; constexpr char kPolicyCompliantResponse[] = "{ \"policyCompliant\": true }"; -constexpr char kPolicyNonCompliantResponse[] = "{ \"policyCompliant\": false }"; // Helper class to define callbacks that verify that they were run. // Wraps a bool initially set to |false| and verifies that it's been set to @@ -416,26 +415,16 @@ policy_bridge()->ReportCompliance( "\"nonComplianceDetails\" : [}", PolicyComplianceCallback(run_loop().QuitClosure(), - kPolicyNonCompliantResponse)); + kPolicyCompliantResponse)); run_loop().Run(); } -TEST_F(ArcPolicyBridgeTest, ReportComplianceTest_NonCompliantReasons) { +TEST_F(ArcPolicyBridgeTest, ReportComplianceTest_WithNonCompliantDetails) { policy_bridge()->ReportCompliance( "{\"nonComplianceDetails\" : " "[{\"fieldPath\":\"\",\"nonComplianceReason\":0,\"packageName\":\"\"," "\"settingName\":\"someSetting\",\"cachedSize\":-1}]}", PolicyComplianceCallback(run_loop().QuitClosure(), - kPolicyNonCompliantResponse)); - run_loop().Run(); -} - -TEST_F(ArcPolicyBridgeTest, ReportComplianceTest_CompliantReasons) { - policy_bridge()->ReportCompliance( - "{\"nonComplianceDetails\" : " - "[{\"fieldPath\":\"\",\"nonComplianceReason\":1,\"packageName\":\"\"," - "\"settingName\":\"someSetting\",\"cachedSize\":-1}]}", - PolicyComplianceCallback(run_loop().QuitClosure(), kPolicyCompliantResponse)); run_loop().Run(); }
diff --git a/chrome/browser/chromeos/login/login_manager_test.cc b/chrome/browser/chromeos/login/login_manager_test.cc index 5e9bcdb..354f2dc 100644 --- a/chrome/browser/chromeos/login/login_manager_test.cc +++ b/chrome/browser/chromeos/login/login_manager_test.cc
@@ -201,8 +201,6 @@ const UserContext user_context = CreateUserContext(user_id); SetExpectedCredentials(user_context); EXPECT_TRUE(TryToLogin(user_context)); - // Let LoginDisplayHostImpl delete itself. - content::RunAllPendingInMessageLoop(); } void LoginManagerTest::AddUser(const std::string& user_id) {
diff --git a/chrome/browser/extensions/webstore_install_helper.cc b/chrome/browser/extensions/webstore_install_helper.cc index 691ec849..cd21e66 100644 --- a/chrome/browser/extensions/webstore_install_helper.cc +++ b/chrome/browser/extensions/webstore_install_helper.cc
@@ -10,6 +10,7 @@ #include "components/safe_json/safe_json_parser.h" #include "content/public/browser/browser_thread.h" #include "net/base/load_flags.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_request.h" using content::BrowserThread; @@ -53,7 +54,36 @@ // No existing |icon_fetcher_| to avoid unbalanced AddRef(). CHECK(!icon_fetcher_.get()); AddRef(); // Balanced in OnFetchComplete(). - icon_fetcher_.reset(new chrome::BitmapFetcher(icon_url_, this)); + + net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("webstore_install_helper", R"( + semantics { + sender: "Webstore Install Helper" + description: + "Fetches the bitmap corresponding to an extension icon." + trigger: + "This can happen in a few different circumstances: " + "1-User initiated an install from the Chrome Web Store." + "2-User initiated an inline installation from another website." + "3-Loading of kiosk app data on Chrome OS (provided that the " + "kiosk app is a Web Store app)." + data: + "The url of the icon for the extension, which includes the " + "extension id." + destination: GOOGLE_OWNED_SERVICE + } + policy { + cookies_allowed: false + setting: + "There's no direct Chromium's setting to disable this, but you " + "could uninstall all extensions and not install (or begin the " + "installation flow for) any more." + policy_exception_justification: + "Not implemented, considered not useful." + })"); + + icon_fetcher_.reset( + new chrome::BitmapFetcher(icon_url_, this, traffic_annotation)); icon_fetcher_->Init( context_getter_, std::string(), net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc index f63623c..965168fe 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.cc +++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -59,6 +59,7 @@ #include "components/metrics/drive_metrics_provider.h" #include "components/metrics/file_metrics_provider.h" #include "components/metrics/gpu/gpu_metrics_provider.h" +#include "components/metrics/metrics_log_uploader.h" #include "components/metrics/metrics_pref_names.h" #include "components/metrics/metrics_reporting_default_state.h" #include "components/metrics/metrics_service.h" @@ -515,11 +516,12 @@ ChromeMetricsServiceClient::CreateUploader( const std::string& server_url, const std::string& mime_type, + metrics::MetricsLogUploader::MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete) { return std::unique_ptr<metrics::MetricsLogUploader>( new metrics::NetMetricsLogUploader( - g_browser_process->system_request_context(), - server_url, mime_type, on_upload_complete)); + g_browser_process->system_request_context(), server_url, mime_type, + service_type, on_upload_complete)); } base::TimeDelta ChromeMetricsServiceClient::GetStandardUploadInterval() {
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.h b/chrome/browser/metrics/chrome_metrics_service_client.h index 24e87b3..dad283c 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.h +++ b/chrome/browser/metrics/chrome_metrics_service_client.h
@@ -18,6 +18,7 @@ #include "base/threading/thread_checker.h" #include "build/build_config.h" #include "chrome/browser/metrics/metrics_memory_details.h" +#include "components/metrics/metrics_log_uploader.h" #include "components/metrics/metrics_service_client.h" #include "components/metrics/profiler/tracking_synchronizer_observer.h" #include "components/metrics/proto/system_profile.pb.h" @@ -80,6 +81,7 @@ std::unique_ptr<metrics::MetricsLogUploader> CreateUploader( const std::string& server_url, const std::string& mime_type, + metrics::MetricsLogUploader::MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete) override; base::TimeDelta GetStandardUploadInterval() override; base::string16 GetRegistryBackupKey() override;
diff --git a/chrome/browser/ntp_snippets/ntp_snippets_features.cc b/chrome/browser/ntp_snippets/ntp_snippets_features.cc index 5af0a6f..6d5a891 100644 --- a/chrome/browser/ntp_snippets/ntp_snippets_features.cc +++ b/chrome/browser/ntp_snippets/ntp_snippets_features.cc
@@ -14,6 +14,7 @@ const char kNotificationsUseSnippetAsTextParam[] = "use_snippet_as_text"; const char kNotificationsKeepWhenFrontmostParam[] = "keep_notification_when_frontmost"; +const char kNotificationsOpenToNTPParam[] = "open_to_ntp"; const char kNotificationsDailyLimit[] = "daily_limit"; const char kNotificationsIgnoredLimitParam[] = "ignored_limit";
diff --git a/chrome/browser/ntp_snippets/ntp_snippets_features.h b/chrome/browser/ntp_snippets/ntp_snippets_features.h index 867077b7..a254064 100644 --- a/chrome/browser/ntp_snippets/ntp_snippets_features.h +++ b/chrome/browser/ntp_snippets/ntp_snippets_features.h
@@ -25,6 +25,10 @@ // "false": automatically dismiss notification when Chrome becomes frontmost. extern const char kNotificationsKeepWhenFrontmostParam[]; +// "true": notifications link to chrome://newtab, with appropriate text. +// "false": notifications link to URL of notifying article. +extern const char kNotificationsOpenToNTPParam[]; + // An integer. The maximum number of notifications that will be shown in 1 day. extern const char kNotificationsDailyLimit[]; constexpr int kNotificationsDefaultDailyLimit = 1;
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index cef77d3..75ca0ce 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -575,7 +575,6 @@ #if defined(OS_CHROMEOS) arc::ArcSessionManager::RegisterProfilePrefs(registry); - arc::ArcPolicyBridge::RegisterProfilePrefs(registry); chromeos::first_run::RegisterProfilePrefs(registry); chromeos::file_system_provider::RegisterProfilePrefs(registry); chromeos::KeyPermissions::RegisterProfilePrefs(registry);
diff --git a/chrome/browser/profiles/profile_avatar_downloader.cc b/chrome/browser/profiles/profile_avatar_downloader.cc index 6bfb7a88..e3647a0 100644 --- a/chrome/browser/profiles/profile_avatar_downloader.cc +++ b/chrome/browser/profiles/profile_avatar_downloader.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_avatar_icon_util.h" #include "net/base/load_flags.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #include "ui/gfx/image/image.h" namespace { @@ -27,7 +28,28 @@ DCHECK(!callback_.is_null()); GURL url(std::string(kHighResAvatarDownloadUrlPrefix) + profiles::GetDefaultAvatarIconFileNameAtIndex(icon_index)); - fetcher_.reset(new chrome::BitmapFetcher(url, this)); + net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("profile_avatar", R"( + semantics { + sender: "Profile Avatar Downloader" + description: + "The Chromium binary comes with a bundle of low-resolution " + "versions of avatar images. When the user selects an avatar in " + "chrome://settings, Chromium will download a high-resolution " + "version from Google's static content servers for use in the " + "people manager UI." + trigger: + "User selects a new avatar in chrome://settings for their profile" + data: "None, only the filename of the png to download." + destination: GOOGLE_OWNED_SERVICE + } + policy { + cookies_allowed: false + policy_exception_justification: + "No content is being uploaded or saved; this request merely " + "downloads a publicly available PNG file." + })"); + fetcher_.reset(new chrome::BitmapFetcher(url, this, traffic_annotation)); } ProfileAvatarDownloader::~ProfileAvatarDownloader() {
diff --git a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc index e4eac62b..c9da53c 100644 --- a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc +++ b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
@@ -525,21 +525,21 @@ class WindowDestroyer : public content::WebContentsObserver { public: WindowDestroyer(content::WebContents* web_contents, TabStripModel* model) - : content::WebContentsObserver(web_contents), - tab_strip_model_(model), - browser_closed_observer_(chrome::NOTIFICATION_BROWSER_CLOSED, - content::NotificationService::AllSources()) {} - - // Wait for the browser window to be destroyed. - void Wait() { browser_closed_observer_.Wait(); } + : content::WebContentsObserver(web_contents), tab_strip_model_(model) {} void RenderProcessGone(base::TerminationStatus status) override { + // Wait for the window to be destroyed, which will ensure all other + // RenderViewHost objects are deleted before we return and proceed with + // the next iteration of notifications. + content::WindowedNotificationObserver observer( + chrome::NOTIFICATION_BROWSER_CLOSED, + content::NotificationService::AllSources()); tab_strip_model_->CloseAllTabs(); + observer.Wait(); } private: TabStripModel* tab_strip_model_; - content::WindowedNotificationObserver browser_closed_observer_; DISALLOW_COPY_AND_ASSIGN(WindowDestroyer); }; @@ -572,12 +572,16 @@ // Create an object that will close the window on a process crash. WindowDestroyer destroyer(wc1, browser()->tab_strip_model()); + content::WindowedNotificationObserver observer( + chrome::NOTIFICATION_BROWSER_CLOSED, + content::NotificationService::AllSources()); + // Kill the renderer process, simulating a crash. This should the ProcessDied // method to be called. Alternatively, RenderProcessHost::OnChannelError can // be called to directly force a call to ProcessDied. wc1->GetRenderProcessHost()->Shutdown(-1, true); - destroyer.Wait(); + observer.Wait(); } // Sets up the browser in order to start the tests with two tabs open: one
diff --git a/chrome/browser/sessions/session_restore_stats_collector.cc b/chrome/browser/sessions/session_restore_stats_collector.cc index abc35130..b8459f9 100644 --- a/chrome/browser/sessions/session_restore_stats_collector.cc +++ b/chrome/browser/sessions/session_restore_stats_collector.cc
@@ -98,9 +98,7 @@ : tab_count(0u), tabs_deferred(0u), tabs_load_started(0u), - tabs_loaded(0u), - parallel_tab_loads(0u) { -} + tabs_loaded(0u) {} SessionRestoreStatsCollector::TabState::TabState( NavigationController* controller) @@ -397,11 +395,8 @@ tab_state->loading_state = TAB_IS_LOADING; ++loading_tab_count_; - if (!done_tracking_non_deferred_tabs_) { + if (!done_tracking_non_deferred_tabs_) ++tab_loader_stats_.tabs_load_started; - tab_loader_stats_.parallel_tab_loads = - std::max(tab_loader_stats_.parallel_tab_loads, loading_tab_count_); - } } void SessionRestoreStatsCollector::ReleaseIfDoneTracking() { @@ -516,9 +511,6 @@ base::Histogram::kUmaTargetedHistogramFlag); counter_for_count->AddTime(tab_loader_stats.non_deferred_tabs_loaded); } - - UMA_HISTOGRAM_COUNTS_100("SessionRestore.ParallelTabLoads", - tab_loader_stats.parallel_tab_loads); } void SessionRestoreStatsCollector::UmaStatsReportingDelegate::
diff --git a/chrome/browser/sessions/session_restore_stats_collector.h b/chrome/browser/sessions/session_restore_stats_collector.h index e7e3a883..ee52c3a 100644 --- a/chrome/browser/sessions/session_restore_stats_collector.h +++ b/chrome/browser/sessions/session_restore_stats_collector.h
@@ -103,10 +103,6 @@ // (vaguely named for historical reasons, as it predates the concept of // deferred tabs). base::TimeDelta non_deferred_tabs_loaded; - - // The maximum number of tabs loading in parallel. This corresponds to the - // "SessionRestore.ParallelTabLoads" metric. - size_t parallel_tab_loads; }; // The StatsReportingDelegate is responsible for delivering statistics
diff --git a/chrome/browser/sessions/session_restore_stats_collector_unittest.cc b/chrome/browser/sessions/session_restore_stats_collector_unittest.cc index ea2a8e0c..10082a60 100644 --- a/chrome/browser/sessions/session_restore_stats_collector_unittest.cc +++ b/chrome/browser/sessions/session_restore_stats_collector_unittest.cc
@@ -63,8 +63,7 @@ size_t tabs_loaded, int foreground_tab_first_loaded_ms, int foreground_tab_first_paint_ms, - int non_deferred_tabs_loaded_ms, - size_t parallel_tab_loads) { + int non_deferred_tabs_loaded_ms) { EXPECT_LT(0u, report_tab_loader_stats_call_count_); report_tab_loader_stats_call_count_--; @@ -78,7 +77,6 @@ tab_loader_stats_.foreground_tab_first_paint); EXPECT_EQ(base::TimeDelta::FromMilliseconds(non_deferred_tabs_loaded_ms), tab_loader_stats_.non_deferred_tabs_loaded); - EXPECT_EQ(parallel_tab_loads, tab_loader_stats_.parallel_tab_loads); } void ExpectReportTabDeferredCalled() { @@ -324,8 +322,7 @@ Tick(); // 2ms. GenerateLoadStop(0); - mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 0, 1, 1, 2, 1, 2, - 1); + mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 0, 1, 1, 2, 1, 2); mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); } @@ -343,8 +340,7 @@ Tick(); // 2ms. GenerateRenderWidgetHostDidUpdateBackingStore(0); - mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 0, 1, 1, 1, 2, 1, - 1); + mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 0, 1, 1, 1, 2, 1); mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); } @@ -385,8 +381,7 @@ Tick(); // 7ms. GenerateLoadStop(2); - mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(3, 0, 3, 3, 2, 1, 7, - 1); + mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(3, 0, 3, 3, 2, 1, 7); mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); mock_reporting_delegate.EnsureNoUnexpectedCalls(); } @@ -426,8 +421,7 @@ mock_reporting_delegate.EnsureNoUnexpectedCalls(); Tick(); // 6ms. GenerateLoadStop(2); - mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(3, 0, 3, 3, 2, 1, 6, - 2); + mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(3, 0, 3, 3, 2, 1, 6); mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); mock_reporting_delegate.EnsureNoUnexpectedCalls(); } @@ -453,8 +447,7 @@ // Foreground tab finishes loading and stats get reported. Tick(); // 2ms. GenerateLoadStop(0); - mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(2, 1, 1, 1, 2, 1, 2, - 1); + mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(2, 1, 1, 1, 2, 1, 2); mock_reporting_delegate.EnsureNoUnexpectedCalls(); // Background tab starts loading, paints and stops loading. This fires off a @@ -501,8 +494,7 @@ // stats to be emitted, but with empty foreground paint and load values. Tick(); // 3ms. GenerateRenderWidgetHostDidUpdateBackingStore(1); - mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 0, 1, 1, 0, 0, 2, - 1); + mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 0, 1, 1, 0, 0, 2); mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); mock_reporting_delegate.EnsureNoUnexpectedCalls(); } @@ -538,8 +530,7 @@ // stats to be emitted, but with an empty foreground paint value. Tick(); // 3ms. GenerateRenderWidgetHostDidUpdateBackingStore(1); - mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 0, 1, 1, 1, 0, 1, - 1); + mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 0, 1, 1, 1, 0, 1); mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); mock_reporting_delegate.EnsureNoUnexpectedCalls(); } @@ -555,8 +546,7 @@ // Destroy the tab. Expect all timings to be zero. GenerateWebContentsDestroyed(0); - mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 0, 1, 0, 0, 0, 0, - 1); + mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 0, 1, 0, 0, 0, 0); mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); mock_reporting_delegate.EnsureNoUnexpectedCalls(); } @@ -576,8 +566,7 @@ // Destroy the tab. Expect both load timings to be zero. GenerateWebContentsDestroyed(0); - mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 0, 1, 0, 0, 1, 0, - 1); + mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 0, 1, 0, 0, 1, 0); mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); mock_reporting_delegate.EnsureNoUnexpectedCalls(); } @@ -599,8 +588,7 @@ // Reload the tab. Expect the paint timing to be zero. Tick(); // 2 ms. GenerateLoadStart(0); - mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 0, 1, 1, 1, 0, 1, - 1); + mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 0, 1, 1, 1, 0, 1); mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); mock_reporting_delegate.EnsureNoUnexpectedCalls(); } @@ -625,8 +613,7 @@ // with all zero timings. Tick(); // 2 ms. GenerateWebContentsDestroyed(0); - mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(2, 1, 1, 0, 0, 0, 0, - 1); + mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(2, 1, 1, 0, 0, 0, 0); mock_reporting_delegate.EnsureNoUnexpectedCalls(); // Destroy the background tab. The collector should release itself.
diff --git a/chrome/browser/sessions/session_service.cc b/chrome/browser/sessions/session_service.cc index 185ad29..2cc27dc 100644 --- a/chrome/browser/sessions/session_service.cc +++ b/chrome/browser/sessions/session_service.cc
@@ -77,9 +77,6 @@ this)), has_open_trackable_browsers_(false), move_on_new_browser_(false), - save_delay_in_millis_(base::TimeDelta::FromMilliseconds(2500)), - save_delay_in_mins_(base::TimeDelta::FromMinutes(10)), - save_delay_in_hrs_(base::TimeDelta::FromHours(8)), force_browser_not_alive_with_no_windows_(false), weak_factory_(this) { // We should never be created when incognito. @@ -96,9 +93,6 @@ this)), has_open_trackable_browsers_(false), move_on_new_browser_(false), - save_delay_in_millis_(base::TimeDelta::FromMilliseconds(2500)), - save_delay_in_mins_(base::TimeDelta::FromMinutes(10)), - save_delay_in_hrs_(base::TimeDelta::FromHours(8)), force_browser_not_alive_with_no_windows_(false), weak_factory_(this) { Init(); @@ -354,8 +348,6 @@ TabClosed(session_tab_helper->window_id(), session_tab_helper->session_id(), contents->GetClosedByUserGesture()); - RecordSessionUpdateHistogramData(content::NOTIFICATION_WEB_CONTENTS_DESTROYED, - &last_updated_tab_closed_time_); } void SessionService::SetWindowType(const SessionID& window_id, @@ -526,8 +518,6 @@ } void SessionService::OnSavedCommands() { - RecordSessionUpdateHistogramData(chrome::NOTIFICATION_SESSION_SERVICE_SAVED, - &last_updated_save_time_); content::NotificationService::current()->Notify( chrome::NOTIFICATION_SESSION_SERVICE_SAVED, content::Source<Profile>(profile()), @@ -628,8 +618,6 @@ session_tab_helper->session_id(), web_contents->GetController().GetEntryCount()); } - RecordSessionUpdateHistogramData(type, - &last_updated_nav_list_pruned_time_); break; } @@ -675,11 +663,6 @@ session_tab_helper->session_id(), navigation); content::Details<content::LoadCommittedDetails> changed(details); - if (changed->type == content::NAVIGATION_TYPE_NEW_PAGE || - changed->type == content::NAVIGATION_TYPE_EXISTING_PAGE) { - RecordSessionUpdateHistogramData(type, - &last_updated_nav_entry_commit_time_); - } break; } @@ -974,113 +957,6 @@ browser->is_app() ? TYPE_APP : TYPE_NORMAL); } -void SessionService::RecordSessionUpdateHistogramData(int type, - base::TimeTicks* last_updated_time) { - if (!last_updated_time->is_null()) { - base::TimeDelta delta = base::TimeTicks::Now() - *last_updated_time; - // We're interested in frequent updates periods longer than - // 10 minutes. - bool use_long_period = false; - if (delta >= save_delay_in_mins_) { - use_long_period = true; - } - switch (type) { - case chrome::NOTIFICATION_SESSION_SERVICE_SAVED : - RecordUpdatedSaveTime(delta, use_long_period); - break; - case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: - RecordUpdatedTabClosed(delta, use_long_period); - break; - case content::NOTIFICATION_NAV_LIST_PRUNED: - RecordUpdatedNavListPruned(delta, use_long_period); - break; - case content::NOTIFICATION_NAV_ENTRY_COMMITTED: - RecordUpdatedNavEntryCommit(delta, use_long_period); - break; - default: - NOTREACHED() << "Bad type sent to RecordSessionUpdateHistogramData"; - break; - } - } - (*last_updated_time) = base::TimeTicks::Now(); -} - -void SessionService::RecordUpdatedTabClosed(base::TimeDelta delta, - bool use_long_period) { - std::string name("SessionRestore.TabClosedPeriod"); - UMA_HISTOGRAM_CUSTOM_TIMES(name, - delta, - // 2500ms is the default save delay. - save_delay_in_millis_, - save_delay_in_mins_, - 50); - if (use_long_period) { - std::string long_name_("SessionRestore.TabClosedLongPeriod"); - UMA_HISTOGRAM_CUSTOM_TIMES(long_name_, - delta, - save_delay_in_mins_, - save_delay_in_hrs_, - 50); - } -} - -void SessionService::RecordUpdatedNavListPruned(base::TimeDelta delta, - bool use_long_period) { - std::string name("SessionRestore.NavigationListPrunedPeriod"); - UMA_HISTOGRAM_CUSTOM_TIMES(name, - delta, - // 2500ms is the default save delay. - save_delay_in_millis_, - save_delay_in_mins_, - 50); - if (use_long_period) { - std::string long_name_("SessionRestore.NavigationListPrunedLongPeriod"); - UMA_HISTOGRAM_CUSTOM_TIMES(long_name_, - delta, - save_delay_in_mins_, - save_delay_in_hrs_, - 50); - } -} - -void SessionService::RecordUpdatedNavEntryCommit(base::TimeDelta delta, - bool use_long_period) { - std::string name("SessionRestore.NavEntryCommittedPeriod"); - UMA_HISTOGRAM_CUSTOM_TIMES(name, - delta, - // 2500ms is the default save delay. - save_delay_in_millis_, - save_delay_in_mins_, - 50); - if (use_long_period) { - std::string long_name_("SessionRestore.NavEntryCommittedLongPeriod"); - UMA_HISTOGRAM_CUSTOM_TIMES(long_name_, - delta, - save_delay_in_mins_, - save_delay_in_hrs_, - 50); - } -} - -void SessionService::RecordUpdatedSaveTime(base::TimeDelta delta, - bool use_long_period) { - std::string name("SessionRestore.SavePeriod"); - UMA_HISTOGRAM_CUSTOM_TIMES(name, - delta, - // 2500ms is the default save delay. - save_delay_in_millis_, - save_delay_in_mins_, - 50); - if (use_long_period) { - std::string long_name_("SessionRestore.SaveLongPeriod"); - UMA_HISTOGRAM_CUSTOM_TIMES(long_name_, - delta, - save_delay_in_mins_, - save_delay_in_hrs_, - 50); - } -} - void SessionService::MaybeDeleteSessionOnlyData() { // Don't try anything if we're testing. The browser_process is not fully // created and DeleteSession will crash if we actually attempt it.
diff --git a/chrome/browser/sessions/session_service.h b/chrome/browser/sessions/session_service.h index 15ec48c..e11a7f2 100644 --- a/chrome/browser/sessions/session_service.h +++ b/chrome/browser/sessions/session_service.h
@@ -325,12 +325,6 @@ void RecordSessionUpdateHistogramData(int type, base::TimeTicks* last_updated_time); - // Helper methods to record the histogram data - void RecordUpdatedTabClosed(base::TimeDelta delta, bool use_long_period); - void RecordUpdatedNavListPruned(base::TimeDelta delta, bool use_long_period); - void RecordUpdatedNavEntryCommit(base::TimeDelta delta, bool use_long_period); - void RecordUpdatedSaveTime(base::TimeDelta delta, bool use_long_period); - // Deletes session data if no windows are open for the current profile. void MaybeDeleteSessionOnlyData(); @@ -387,17 +381,6 @@ // current/last session. bool move_on_new_browser_; - // Used for reporting frequency of session altering operations. - base::TimeTicks last_updated_tab_closed_time_; - base::TimeTicks last_updated_nav_list_pruned_time_; - base::TimeTicks last_updated_nav_entry_commit_time_; - base::TimeTicks last_updated_save_time_; - - // Constants used in calculating histogram data. - const base::TimeDelta save_delay_in_millis_; - const base::TimeDelta save_delay_in_mins_; - const base::TimeDelta save_delay_in_hrs_; - // For browser_tests, since we want to simulate the browser shutting down // without quitting. bool force_browser_not_alive_with_no_windows_;
diff --git a/chrome/browser/ui/login/login_handler_browsertest.cc b/chrome/browser/ui/login/login_handler_browsertest.cc index 63cd691..d3e1ca5 100644 --- a/chrome/browser/ui/login/login_handler_browsertest.cc +++ b/chrome/browser/ui/login/login_handler_browsertest.cc
@@ -98,7 +98,6 @@ const char kMultiRealmTestPage[] = "/login/multi_realm.html"; const int kMultiRealmTestRealmCount = 2; -const int kMultiRealmTestAuthRequestsCount = 4; const char kSingleRealmTestPage[] = "/login/single_realm.html"; @@ -461,102 +460,104 @@ // Test handling of resources that require authentication even though // the page they are included on doesn't. In this case we should only // present the minimal number of prompts necessary for successfully -// displaying the page. -class MultiRealmLoginPromptBrowserTest : public LoginPromptBrowserTest { - public: - void TearDownOnMainThread() override { - login_prompt_observer_.UnregisterAll(); - LoginPromptBrowserTest::TearDownOnMainThread(); - } - - // Load the multi-realm test page, waits for LoginHandlers to be created, then - // calls |for_each_realm_func| once for each authentication realm, passing a - // LoginHandler for the realm as an argument. The page should stop loading - // after that. - template <class F> - void RunTest(const F& for_each_realm_func); - - NavigationController* GetNavigationController() { - return &browser() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetController(); - } - - LoginPromptBrowserTestObserver* login_prompt_observer() { - return &login_prompt_observer_; - } - - private: - LoginPromptBrowserTestObserver login_prompt_observer_; -}; - -template <class F> -void MultiRealmLoginPromptBrowserTest::RunTest(const F& for_each_realm_func) { +// displaying the page. First we check whether cancelling works as +// expected. +IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmCancellation) { ASSERT_TRUE(embedded_test_server()->Start()); GURL test_page = embedded_test_server()->GetURL(kMultiRealmTestPage); - NavigationController* controller = GetNavigationController(); + content::WebContents* contents = + browser()->tab_strip_model()->GetActiveWebContents(); + NavigationController* controller = &contents->GetController(); + LoginPromptBrowserTestObserver observer; - login_prompt_observer_.Register( - content::Source<NavigationController>(controller)); + observer.Register(content::Source<NavigationController>(controller)); WindowedLoadStopObserver load_stop_waiter(controller, 1); - browser()->OpenURL(OpenURLParams(test_page, Referrer(), - WindowOpenDisposition::CURRENT_TAB, - ui::PAGE_TRANSITION_TYPED, false)); + { + WindowedAuthNeededObserver auth_needed_waiter(controller); + browser()->OpenURL(OpenURLParams(test_page, Referrer(), + WindowOpenDisposition::CURRENT_TAB, + ui::PAGE_TRANSITION_TYPED, false)); + auth_needed_waiter.Wait(); + } - // Need to have LoginHandlers created for all requests that need - // authentication. - while (login_prompt_observer_.handlers().size() < - kMultiRealmTestAuthRequestsCount) - WindowedAuthNeededObserver(controller).Wait(); + int n_handlers = 0; - // Now confirm or cancel auth once per realm. - std::set<std::string> seen_realms; - for (int i = 0; i < kMultiRealmTestRealmCount; ++i) { - auto it = std::find_if( - login_prompt_observer_.handlers().begin(), - login_prompt_observer_.handlers().end(), - [&seen_realms](LoginHandler* handler) { - return seen_realms.count(handler->auth_info()->realm) == 0; - }); - ASSERT_TRUE(it != login_prompt_observer_.handlers().end()); - seen_realms.insert((*it)->auth_info()->realm); + while (n_handlers < kMultiRealmTestRealmCount) { + WindowedAuthNeededObserver auth_needed_waiter(controller); - for_each_realm_func(*it); + while (!observer.handlers().empty()) { + WindowedAuthCancelledObserver auth_cancelled_waiter(controller); + LoginHandler* handler = *observer.handlers().begin(); + + ASSERT_TRUE(handler); + n_handlers++; + handler->CancelAuth(); + auth_cancelled_waiter.Wait(); + } + + if (n_handlers < kMultiRealmTestRealmCount) + auth_needed_waiter.Wait(); } load_stop_waiter.Wait(); + + EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers); + EXPECT_EQ(0, observer.auth_supplied_count()); + EXPECT_LT(0, observer.auth_needed_count()); + EXPECT_LT(0, observer.auth_cancelled_count()); } -// Checks that cancelling works as expected. -IN_PROC_BROWSER_TEST_F(MultiRealmLoginPromptBrowserTest, - MultipleRealmCancellation) { - RunTest([this](LoginHandler* handler) { - WindowedAuthCancelledObserver waiter(GetNavigationController()); - handler->CancelAuth(); - waiter.Wait(); - }); +// Similar to the MultipleRealmCancellation test above, but tests +// whether supplying credentials work as exepcted. +IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmConfirmation) { + ASSERT_TRUE(embedded_test_server()->Start()); + GURL test_page = embedded_test_server()->GetURL(kMultiRealmTestPage); - EXPECT_EQ(0, login_prompt_observer()->auth_supplied_count()); - EXPECT_LT(0, login_prompt_observer()->auth_needed_count()); - EXPECT_LT(0, login_prompt_observer()->auth_cancelled_count()); -} + content::WebContents* contents = + browser()->tab_strip_model()->GetActiveWebContents(); + NavigationController* controller = &contents->GetController(); + LoginPromptBrowserTestObserver observer; -// Checks that supplying credentials works as exepcted. -IN_PROC_BROWSER_TEST_F(MultiRealmLoginPromptBrowserTest, - MultipleRealmConfirmation) { - RunTest([this](LoginHandler* handler) { - WindowedAuthSuppliedObserver waiter(GetNavigationController()); - SetAuthFor(handler); - waiter.Wait(); - }); + observer.Register(content::Source<NavigationController>(controller)); - EXPECT_LT(0, login_prompt_observer()->auth_needed_count()); - EXPECT_LT(0, login_prompt_observer()->auth_supplied_count()); - EXPECT_EQ(0, login_prompt_observer()->auth_cancelled_count()); + WindowedLoadStopObserver load_stop_waiter(controller, 1); + int n_handlers = 0; + + { + WindowedAuthNeededObserver auth_needed_waiter(controller); + + browser()->OpenURL(OpenURLParams(test_page, Referrer(), + WindowOpenDisposition::CURRENT_TAB, + ui::PAGE_TRANSITION_TYPED, false)); + auth_needed_waiter.Wait(); + } + + while (n_handlers < kMultiRealmTestRealmCount) { + WindowedAuthNeededObserver auth_needed_waiter(controller); + + while (!observer.handlers().empty()) { + WindowedAuthSuppliedObserver auth_supplied_waiter(controller); + LoginHandler* handler = *observer.handlers().begin(); + + ASSERT_TRUE(handler); + n_handlers++; + SetAuthFor(handler); + auth_supplied_waiter.Wait(); + } + + if (n_handlers < kMultiRealmTestRealmCount) + auth_needed_waiter.Wait(); + } + + load_stop_waiter.Wait(); + + EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers); + EXPECT_LT(0, observer.auth_needed_count()); + EXPECT_LT(0, observer.auth_supplied_count()); + EXPECT_EQ(0, observer.auth_cancelled_count()); } // Testing for recovery from an incorrect password for the case where
diff --git a/chrome/browser/ui/login/login_handler_test_utils.cc b/chrome/browser/ui/login/login_handler_test_utils.cc index d1c419d7..a0814c6b 100644 --- a/chrome/browser/ui/login/login_handler_test_utils.cc +++ b/chrome/browser/ui/login/login_handler_test_utils.cc
@@ -57,10 +57,6 @@ registrar_.Add(this, chrome::NOTIFICATION_AUTH_CANCELLED, source); } -void LoginPromptBrowserTestObserver::UnregisterAll() { - registrar_.RemoveAll(); -} - WindowedLoadStopObserver::WindowedLoadStopObserver( content::NavigationController* controller, int notification_count)
diff --git a/chrome/browser/ui/login/login_handler_test_utils.h b/chrome/browser/ui/login/login_handler_test_utils.h index bf277a0..8f32a54f 100644 --- a/chrome/browser/ui/login/login_handler_test_utils.h +++ b/chrome/browser/ui/login/login_handler_test_utils.h
@@ -31,7 +31,6 @@ void RemoveHandler(LoginHandler* handler); void Register(const content::NotificationSource& source); - void UnregisterAll(); const std::list<LoginHandler*>& handlers() const { return handlers_; }
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc index 3e12199..19b3da3 100644 --- a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc +++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
@@ -48,6 +48,7 @@ #include "content/public/browser/navigation_entry.h" #include "content/public/browser/web_contents.h" #include "extensions/common/constants.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/window_open_disposition.h" #include "url/gurl.h" @@ -289,11 +290,53 @@ BitmapFetcherServiceFactory::GetForBrowserContext(profile_); if (image_service) { image_service->CancelRequest(request_id_); + + // TODO(jdonnelly, rhalavati): Create a helper function with Callback to + // create annotation and pass it to image_service, merging this annotation + // and the one in + // chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc + net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("omnibox_result_change", R"( + semantics { + sender: "Omnibox" + description: + "Chromium provides answers in the suggestion list for " + "certain queries that user types in the omnibox. This request " + "retrieves a small image (for example, an icon illustrating " + "the current weather conditions) when this can add information " + "to an answer." + trigger: + "Change of results for the query typed by the user in the " + "omnibox." + data: + "The only data sent is the path to an image. No user data is " + "included, although some might be inferrable (e.g. whether the " + "weather is sunny or rainy in the user's current location) " + "from the name of the image in the path." + destination: WEBSITE + } + policy { + cookies_allowed: true + cookies_store: "user" + setting: + "You can enable or disable this feature via 'Use a prediction " + "service to help complete searches and URLs typed in the " + "address bar.' in Chromium's settings under Advanced. The " + "feature is enabled by default." + policy { + SearchSuggestEnabled { + policy_options {mode: MANDATORY} + value: false + } + } + })"); + request_id_ = image_service->RequestImage( match->answer->second_line().image_url(), new AnswerImageObserver( base::Bind(&ChromeOmniboxClient::OnBitmapFetched, - base::Unretained(this), on_bitmap_fetched))); + base::Unretained(this), on_bitmap_fetched)), + traffic_annotation); } } }
diff --git a/chrome/browser/ui/passwords/account_avatar_fetcher.cc b/chrome/browser/ui/passwords/account_avatar_fetcher.cc index b12c625..c842cc0 100644 --- a/chrome/browser/ui/passwords/account_avatar_fetcher.cc +++ b/chrome/browser/ui/passwords/account_avatar_fetcher.cc
@@ -5,15 +5,49 @@ #include "chrome/browser/ui/passwords/account_avatar_fetcher.h" #include "net/base/load_flags.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_operations.h" +namespace { + +constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation = + net::DefineNetworkTrafficAnnotation("credenential_avatar", R"( + semantics { + sender: "Chrome Password Manager" + description: + "Every credential saved in Chromium via the Credential Management " + "API can have an avatar URL. The URL is essentially provided by " + "the site calling the API. The avatar is used in the account " + "chooser UI and auto signin toast which appear when a site calls " + "navigator.credentials.get(). The avatar is retrieved before " + "showing the UI." + trigger: + "User visits a site that calls navigator.credentials.get(). " + "Assuming there are matching credentials in the Chromium password " + "store, the avatars are retrieved." + destination: WEBSITE + } + policy { + cookies_allowed: false + setting: + "One can disable saving new credentials in the settings (see " + "'Passwords and forms'). There is no setting to disable the API." + policy { + PasswordManagerEnabled { + policy_options {mode: MANDATORY} + value: false + } + } + })"); + +} // namespace + AccountAvatarFetcher::AccountAvatarFetcher( const GURL& url, const base::WeakPtr<AccountAvatarFetcherDelegate>& delegate) - : fetcher_(url, this), delegate_(delegate) { -} + : fetcher_(url, this, kTrafficAnnotation), delegate_(delegate) {} AccountAvatarFetcher::~AccountAvatarFetcher() = default;
diff --git a/chrome/browser/ui/views/find_bar_views_interactive_uitest.cc b/chrome/browser/ui/views/find_bar_views_interactive_uitest.cc index aa13796b..497aa60f 100644 --- a/chrome/browser/ui/views/find_bar_views_interactive_uitest.cc +++ b/chrome/browser/ui/views/find_bar_views_interactive_uitest.cc
@@ -85,14 +85,6 @@ return details; } - FindNotificationDetails WaitForFinalFindResult() { - while (true) { - auto details = WaitForFindResult(); - if (details.final_update()) - return details; - } - } - private: DISALLOW_COPY_AND_ASSIGN(FindInPageTest); }; @@ -191,28 +183,28 @@ // Clicking the next and previous buttons should not alter the focused view. ClickOnView(next_button); - EXPECT_EQ(2, WaitForFinalFindResult().active_match_ordinal()); + EXPECT_EQ(2, WaitForFindResult().active_match_ordinal()); EXPECT_TRUE(IsViewFocused(browser(), VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); ClickOnView(previous_button); - EXPECT_EQ(1, WaitForFinalFindResult().active_match_ordinal()); + EXPECT_EQ(1, WaitForFindResult().active_match_ordinal()); EXPECT_TRUE(IsViewFocused(browser(), VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); // Tapping the next and previous buttons should not alter the focused view. TapOnView(next_button); - EXPECT_EQ(2, WaitForFinalFindResult().active_match_ordinal()); + EXPECT_EQ(2, WaitForFindResult().active_match_ordinal()); EXPECT_TRUE(IsViewFocused(browser(), VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); TapOnView(previous_button); - EXPECT_EQ(1, WaitForFinalFindResult().active_match_ordinal()); + EXPECT_EQ(1, WaitForFindResult().active_match_ordinal()); EXPECT_TRUE(IsViewFocused(browser(), VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); // The same should be true even when the previous button is focused. previous_button->RequestFocus(); EXPECT_TRUE(IsViewFocused(browser(), VIEW_ID_FIND_IN_PAGE_PREVIOUS_BUTTON)); ClickOnView(next_button); - EXPECT_EQ(2, WaitForFinalFindResult().active_match_ordinal()); + EXPECT_EQ(2, WaitForFindResult().active_match_ordinal()); EXPECT_TRUE(IsViewFocused(browser(), VIEW_ID_FIND_IN_PAGE_PREVIOUS_BUTTON)); TapOnView(next_button); - EXPECT_EQ(3, WaitForFinalFindResult().active_match_ordinal()); + EXPECT_EQ(3, WaitForFindResult().active_match_ordinal()); EXPECT_TRUE(IsViewFocused(browser(), VIEW_ID_FIND_IN_PAGE_PREVIOUS_BUTTON)); }
diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc index 19bdcb64..c5853e0 100644 --- a/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc +++ b/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc
@@ -103,12 +103,6 @@ private: void RegisterMessages() override; - void RegisterMessage(const std::string& message, - const content::WebUI::MessageCallback& handler); - - void HandleMessage(const content::WebUI::MessageCallback& handler, - const base::ListValue* data); - // Runs NetInternalsTest.callback with the given value. void RunJavascriptCallback(base::Value* value); @@ -164,56 +158,35 @@ } void NetInternalsTest::MessageHandler::RegisterMessages() { - RegisterMessage( - "getTestServerURL", + web_ui()->RegisterMessageCallback("getTestServerURL", base::Bind(&NetInternalsTest::MessageHandler::GetTestServerURL, base::Unretained(this))); - RegisterMessage("addCacheEntry", - base::Bind(&NetInternalsTest::MessageHandler::AddCacheEntry, - base::Unretained(this))); - RegisterMessage("loadPage", - base::Bind(&NetInternalsTest::MessageHandler::LoadPage, - base::Unretained(this))); - RegisterMessage("prerenderPage", - base::Bind(&NetInternalsTest::MessageHandler::PrerenderPage, - base::Unretained(this))); - RegisterMessage( - "navigateToPrerender", + web_ui()->RegisterMessageCallback("addCacheEntry", + base::Bind(&NetInternalsTest::MessageHandler::AddCacheEntry, + base::Unretained(this))); + web_ui()->RegisterMessageCallback("loadPage", + base::Bind(&NetInternalsTest::MessageHandler::LoadPage, + base::Unretained(this))); + web_ui()->RegisterMessageCallback("prerenderPage", + base::Bind(&NetInternalsTest::MessageHandler::PrerenderPage, + base::Unretained(this))); + web_ui()->RegisterMessageCallback("navigateToPrerender", base::Bind(&NetInternalsTest::MessageHandler::NavigateToPrerender, base::Unretained(this))); - RegisterMessage( - "createIncognitoBrowser", + web_ui()->RegisterMessageCallback("createIncognitoBrowser", base::Bind(&NetInternalsTest::MessageHandler::CreateIncognitoBrowser, base::Unretained(this))); - RegisterMessage( - "closeIncognitoBrowser", + web_ui()->RegisterMessageCallback("closeIncognitoBrowser", base::Bind(&NetInternalsTest::MessageHandler::CloseIncognitoBrowser, base::Unretained(this))); - RegisterMessage( - "getNetLogFileContents", - base::Bind(&NetInternalsTest::MessageHandler::GetNetLogFileContents, - base::Unretained(this))); - RegisterMessage( - "enableDataReductionProxy", - base::Bind(&NetInternalsTest::MessageHandler::EnableDataReductionProxy, - base::Unretained(this))); -} - -void NetInternalsTest::MessageHandler::RegisterMessage( - const std::string& message, - const content::WebUI::MessageCallback& handler) { - web_ui()->RegisterMessageCallback( - message, base::Bind(&NetInternalsTest::MessageHandler::HandleMessage, - base::Unretained(this), handler)); -} - -void NetInternalsTest::MessageHandler::HandleMessage( - const content::WebUI::MessageCallback& handler, - const base::ListValue* data) { - // The handler might run a nested loop to wait for something. - base::MessageLoop::ScopedNestableTaskAllower nestable_task_allower( - base::MessageLoop::current()); - handler.Run(data); + web_ui()->RegisterMessageCallback("getNetLogFileContents", + base::Bind( + &NetInternalsTest::MessageHandler::GetNetLogFileContents, + base::Unretained(this))); + web_ui()->RegisterMessageCallback("enableDataReductionProxy", + base::Bind( + &NetInternalsTest::MessageHandler::EnableDataReductionProxy, + base::Unretained(this))); } void NetInternalsTest::MessageHandler::RunJavascriptCallback(
diff --git a/chrome/browser/win/enumerate_modules_model.cc b/chrome/browser/win/enumerate_modules_model.cc index c9349cf..47eae22 100644 --- a/chrome/browser/win/enumerate_modules_model.cc +++ b/chrome/browser/win/enumerate_modules_model.cc
@@ -28,7 +28,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "base/threading/sequenced_worker_pool.h" +#include "base/task_scheduler/post_task.h" #include "base/time/time.h" #include "base/values.h" #include "base/version.h" @@ -163,10 +163,15 @@ } ModuleEnumerator::ModuleEnumerator(EnumerateModulesModel* observer) - : enumerated_modules_(nullptr), + : background_task_runner_(base::CreateTaskRunnerWithTraits( + base::TaskTraits() + .MayBlock() + .WithPriority(base::TaskPriority::BACKGROUND) + .WithShutdownBehavior( + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN))), + enumerated_modules_(nullptr), observer_(observer), - per_module_delay_(kDefaultPerModuleDelay) { -} + per_module_delay_(kDefaultPerModuleDelay) {} ModuleEnumerator::~ModuleEnumerator() { } @@ -178,11 +183,9 @@ // This object can't be reaped until it has finished scanning, so its safe // to post a raw pointer to another thread. It will simply be leaked if the // scanning has not been finished before shutdown. - BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior( + background_task_runner_->PostTask( FROM_HERE, - base::Bind(&ModuleEnumerator::ScanImplStart, - base::Unretained(this)), - base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); + base::Bind(&ModuleEnumerator::ScanImplStart, base::Unretained(this))); } void ModuleEnumerator::SetPerModuleDelayToZero() { @@ -225,25 +228,12 @@ // Post a delayed task to scan the first module. This forwards directly to // ScanImplFinish if there are no modules to scan. - BrowserThread::GetBlockingPool()->PostDelayedWorkerTask( + background_task_runner_->PostDelayedTask( FROM_HERE, - base::Bind(&ModuleEnumerator::ScanImplModule, - base::Unretained(this), - 0), + base::Bind(&ModuleEnumerator::ScanImplModule, base::Unretained(this), 0), per_module_delay_); } -void ModuleEnumerator::ScanImplDelay(size_t index) { - // Bounce this over to a CONTINUE_ON_SHUTDOWN task in the same pool. This is - // necessary to prevent shutdown hangs while inspecting a module. - BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior( - FROM_HERE, - base::Bind(&ModuleEnumerator::ScanImplModule, - base::Unretained(this), - index), - base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); -} - void ModuleEnumerator::ScanImplModule(size_t index) { while (index < enumerated_modules_->size()) { base::TimeTicks start_time = base::TimeTicks::Now(); @@ -255,14 +245,12 @@ enumeration_inspection_time_ += elapsed; enumeration_total_time_ += elapsed; - // With a non-zero delay, bounce back over to ScanImplDelay, which will - // bounce back to this function and inspect the next module. + // If |per_module_delay_| is non-zero, post a task to scan the next module + // when the delay expires. if (!per_module_delay_.is_zero()) { - BrowserThread::GetBlockingPool()->PostDelayedWorkerTask( - FROM_HERE, - base::Bind(&ModuleEnumerator::ScanImplDelay, - base::Unretained(this), - index + 1), + background_task_runner_->PostDelayedTask( + FROM_HERE, base::Bind(&ModuleEnumerator::ScanImplModule, + base::Unretained(this), index + 1), per_module_delay_); return; } @@ -613,9 +601,9 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); // |module_enumerator_| is used as a lock to know whether or not there are - // active/pending blocking pool tasks. If a module enumerator exists then a - // scan is already underway. Otherwise, either no scan has been completed or - // a scan has terminated. + // active/pending background tasks. If a module enumerator exists then a scan + // is already underway. Otherwise, either no scan has been completed or a scan + // has terminated. if (module_enumerator_) { // If a scan is in progress and this request is for immediate results, then // inform the background scan. This is done without any locks because the @@ -628,7 +616,7 @@ // Only allow a single scan per process lifetime. Immediately notify any // observers that the scan is complete. At this point |enumerated_modules_| is - // safe to access as no potentially racing blocking pool task can exist. + // safe to access as no potentially racing background task can exist. if (!enumerated_modules_.empty()) { for (Observer& observer : observers_) observer.OnScanCompleted();
diff --git a/chrome/browser/win/enumerate_modules_model.h b/chrome/browser/win/enumerate_modules_model.h index 76ce022..7eb192f 100644 --- a/chrome/browser/win/enumerate_modules_model.h +++ b/chrome/browser/win/enumerate_modules_model.h
@@ -141,18 +141,11 @@ private: FRIEND_TEST_ALL_PREFIXES(EnumerateModulesTest, CollapsePath); - // This function enumerates all modules in the blocking pool. Once the list of - // module filenames is populated it posts a delayed task to call - // ScanImplDelay for the first module. + // This function posts a task to enumerate all modules asynchronously. Once + // the list of module filenames is populated, a delayed task is posted to scan + // the first module. void ScanImplStart(); - // Immediately posts a CONTINUE_ON_SHUTDOWN task to ScanImplModule for the - // given module. This ping-ponging is because the blocking pool does not - // offer a delayed CONTINUE_ON_SHUTDOWN task. - // TODO(chrisha): When the new scheduler enables delayed CONTINUE_ON_SHUTDOWN - // tasks, simplify this logic. - void ScanImplDelay(size_t index); - // Inspects the module in |enumerated_modules_| at the given |index|. Gets // module information, normalizes it, and collapses the path. This is an // expensive operation and non-critical. Posts a delayed task to ScanImplDelay @@ -210,6 +203,9 @@ // The typedef for the vector that maps a regular file path to %env_var%. typedef std::vector<std::pair<base::string16, base::string16>> PathMapping; + // The TaskRunner to perform work in the background. + const scoped_refptr<base::TaskRunner> background_task_runner_; + // The vector of paths to %env_var%, used to account for differences in // where people keep there files, c:\windows vs. d:\windows, etc. PathMapping path_mapping_; @@ -248,7 +244,7 @@ // ready. // // The member functions of this class may only be used from the UI thread. The -// bulk of the work is actually performed in the blocking pool with +// bulk of the work is actually performed asynchronously in TaskScheduler with // CONTINUE_ON_SHUTDOWN semantics, as the WinCrypt functions can effectively // block arbitrarily during shutdown. // @@ -341,13 +337,12 @@ void DoneScanning(); // The vector containing all the modules enumerated. Will be normalized and - // any bad modules will be marked. Written to from the blocking pool by the - // |module_enumerator_|, read from on the UI thread by this class. + // any bad modules will be marked. Written to from the background TaskRunner + // by the |module_enumerator_|, read from on the UI thread by this class. ModuleEnumerator::ModulesVector enumerated_modules_; - // The object responsible for enumerating the modules in the blocking pool. - // Only used from the UI thread. This ends up internally doing its work in the - // blocking pool. + // The object responsible for enumerating the modules on a background + // TaskRunner. Only accessed from the UI thread. std::unique_ptr<ModuleEnumerator> module_enumerator_; // Whether the conflict notification has been acknowledged by the user. Only
diff --git a/chrome/browser/win/enumerate_modules_model_unittest.cc b/chrome/browser/win/enumerate_modules_model_unittest.cc index 3b1f3b4..1649ada 100644 --- a/chrome/browser/win/enumerate_modules_model_unittest.cc +++ b/chrome/browser/win/enumerate_modules_model_unittest.cc
@@ -10,6 +10,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_task_scheduler.h" #include "testing/gtest/include/gtest/gtest.h" typedef testing::Test EnumerateModulesTest; @@ -103,6 +104,7 @@ }; TEST_F(EnumerateModulesTest, CollapsePath) { + base::test::ScopedTaskScheduler scoped_task_scheduler; ModuleEnumerator module_enumerator(nullptr); module_enumerator.path_mapping_.clear(); module_enumerator.path_mapping_.push_back(
diff --git a/chrome/common/chrome_paths.cc b/chrome/common/chrome_paths.cc index 122dd54..d33af32 100644 --- a/chrome/common/chrome_paths.cc +++ b/chrome/common/chrome_paths.cc
@@ -241,6 +241,13 @@ return false; cur = cur.Append(FILE_PATH_LITERAL("Diagnostics")); break; + case chrome::DIR_ROAMING_USER_DATA: + if (!GetDefaultRoamingUserDataDirectory(&cur)) { + NOTREACHED(); + return false; + } + create_dir = true; + break; #endif case chrome::DIR_RESOURCES: #if defined(OS_MACOSX)
diff --git a/chrome/common/chrome_paths.h b/chrome/common/chrome_paths.h index dd8c0b5b..0924105 100644 --- a/chrome/common/chrome_paths.h +++ b/chrome/common/chrome_paths.h
@@ -26,6 +26,8 @@ #if defined(OS_WIN) DIR_WATCHER_DATA, // Directory where the Chrome watcher stores // data. + DIR_ROAMING_USER_DATA, // Directory where user data is stored that + // needs to be roamed between computers. #endif DIR_RESOURCES, // Directory containing separate file resources // used by Chrome at runtime.
diff --git a/chrome/common/chrome_paths_internal.h b/chrome/common/chrome_paths_internal.h index 4b9322a5..ab812935 100644 --- a/chrome/common/chrome_paths_internal.h +++ b/chrome/common/chrome_paths_internal.h
@@ -27,6 +27,12 @@ // DIR_USER_DATA has been overridden by a command-line option. bool GetDefaultUserDataDirectory(base::FilePath* result); +#if defined(OS_WIN) +// Get the path to the roaming user's data directory, regardless of whether +// DIR_ROAMING_USER_DATA has been overridden by a command-line option. +bool GetDefaultRoamingUserDataDirectory(base::FilePath* result); +#endif + // Get the path to the user's cache directory. This is normally the // same as the profile directory, but on Linux it can also be // $XDG_CACHE_HOME and on Mac it can be under ~/Library/Caches.
diff --git a/chrome/common/chrome_paths_win.cc b/chrome/common/chrome_paths_win.cc index 597448b..767f967 100644 --- a/chrome/common/chrome_paths_win.cc +++ b/chrome/common/chrome_paths_win.cc
@@ -51,6 +51,15 @@ return true; } +bool GetDefaultRoamingUserDataDirectory(base::FilePath* result) { + if (!PathService::Get(base::DIR_APP_DATA, result)) + return false; + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); + *result = result->Append(dist->GetInstallSubDir()); + *result = result->Append(chrome::kUserDataDirname); + return true; +} + void GetUserCacheDirectory(const base::FilePath& profile_dir, base::FilePath* result) { // This function does more complicated things on Mac/Linux.
diff --git a/chrome/common/crash_keys.cc b/chrome/common/crash_keys.cc index fe3830b..313ccc9 100644 --- a/chrome/common/crash_keys.cc +++ b/chrome/common/crash_keys.cc
@@ -101,7 +101,10 @@ // but ultimately constitute a single key-value pair. // // If you're adding keys here, please also add them to the following list: - // chrome/app/chrome_crash_reporter_client_win.cc::RegisterCrashKeysHelper(). + // chrome/app/chrome_crash_reporter_client_win.cc::RegisterCrashKeysHelper(), + // and consider adding the new keys to the following list as well: + // android_webview/common/crash_reporter/crash_keys.cc:: + // RegisterWebViewCrashKeys(). base::debug::CrashKey fixed_keys[] = { #if defined(OS_MACOSX) || defined(OS_WIN) { kMetricsClientId, kSmallSize },
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 666c385..254cdb9 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -31,9 +31,6 @@ // utility methods (IsArcPlayStoreEnabledForProfile() and // SetArcPlayStoreEnabledForProfile()) in chrome/browser/chromeos/arc/arc_util. const char kArcEnabled[] = "arc.enabled"; -// A preference that indicated whether Android reported that it's compliant -// with provided policies. When it's compliant, Android kiosk app will start. -const char kArcPolicyCompliant[] = "arc.policy_compliant"; // A preference that indicates that user accepted PlayStore terms. const char kArcTermsAccepted[] = "arc.terms.accepted"; // A preference to keep user's consent to use location service.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 95181d91..03a07aa 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -23,7 +23,6 @@ extern const char kArcBackupRestoreEnabled[]; extern const char kArcDataRemoveRequested[]; extern const char kArcEnabled[]; -extern const char kArcPolicyCompliant[]; extern const char kArcTermsAccepted[]; extern const char kArcLocationServiceEnabled[]; extern const char kArcPackages[];
diff --git a/chromecast/browser/metrics/cast_metrics_service_client.cc b/chromecast/browser/metrics/cast_metrics_service_client.cc index a8a4fa8..0d61688 100644 --- a/chromecast/browser/metrics/cast_metrics_service_client.cc +++ b/chromecast/browser/metrics/cast_metrics_service_client.cc
@@ -24,6 +24,7 @@ #include "components/metrics/client_info.h" #include "components/metrics/enabled_state_provider.h" #include "components/metrics/gpu/gpu_metrics_provider.h" +#include "components/metrics/metrics_log_uploader.h" #include "components/metrics/metrics_provider.h" #include "components/metrics/metrics_service.h" #include "components/metrics/metrics_state_manager.h" @@ -244,10 +245,12 @@ CastMetricsServiceClient::CreateUploader( const std::string& server_url, const std::string& mime_type, + ::metrics::MetricsLogUploader::MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete) { return std::unique_ptr<::metrics::MetricsLogUploader>( new ::metrics::NetMetricsLogUploader(request_context_, server_url, - mime_type, on_upload_complete)); + mime_type, service_type, + on_upload_complete)); } base::TimeDelta CastMetricsServiceClient::GetStandardUploadInterval() {
diff --git a/chromecast/browser/metrics/cast_metrics_service_client.h b/chromecast/browser/metrics/cast_metrics_service_client.h index 64d2ad6..a45cee9c 100644 --- a/chromecast/browser/metrics/cast_metrics_service_client.h +++ b/chromecast/browser/metrics/cast_metrics_service_client.h
@@ -14,6 +14,7 @@ #include "base/memory/ref_counted.h" #include "build/build_config.h" #include "components/metrics/enabled_state_provider.h" +#include "components/metrics/metrics_log_uploader.h" #include "components/metrics/metrics_service_client.h" class PrefRegistrySimple; @@ -81,6 +82,7 @@ std::unique_ptr<::metrics::MetricsLogUploader> CreateUploader( const std::string& server_url, const std::string& mime_type, + ::metrics::MetricsLogUploader::MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete) override; base::TimeDelta GetStandardUploadInterval() override;
diff --git a/components/arc/common/policy.mojom b/components/arc/common/policy.mojom index 94122bb..742d0e71 100644 --- a/components/arc/common/policy.mojom +++ b/components/arc/common/policy.mojom
@@ -15,6 +15,7 @@ // Pass a JSON with policy compliance details that reference fields in // CloudDps NonComplianceReason. Should return ChromeOS response to the report // in JSON format as in CloudDps PolicyComplianceReportResponse. + // ChromeOS always returns that it's compliant with the report. [MinVersion=1] ReportCompliance@1(string request) => (string response); };
diff --git a/components/crash/content/app/breakpad_linux.cc b/components/crash/content/app/breakpad_linux.cc index 12c55b81..3c31d761 100644 --- a/components/crash/content/app/breakpad_linux.cc +++ b/components/crash/content/app/breakpad_linux.cc
@@ -110,14 +110,7 @@ class MicrodumpInfo { public: - MicrodumpInfo() - : microdump_build_fingerprint_(nullptr), - microdump_product_info_(nullptr), - microdump_gpu_fingerprint_(nullptr), - microdump_process_type_(nullptr), - skip_dump_if_principal_mapping_not_referenced_(false), - address_within_principal_mapping_(0ul), - should_sanitize_dumps_(false) {} + MicrodumpInfo() : microdump_gpu_fingerprint_(nullptr) {} // The order in which SetGpuFingerprint and Initialize are called // may be dependent on the timing of the availability of GPU @@ -132,28 +125,21 @@ // SetGpuFingerprint has not been called called at the point at // which a microdump is generated, then the GPU fingerprint will be // UNKNOWN. - void SetGpuFingerprint(const std::string& gpu_fingerprint); - void SetSkipDumpIfPrincipalMappingNotReferenced( - uintptr_t address_within_principal_mapping); - void SetShouldSanitizeDumps(bool should_sanitize_dumps); - void UpdateMinidumpDescriptor(MinidumpDescriptor* minidump_descriptor); - void UpdateExceptionHandlers(); + void SetGpuFingerprintForMicrodump(const std::string& gpu_fingerprint); void Initialize(const std::string& process_type, const char* product_name, const char* product_version, - const char* android_build_fp); + const char* android_build_fp, + const SanitizationInfo& sanitization_info); private: base::ThreadChecker thread_checker_; - const char* microdump_build_fingerprint_; - const char* microdump_product_info_; const char* microdump_gpu_fingerprint_; - const char* microdump_process_type_; - bool skip_dump_if_principal_mapping_not_referenced_; - uintptr_t address_within_principal_mapping_; - bool should_sanitize_dumps_; }; +void SetMinidumpSanitizationFields(MinidumpDescriptor* minidump_descriptor, + const SanitizationInfo& sanitization_info); + base::LazyInstance<MicrodumpInfo> g_microdump_info = LAZY_INSTANCE_INITIALIZER; @@ -780,7 +766,12 @@ } #endif +#if defined(OS_ANDROID) +void EnableCrashDumping(bool unattended, + const SanitizationInfo& sanitization_info) { +#else void EnableCrashDumping(bool unattended) { +#endif // defined(OS_ANDROID) g_is_crash_reporter_enabled = true; base::FilePath tmp_path("/tmp"); @@ -805,7 +796,7 @@ } #if defined(OS_ANDROID) unattended = true; // Android never uploads directly. - g_microdump_info.Get().UpdateMinidumpDescriptor(&minidump_descriptor); + SetMinidumpSanitizationFields(&minidump_descriptor, sanitization_info); #endif if (unattended) { g_breakpad = new ExceptionHandler( @@ -883,7 +874,8 @@ } void EnableNonBrowserCrashDumping(const std::string& process_type, - int minidump_fd) { + int minidump_fd, + const SanitizationInfo& sanitization_info) { // This will guarantee that the BuildInfo has been initialized and subsequent // calls will not require memory allocation. base::android::BuildInfo::GetInstance(); @@ -912,71 +904,42 @@ strncpy(g_process_type, process_type.c_str(), process_type_len); MinidumpDescriptor descriptor(minidump_fd); - g_microdump_info.Get().UpdateMinidumpDescriptor(&descriptor); + SetMinidumpSanitizationFields(&descriptor, sanitization_info); g_breakpad = new ExceptionHandler(descriptor, ShouldGenerateDump, CrashDoneInProcessNoUpload, nullptr, true, -1); } -void MicrodumpInfo::SetGpuFingerprint(const std::string& gpu_fingerprint) { +void MicrodumpInfo::SetGpuFingerprintForMicrodump( + const std::string& gpu_fingerprint) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!microdump_gpu_fingerprint_); microdump_gpu_fingerprint_ = strdup(gpu_fingerprint.c_str()); ANNOTATE_LEAKING_OBJECT_PTR(microdump_gpu_fingerprint_); - UpdateExceptionHandlers(); -} - -void MicrodumpInfo::SetSkipDumpIfPrincipalMappingNotReferenced( - uintptr_t address_within_principal_mapping) { - DCHECK(thread_checker_.CalledOnValidThread()); - skip_dump_if_principal_mapping_not_referenced_ = true; - address_within_principal_mapping_ = address_within_principal_mapping; - - UpdateExceptionHandlers(); -} - -void MicrodumpInfo::SetShouldSanitizeDumps(bool should_sanitize_dumps) { - DCHECK(thread_checker_.CalledOnValidThread()); - should_sanitize_dumps_ = should_sanitize_dumps; - - UpdateExceptionHandlers(); -} - -void MicrodumpInfo::UpdateMinidumpDescriptor( - MinidumpDescriptor* minidump_descriptor) { - google_breakpad::MicrodumpExtraInfo* microdump_extra_info = - minidump_descriptor->microdump_extra_info(); - - minidump_descriptor->set_skip_dump_if_principal_mapping_not_referenced( - skip_dump_if_principal_mapping_not_referenced_); - minidump_descriptor->set_address_within_principal_mapping( - address_within_principal_mapping_); - minidump_descriptor->set_sanitize_stacks(should_sanitize_dumps_); - - microdump_extra_info->gpu_fingerprint = microdump_gpu_fingerprint_; - microdump_extra_info->product_info = microdump_product_info_; - microdump_extra_info->process_type = microdump_process_type_; - microdump_extra_info->build_fingerprint = microdump_build_fingerprint_; -} - -void MicrodumpInfo::UpdateExceptionHandlers() { - if (g_breakpad) { - MinidumpDescriptor descriptor(g_breakpad->minidump_descriptor()); - UpdateMinidumpDescriptor(&descriptor); - g_breakpad->set_minidump_descriptor(descriptor); - } if (g_microdump) { MinidumpDescriptor descriptor(g_microdump->minidump_descriptor()); - UpdateMinidumpDescriptor(&descriptor); + descriptor.microdump_extra_info()->gpu_fingerprint = + microdump_gpu_fingerprint_; g_microdump->set_minidump_descriptor(descriptor); } } +void SetMinidumpSanitizationFields(MinidumpDescriptor* minidump_descriptor, + const SanitizationInfo& sanitization_info) { + minidump_descriptor->set_skip_dump_if_principal_mapping_not_referenced( + sanitization_info.skip_dump_if_principal_mapping_not_referenced); + minidump_descriptor->set_address_within_principal_mapping( + sanitization_info.address_within_principal_mapping); + minidump_descriptor->set_sanitize_stacks( + sanitization_info.should_sanitize_dumps); +} + void MicrodumpInfo::Initialize(const std::string& process_type, const char* product_name, const char* product_version, - const char* android_build_fp) { + const char* android_build_fp, + const SanitizationInfo& sanitization_info) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!g_microdump); // |process_type| for webview's browser process is kBrowserProcessType or @@ -987,23 +950,26 @@ process_type == kBrowserProcessType; MinidumpDescriptor descriptor(MinidumpDescriptor::kMicrodumpOnConsole); + google_breakpad::MicrodumpExtraInfo* microdump_extra_info = + descriptor.microdump_extra_info(); if (product_name && product_version) { - microdump_product_info_ = + microdump_extra_info->product_info = strdup((product_name + std::string(":") + product_version).c_str()); - ANNOTATE_LEAKING_OBJECT_PTR(microdump_product_info_); + ANNOTATE_LEAKING_OBJECT_PTR(microdump_extra_info->product_info); } - microdump_process_type_ = + microdump_extra_info->process_type = strdup(process_type.empty() ? kBrowserProcessType : process_type.c_str()); - ANNOTATE_LEAKING_OBJECT_PTR(microdump_process_type_); + ANNOTATE_LEAKING_OBJECT_PTR(microdump_extra_info->process_type); if (android_build_fp) { - microdump_build_fingerprint_ = strdup(android_build_fp); - ANNOTATE_LEAKING_OBJECT_PTR(microdump_build_fingerprint_); + microdump_extra_info->build_fingerprint = strdup(android_build_fp); + ANNOTATE_LEAKING_OBJECT_PTR(microdump_extra_info->build_fingerprint); } - UpdateMinidumpDescriptor(&descriptor); + SetMinidumpSanitizationFields(&descriptor, sanitization_info); + microdump_extra_info->gpu_fingerprint = microdump_gpu_fingerprint_; g_microdump = new ExceptionHandler(descriptor, ShouldGenerateDump, MicrodumpCrashDone, @@ -1930,7 +1896,20 @@ (void) HANDLE_EINTR(sys_waitpid(child, nullptr, 0)); } +#if defined(OS_ANDROID) +// In Android WebView, microdumps are generated conditionally (depending on the +// cause of the crash) and can be sanitized to prevent exposing unnecessary data +// from the embedding application. void InitCrashReporter(const std::string& process_type) { + SanitizationInfo sanitization_info; + InitCrashReporter(process_type, sanitization_info); +} + +void InitCrashReporter(const std::string& process_type, + const SanitizationInfo& sanitization_info) { +#else +void InitCrashReporter(const std::string& process_type) { +#endif // defined(OS_ANDROID) // The maximum lengths specified by breakpad include the trailing NULL, so the // actual length of the chunk is one less. static_assert(crash_keys::kChunkMaxLength == 63, "kChunkMaxLength mismatch"); @@ -1944,7 +1923,7 @@ // Handler registration is LIFO. Install the microdump handler first, such // that if conventional minidump crash reporting is enabled below, it takes // precedence (i.e. its handler is run first) over the microdump handler. - InitMicrodumpCrashHandlerIfNecessary(process_type); + InitMicrodumpCrashHandlerIfNecessary(process_type, sanitization_info); #endif // Determine the process type and take appropriate action. const base::CommandLine& parsed_command_line = @@ -1967,7 +1946,12 @@ } InitCrashKeys(); +#if defined(OS_ANDROID) + EnableCrashDumping(GetCrashReporterClient()->IsRunningUnattended(), + sanitization_info); +#else EnableCrashDumping(GetCrashReporterClient()->IsRunningUnattended()); +#endif // defined(OS_ANDROID) } else if (GetCrashReporterClient()->EnableBreakpadForProcess(process_type)) { #if defined(OS_ANDROID) NOTREACHED() << "Breakpad initialized with InitCrashReporter() instead of " @@ -1995,13 +1979,22 @@ #if defined(OS_ANDROID) void InitNonBrowserCrashReporterForAndroid(const std::string& process_type) { + SanitizationInfo sanitization_info; + sanitization_info.should_sanitize_dumps = false; + sanitization_info.skip_dump_if_principal_mapping_not_referenced = false; + InitNonBrowserCrashReporterForAndroid(process_type, sanitization_info); +} + +void InitNonBrowserCrashReporterForAndroid( + const std::string& process_type, + const SanitizationInfo& sanitization_info) { const base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); // Handler registration is LIFO. Install the microdump handler first, such // that if conventional minidump crash reporting is enabled below, it takes // precedence (i.e. its handler is run first) over the microdump handler. - InitMicrodumpCrashHandlerIfNecessary(process_type); + InitMicrodumpCrashHandlerIfNecessary(process_type, sanitization_info); if (command_line->HasSwitch(switches::kEnableCrashReporter)) { // On Android we need to provide a FD to the file where the minidump is @@ -2013,7 +2006,8 @@ NOTREACHED() << "Could not find minidump FD, crash reporting disabled."; } else { InitCrashKeys(); - EnableNonBrowserCrashDumping(process_type, minidump_fd); + EnableNonBrowserCrashDumping(process_type, minidump_fd, + sanitization_info); // Note: not installing DumpWithoutCrash handler here because browser // is not set up to receive multiple reports from child process. } @@ -2023,7 +2017,9 @@ // The microdump handler does NOT upload anything. It just dumps out on the // system console (logcat) a restricted and serialized variant of a minidump. // See crbug.com/410294 for more details. -void InitMicrodumpCrashHandlerIfNecessary(const std::string& process_type) { +void InitMicrodumpCrashHandlerIfNecessary( + const std::string& process_type, + const SanitizationInfo& sanitization_info) { if (!GetCrashReporterClient()->ShouldEnableBreakpadMicrodumps()) return; @@ -2042,12 +2038,12 @@ base::android::BuildInfo::GetInstance()->android_build_fp(); g_microdump_info.Get().Initialize(process_type, product_name, product_version, - android_build_fp); + android_build_fp, sanitization_info); } void AddGpuFingerprintToMicrodumpCrashHandler( const std::string& gpu_fingerprint) { - g_microdump_info.Get().SetGpuFingerprint(gpu_fingerprint); + g_microdump_info.Get().SetGpuFingerprintForMicrodump(gpu_fingerprint); } void GenerateMinidumpOnDemandForAndroid(int dump_fd) { @@ -2063,16 +2059,6 @@ void SuppressDumpGeneration() { g_dumps_suppressed = G_DUMPS_SUPPRESSED_MAGIC; } - -void SetSkipDumpIfPrincipalMappingNotReferenced( - uintptr_t address_within_principal_mapping) { - g_microdump_info.Get().SetSkipDumpIfPrincipalMappingNotReferenced( - address_within_principal_mapping); -} - -void SetShouldSanitizeDumps(bool should_sanitize_dumps) { - g_microdump_info.Get().SetShouldSanitizeDumps(should_sanitize_dumps); -} #endif // OS_ANDROID bool IsCrashReporterEnabled() {
diff --git a/components/crash/content/app/breakpad_linux.h b/components/crash/content/app/breakpad_linux.h index 2cd1795..3ef4e8a9 100644 --- a/components/crash/content/app/breakpad_linux.h +++ b/components/crash/content/app/breakpad_linux.h
@@ -17,6 +17,15 @@ extern void InitCrashReporter(const std::string& process_type); #if defined(OS_ANDROID) +struct SanitizationInfo { + bool should_sanitize_dumps = false; + bool skip_dump_if_principal_mapping_not_referenced = false; + uintptr_t address_within_principal_mapping = 0; +}; + +// Turns on the crash reporter in any process. +extern void InitCrashReporter(const std::string& process_type, + const SanitizationInfo& sanitization_info); const char kWebViewSingleProcessType[] = "webview"; const char kBrowserProcessType[] = "browser"; @@ -24,10 +33,15 @@ // Enables the crash reporter in child processes. extern void InitNonBrowserCrashReporterForAndroid( const std::string& process_type); +// Enables the crash reporter in child processes. +extern void InitNonBrowserCrashReporterForAndroid( + const std::string& process_type, + const SanitizationInfo& sanitization_info); // Enables *micro*dump only. Can be called from any process. extern void InitMicrodumpCrashHandlerIfNecessary( - const std::string& process_type); + const std::string& process_type, + const SanitizationInfo& sanitization_info); extern void AddGpuFingerprintToMicrodumpCrashHandler( const std::string& gpu_fingerprint); @@ -36,23 +50,7 @@ // generate dumps. Calling base::debug::DumpWithoutCrashing will still // generate a dump. extern void SuppressDumpGeneration(); - -// Calling SetShouldSanitizeDumps determines whether or not subsequent -// crash dumps should be sanitized. Sanitized dumps still contain -// enough stack information to unwind crashes, but other stack data is -// erased. -extern void SetShouldSanitizeDumps(bool sanitize_dumps); - -// Inform breakpad of an address within the text section that is -// considered interesting for the purpose of crashes so that this can -// be used to elide microdumps that do not reference interesting -// code. Minidumps will still be generated, but stacks from threads -// that do not reference the principal mapping will not be included. -// The full interesting address range is determined by looking up the -// memory mapping that contains |addr|. -extern void SetSkipDumpIfPrincipalMappingNotReferenced( - uintptr_t address_within_principal_mapping); -#endif +#endif // defined(OS_ANDROID) // Checks if crash reporting is enabled. Note that this is not the same as // being opted into metrics reporting (and crash reporting), which controls
diff --git a/components/data_use_measurement/core/data_use_user_data.cc b/components/data_use_measurement/core/data_use_user_data.cc index 4c452e9..de9cf6f 100644 --- a/components/data_use_measurement/core/data_use_user_data.cc +++ b/components/data_use_measurement/core/data_use_user_data.cc
@@ -124,6 +124,8 @@ return "NTPSnippetsThumbnails"; case DOODLE: return "Doodle"; + case UKM: + return "UKM"; } return "INVALID"; }
diff --git a/components/data_use_measurement/core/data_use_user_data.h b/components/data_use_measurement/core/data_use_user_data.h index b930c3f..4f8b4b9 100644 --- a/components/data_use_measurement/core/data_use_user_data.h +++ b/components/data_use_measurement/core/data_use_user_data.h
@@ -62,6 +62,7 @@ NTP_SNIPPETS_SUGGESTIONS, NTP_SNIPPETS_THUMBNAILS, DOODLE, + UKM, }; // Data use broken by content type. This enum must remain synchronized
diff --git a/components/metrics/metrics_log_uploader.cc b/components/metrics/metrics_log_uploader.cc index 41b83ed..0d67ced 100644 --- a/components/metrics/metrics_log_uploader.cc +++ b/components/metrics/metrics_log_uploader.cc
@@ -9,11 +9,12 @@ MetricsLogUploader::MetricsLogUploader( const std::string& server_url, const std::string& mime_type, + MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete) : server_url_(server_url), mime_type_(mime_type), - on_upload_complete_(on_upload_complete) { -} + service_type_(service_type), + on_upload_complete_(on_upload_complete) {} MetricsLogUploader::~MetricsLogUploader() { }
diff --git a/components/metrics/metrics_log_uploader.h b/components/metrics/metrics_log_uploader.h index 2ef0cf2..bcc4662 100644 --- a/components/metrics/metrics_log_uploader.h +++ b/components/metrics/metrics_log_uploader.h
@@ -16,11 +16,20 @@ // of MetricsService. class MetricsLogUploader { public: + // Possible service types. This should correspond to a type from + // DataUseUserData. + enum MetricServiceType { + UMA, + UKM, + }; + // Constructs the uploader that will upload logs to the specified |server_url| - // with the given |mime_type|. The |on_upload_complete| callback will be - // called with the HTTP response code of the upload or with -1 on an error. + // with the given |mime_type|. The |service_type| marks which service the + // data usage should be attributed to. The |on_upload_complete| callback will + // be called with the HTTP response code of the upload or with -1 on an error. MetricsLogUploader(const std::string& server_url, const std::string& mime_type, + MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete); virtual ~MetricsLogUploader(); @@ -33,6 +42,11 @@ protected: const std::string server_url_; const std::string mime_type_; + + // Which service type this uploads for. This is used for bandwidth + // attribution. + const MetricServiceType service_type_; + const base::Callback<void(int)> on_upload_complete_; private:
diff --git a/components/metrics/metrics_service.cc b/components/metrics/metrics_service.cc index c8b9e30b..91e7dd23 100644 --- a/components/metrics/metrics_service.cc +++ b/components/metrics/metrics_service.cc
@@ -1000,8 +1000,8 @@ if (!log_uploader_) { log_uploader_ = client_->CreateUploader( - client_->GetMetricsServerUrl(), - metrics::kDefaultMetricsMimeType, + client_->GetMetricsServerUrl(), metrics::kDefaultMetricsMimeType, + metrics::MetricsLogUploader::UMA, base::Bind(&MetricsService::OnLogUploadComplete, self_ptr_factory_.GetWeakPtr())); }
diff --git a/components/metrics/metrics_service_client.h b/components/metrics/metrics_service_client.h index 2ce2017..0c5f693 100644 --- a/components/metrics/metrics_service_client.h +++ b/components/metrics/metrics_service_client.h
@@ -13,6 +13,7 @@ #include "base/callback.h" #include "base/strings/string16.h" #include "base/time/time.h" +#include "components/metrics/metrics_log_uploader.h" #include "components/metrics/metrics_reporting_default_state.h" #include "components/metrics/proto/system_profile.pb.h" @@ -95,6 +96,7 @@ virtual std::unique_ptr<MetricsLogUploader> CreateUploader( const std::string& server_url, const std::string& mime_type, + metrics::MetricsLogUploader::MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete) = 0; // Returns the standard interval between upload attempts.
diff --git a/components/metrics/net/net_metrics_log_uploader.cc b/components/metrics/net/net_metrics_log_uploader.cc index 5b2c95e..0064177 100644 --- a/components/metrics/net/net_metrics_log_uploader.cc +++ b/components/metrics/net/net_metrics_log_uploader.cc
@@ -6,6 +6,7 @@ #include "base/metrics/histogram_macros.h" #include "components/data_use_measurement/core/data_use_user_data.h" +#include "components/metrics/metrics_log_uploader.h" #include "net/base/load_flags.h" #include "net/url_request/url_fetcher.h" #include "url/gurl.h" @@ -16,10 +17,13 @@ net::URLRequestContextGetter* request_context_getter, const std::string& server_url, const std::string& mime_type, + MetricsLogUploader::MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete) - : MetricsLogUploader(server_url, mime_type, on_upload_complete), - request_context_getter_(request_context_getter) { -} + : MetricsLogUploader(server_url, + mime_type, + service_type, + on_upload_complete), + request_context_getter_(request_context_getter) {} NetMetricsLogUploader::~NetMetricsLogUploader() { } @@ -28,8 +32,19 @@ const std::string& log_hash) { current_fetch_ = net::URLFetcher::Create(GURL(server_url_), net::URLFetcher::POST, this); - data_use_measurement::DataUseUserData::AttachToFetcher( - current_fetch_.get(), data_use_measurement::DataUseUserData::UMA); + + auto service = data_use_measurement::DataUseUserData::UMA; + + switch (service_type_) { + case MetricsLogUploader::UMA: + service = data_use_measurement::DataUseUserData::UMA; + break; + case MetricsLogUploader::UKM: + service = data_use_measurement::DataUseUserData::UKM; + break; + } + data_use_measurement::DataUseUserData::AttachToFetcher(current_fetch_.get(), + service); current_fetch_->SetRequestContext(request_context_getter_); current_fetch_->SetUploadData(mime_type_, compressed_log_data);
diff --git a/components/metrics/net/net_metrics_log_uploader.h b/components/metrics/net/net_metrics_log_uploader.h index ab44bdbc..b81d166 100644 --- a/components/metrics/net/net_metrics_log_uploader.h +++ b/components/metrics/net/net_metrics_log_uploader.h
@@ -30,6 +30,7 @@ NetMetricsLogUploader(net::URLRequestContextGetter* request_context_getter, const std::string& server_url, const std::string& mime_type, + MetricsLogUploader::MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete); ~NetMetricsLogUploader() override;
diff --git a/components/metrics/net/net_metrics_log_uploader_unittest.cc b/components/metrics/net/net_metrics_log_uploader_unittest.cc index 8a8704e..14258f7 100644 --- a/components/metrics/net/net_metrics_log_uploader_unittest.cc +++ b/components/metrics/net/net_metrics_log_uploader_unittest.cc
@@ -18,7 +18,7 @@ void CreateAndOnUploadCompleteReuseUploader() { uploader_.reset(new NetMetricsLogUploader( - NULL, "http://dummy_server", "dummy_mime", + NULL, "http://dummy_server", "dummy_mime", MetricsLogUploader::UMA, base::Bind(&NetMetricsLogUploaderTest::OnUploadCompleteReuseUploader, base::Unretained(this)))); uploader_->UploadLog("initial_dummy_data", "initial_dummy_hash");
diff --git a/components/metrics/test_metrics_log_uploader.cc b/components/metrics/test_metrics_log_uploader.cc index f51b663..9c701cc 100644 --- a/components/metrics/test_metrics_log_uploader.cc +++ b/components/metrics/test_metrics_log_uploader.cc
@@ -3,14 +3,19 @@ // found in the LICENSE file. #include "components/metrics/test_metrics_log_uploader.h" +#include "components/metrics/metrics_log_uploader.h" namespace metrics { TestMetricsLogUploader::TestMetricsLogUploader( const std::string& server_url, const std::string& mime_type, + MetricsLogUploader::MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete) - : MetricsLogUploader(server_url, mime_type, on_upload_complete), + : MetricsLogUploader(server_url, + mime_type, + service_type, + on_upload_complete), is_uploading_(false) {} TestMetricsLogUploader::~TestMetricsLogUploader() = default;
diff --git a/components/metrics/test_metrics_log_uploader.h b/components/metrics/test_metrics_log_uploader.h index d2b4bdb..196370a 100644 --- a/components/metrics/test_metrics_log_uploader.h +++ b/components/metrics/test_metrics_log_uploader.h
@@ -13,6 +13,7 @@ public: TestMetricsLogUploader(const std::string& server_url, const std::string& mime_type, + MetricsLogUploader::MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete); ~TestMetricsLogUploader() override;
diff --git a/components/metrics/test_metrics_service_client.cc b/components/metrics/test_metrics_service_client.cc index 60defbc..b68bef8 100644 --- a/components/metrics/test_metrics_service_client.cc +++ b/components/metrics/test_metrics_service_client.cc
@@ -67,9 +67,10 @@ std::unique_ptr<MetricsLogUploader> TestMetricsServiceClient::CreateUploader( const std::string& server_url, const std::string& mime_type, + MetricsLogUploader::MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete) { - uploader_ = - new TestMetricsLogUploader(server_url, mime_type, on_upload_complete); + uploader_ = new TestMetricsLogUploader(server_url, mime_type, service_type, + on_upload_complete); return std::unique_ptr<MetricsLogUploader>(uploader_); }
diff --git a/components/metrics/test_metrics_service_client.h b/components/metrics/test_metrics_service_client.h index b8ddc6a..8d77e52a 100644 --- a/components/metrics/test_metrics_service_client.h +++ b/components/metrics/test_metrics_service_client.h
@@ -10,6 +10,7 @@ #include <string> #include "base/macros.h" +#include "components/metrics/metrics_log_uploader.h" #include "components/metrics/metrics_service_client.h" #include "components/metrics/test_metrics_log_uploader.h" @@ -38,6 +39,7 @@ std::unique_ptr<MetricsLogUploader> CreateUploader( const std::string& server_url, const std::string& mime_type, + MetricsLogUploader::MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete) override; base::TimeDelta GetStandardUploadInterval() override; bool IsReportingPolicyManaged() override;
diff --git a/components/ntp_snippets/features.cc b/components/ntp_snippets/features.cc index 85b325f5f..49c2097 100644 --- a/components/ntp_snippets/features.cc +++ b/components/ntp_snippets/features.cc
@@ -32,7 +32,7 @@ "NTPSnippetsIncreasedVisibility", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kPhysicalWebPageSuggestionsFeature{ - "NTPPhysicalWebPageSuggestions", base::FEATURE_ENABLED_BY_DEFAULT}; + "NTPPhysicalWebPageSuggestions", base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kContentSuggestionsSource{ "NTPSnippets", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/components/omnibox/browser/in_memory_url_index_unittest.cc b/components/omnibox/browser/in_memory_url_index_unittest.cc index 54119ee..57751d8 100644 --- a/components/omnibox/browser/in_memory_url_index_unittest.cc +++ b/components/omnibox/browser/in_memory_url_index_unittest.cc
@@ -710,6 +710,108 @@ EXPECT_EQ(1U, matches.size()); } +TEST_F(InMemoryURLIndexTest, TrimHistoryIds) { + // Constants --------------------------------------------------------------- + + constexpr size_t kItemsToScoreLimit = 500; + constexpr size_t kAlmostLimit = kItemsToScoreLimit - 5; + + constexpr int kLowTypedCount = 2; + constexpr int kHighTypedCount = 100; + + constexpr int kLowVisitCount = 20; + constexpr int kHighVisitCount = 200; + + constexpr base::TimeDelta kOld = base::TimeDelta::FromDays(15); + constexpr base::TimeDelta kNew = base::TimeDelta::FromDays(2); + + constexpr int kMinRowId = 5000; + + // Helpers ----------------------------------------------------------------- + + struct ItemGroup { + history::URLID min_id; + history::URLID max_id; + int typed_count; + int visit_count; + base::TimeDelta days_ago; + }; + + auto GetHistoryIdsUpTo = [&](HistoryID max) { + HistoryIDSet res; + // All ids are inserted in the end so the implicit hint would work. + for (HistoryID id = kMinRowId; id < max; ++id) + res.insert(id); + return res; + }; + + auto CountGroupElementsInIds = [](const ItemGroup& group, + const HistoryIDSet& ids) { + return std::count_if(ids.begin(), ids.end(), [&](history::URLID id) { + return group.min_id <= id && id < group.max_id; + }); + }; + + // Test body -------------------------------------------------------------- + + // Groups of items ordered by increasing priority. + ItemGroup item_groups[] = { + {0, 0, kLowTypedCount, kLowVisitCount, kOld}, + {0, 0, kLowTypedCount, kLowVisitCount, kNew}, + {0, 0, kLowTypedCount, kHighVisitCount, kOld}, + {0, 0, kLowTypedCount, kHighVisitCount, kNew}, + {0, 0, kHighTypedCount, kLowVisitCount, kOld}, + {0, 0, kHighTypedCount, kLowVisitCount, kNew}, + {0, 0, kHighTypedCount, kHighVisitCount, kOld}, + {0, 0, kHighTypedCount, kHighVisitCount, kNew}, + }; + + // Initialize groups. + history::URLID row_id = kMinRowId; + for (auto& group : item_groups) { + group.min_id = row_id; + for (size_t i = 0; i < kAlmostLimit; ++i) { + history::URLRow new_row( + GURL("http://www.fake_url" + std::to_string(row_id) + ".com"), + row_id); + new_row.set_typed_count(group.typed_count); + new_row.set_visit_count(group.visit_count); + new_row.set_last_visit(base::Time::Now() - group.days_ago); + UpdateURL(std::move(new_row)); + ++row_id; + } + group.max_id = row_id; + } + + // First group. Because number of entries is small enough no trimming occurs. + { + auto ids = GetHistoryIdsUpTo(item_groups[0].max_id); + EXPECT_FALSE(GetPrivateData()->TrimHistoryIdsPool(&ids)); + EXPECT_EQ(kAlmostLimit, ids.size()); + } + + // Each next group should fill almost everything, while the previous group + // should occupy what's left. + auto error_position = std::adjacent_find( + std::begin(item_groups), std::end(item_groups), + [&](const ItemGroup& previous, const ItemGroup& current) { + auto ids = GetHistoryIdsUpTo(current.max_id); + EXPECT_TRUE(GetPrivateData()->TrimHistoryIdsPool(&ids)); + + size_t current_count = CountGroupElementsInIds(current, ids); + EXPECT_EQ(kAlmostLimit, current_count); + if (current_count != kAlmostLimit) + return true; + + size_t previous_count = CountGroupElementsInIds(previous, ids); + EXPECT_EQ(kItemsToScoreLimit - kAlmostLimit, previous_count); + return previous_count != kItemsToScoreLimit - kAlmostLimit; + }); + + EXPECT_TRUE(error_position == std::end(item_groups)) + << "broken after: " << error_position - std::begin(item_groups); +} + TEST_F(InMemoryURLIndexTest, HugeResultSet) { // Create a huge set of qualifying history items. for (history::URLID row_id = 5000; row_id < 6000; ++row_id) { @@ -721,12 +823,7 @@ ScoredHistoryMatches matches = url_index_->HistoryItemsForTerms( ASCIIToUTF16("b"), base::string16::npos, kMaxMatches); - URLIndexPrivateData& private_data(*GetPrivateData()); EXPECT_EQ(kMaxMatches, matches.size()); - // There are 7 matches already in the database. - EXPECT_EQ(1008U, private_data.pre_filter_item_count_); - EXPECT_EQ(500U, private_data.post_filter_item_count_); - EXPECT_EQ(kMaxMatches, private_data.post_scoring_item_count_); } TEST_F(InMemoryURLIndexTest, TitleSearch) {
diff --git a/components/omnibox/browser/url_index_private_data.cc b/components/omnibox/browser/url_index_private_data.cc index 8088389..6556116 100644 --- a/components/omnibox/browser/url_index_private_data.cc +++ b/components/omnibox/browser/url_index_private_data.cc
@@ -141,11 +141,7 @@ URLIndexPrivateData::URLIndexPrivateData() : restored_cache_version_(0), - saved_cache_version_(kCurrentCacheFileVersion), - pre_filter_item_count_(0), - post_filter_item_count_(0), - post_scoring_item_count_(0) { -} + saved_cache_version_(kCurrentCacheFileVersion) {} ScoredHistoryMatches URLIndexPrivateData::HistoryItemsForTerms( base::string16 original_search_string, @@ -153,10 +149,6 @@ size_t max_matches, bookmarks::BookmarkModel* bookmark_model, TemplateURLService* template_url_service) { - pre_filter_item_count_ = 0; - post_filter_item_count_ = 0; - post_scoring_item_count_ = 0; - // This list will contain the original search string and any other string // transformations. String16Vector search_strings; @@ -182,6 +174,7 @@ // approach. ResetSearchTermCache(); + bool history_ids_were_trimmed = false; for (const base::string16& search_string : search_strings) { // The search string we receive may contain escaped characters. For reducing // the index we need individual, lower-cased words, ignoring escapings. For @@ -202,29 +195,8 @@ if (lower_words.empty()) continue; HistoryIDSet history_id_set = HistoryIDSetFromWords(lower_words); - pre_filter_item_count_ += history_id_set.size(); - // Trim the candidate pool if it is large. Note that we do not filter out - // items that do not contain the search terms as proper substrings -- - // doing so is the performance-costly operation we are trying to avoid in - // order to maintain omnibox responsiveness. - const size_t kItemsToScoreLimit = 500; - if (history_id_set.size() > kItemsToScoreLimit) { - HistoryIDVector history_ids; - std::copy(history_id_set.begin(), history_id_set.end(), - std::back_inserter(history_ids)); - // Trim down the set by sorting by typed-count, visit-count, and last - // visit. - HistoryItemFactorGreater item_factor_functor(history_info_map_); - std::partial_sort(history_ids.begin(), - history_ids.begin() + kItemsToScoreLimit, - history_ids.end(), item_factor_functor); - history_id_set.clear(); - std::copy(history_ids.begin(), history_ids.begin() + kItemsToScoreLimit, - std::inserter(history_id_set, history_id_set.end())); - post_filter_item_count_ += history_id_set.size(); - } else { - post_filter_item_count_ += pre_filter_item_count_; - } + history_ids_were_trimmed |= TrimHistoryIdsPool(&history_id_set); + ScoredHistoryMatches temp_scored_items; HistoryIdSetToScoredMatches(history_id_set, lower_raw_string, template_url_service, bookmark_model, @@ -242,8 +214,7 @@ std::sort(scored_items.begin(), scored_items.end(), ScoredHistoryMatch::MatchScoreGreater); } - post_scoring_item_count_ = scored_items.size(); - if (pre_filter_item_count_ > post_filter_item_count_) { + if (history_ids_were_trimmed) { // If we trim the results set we do not want to cache the results for next // time as the user's ultimately desired result could easily be eliminated // in the early rough filter. @@ -472,9 +443,6 @@ return data_copy; // Not copied: // search_term_cache_ - // pre_filter_item_count_ - // post_filter_item_count_ - // post_scoring_item_count_ } bool URLIndexPrivateData::Empty() const { @@ -528,6 +496,27 @@ return history_id_set; } +bool URLIndexPrivateData::TrimHistoryIdsPool( + HistoryIDSet* history_id_set) const { + constexpr size_t kItemsToScoreLimit = 500; + if (history_id_set->size() <= kItemsToScoreLimit) + return false; + + HistoryIDVector history_ids(history_id_set->begin(), history_id_set->end()); + + // Trim down the set by sorting by typed-count, visit-count, and last + // visit. + auto new_end = history_ids.begin() + kItemsToScoreLimit; + HistoryItemFactorGreater item_factor_functor(history_info_map_); + + std::nth_element(history_ids.begin(), new_end, history_ids.end(), + item_factor_functor); + history_ids.erase(new_end, history_ids.end()); + + *history_id_set = {history_ids.begin(), history_ids.end()}; + return true; +} + HistoryIDSet URLIndexPrivateData::HistoryIDsForTerm( const base::string16& term) { if (term.empty())
diff --git a/components/omnibox/browser/url_index_private_data.h b/components/omnibox/browser/url_index_private_data.h index 50bcf4b7..4eb77e5 100644 --- a/components/omnibox/browser/url_index_private_data.h +++ b/components/omnibox/browser/url_index_private_data.h
@@ -146,13 +146,14 @@ friend class ::HistoryQuickProviderTest; friend class InMemoryURLIndexTest; - FRIEND_TEST_ALL_PREFIXES(InMemoryURLIndexTest, CalculateWordStartsOffsets); FRIEND_TEST_ALL_PREFIXES(InMemoryURLIndexTest, CacheSaveRestore); + FRIEND_TEST_ALL_PREFIXES(InMemoryURLIndexTest, CalculateWordStartsOffsets); FRIEND_TEST_ALL_PREFIXES(InMemoryURLIndexTest, HugeResultSet); FRIEND_TEST_ALL_PREFIXES(InMemoryURLIndexTest, ReadVisitsFromHistory); FRIEND_TEST_ALL_PREFIXES(InMemoryURLIndexTest, RebuildFromHistoryIfCacheOld); FRIEND_TEST_ALL_PREFIXES(InMemoryURLIndexTest, Scoring); FRIEND_TEST_ALL_PREFIXES(InMemoryURLIndexTest, TitleSearch); + FRIEND_TEST_ALL_PREFIXES(InMemoryURLIndexTest, TrimHistoryIds); FRIEND_TEST_ALL_PREFIXES(InMemoryURLIndexTest, TypedCharacterCaching); FRIEND_TEST_ALL_PREFIXES(InMemoryURLIndexTest, WhitelistedURLs); FRIEND_TEST_ALL_PREFIXES(LimitedInMemoryURLIndexTest, Initialization); @@ -208,6 +209,14 @@ // in |unsorted_words|. HistoryIDSet HistoryIDSetFromWords(const String16Vector& unsorted_words); + // Trims the candidate pool in advance of doing proper substring searching, to + // cap the cost of such searching. Discards the least-relevant items (based on + // visit stats), which are least likely to score highly in the end. To + // minimize the risk of discarding a valuable URL, the candidate pool is still + // left two orders of magnitude larger than the final number of results + // returned from the HQP. Returns whether anything was trimmed. + bool TrimHistoryIdsPool(HistoryIDSet* history_id_set) const; + // Helper function to HistoryIDSetFromWords which composes a set of history // ids for the given term given in |term|. HistoryIDSet HistoryIDsForTerm(const base::string16& term); @@ -379,12 +388,6 @@ // Used only for testing upgrading of an older version of the cache upon // restore. int saved_cache_version_; - - // Used for unit testing only. Records the number of candidate history items - // at three stages in the index searching process. - size_t pre_filter_item_count_; // After word index is queried. - size_t post_filter_item_count_; // After trimming large result set. - size_t post_scoring_item_count_; // After performing final filter/scoring. }; #endif // COMPONENTS_OMNIBOX_BROWSER_URL_INDEX_PRIVATE_DATA_H_
diff --git a/components/printing/renderer/print_web_view_helper.cc b/components/printing/renderer/print_web_view_helper.cc index 173fb4381..e59e372e 100644 --- a/components/printing/renderer/print_web_view_helper.cc +++ b/components/printing/renderer/print_web_view_helper.cc
@@ -1854,9 +1854,15 @@ double css_scale_factor = 1.0f; #if BUILDFLAG(ENABLE_PRINT_PREVIEW) - if (params.params.scale_factor >= kEpsilon) - css_scale_factor = params.params.scale_factor; + if (params.params.scale_factor >= kEpsilon) + css_scale_factor = params.params.scale_factor; #endif + + // Save the original page size here to avoid rounding errors incurred by + // converting to pixels and back and by scaling the page for reflow and + // scaling back. Windows uses |page_size_in_dpi| for the actual page size + // so requires an accurate value. + gfx::Size original_page_size = params.params.page_size; ComputePageLayoutInPointsForCss(frame, params.page_number, params.params, ignore_css_margins_, &css_scale_factor, &page_layout_in_points); @@ -1864,19 +1870,10 @@ gfx::Rect content_area; GetPageSizeAndContentAreaFromPageLayout(page_layout_in_points, &page_size, &content_area); - int dpi = static_cast<int>(params.params.dpi); + // Calculate the actual page size and content area in dpi. if (page_size_in_dpi) { - // Windows uses this for the actual page size. We have scaled page size - // to get blink to reflow the page, so scale it back to the real size - // before returning it. - *page_size_in_dpi = - gfx::Size(static_cast<int>(ConvertUnitDouble(page_size.width(), - kPointsPerInch, dpi) * - css_scale_factor), - static_cast<int>(ConvertUnitDouble(page_size.height(), - kPointsPerInch, dpi) * - css_scale_factor)); + *page_size_in_dpi = original_page_size; } if (content_area_in_dpi) {
diff --git a/components/printing/test/mock_printer.cc b/components/printing/test/mock_printer.cc index 4197dc60..1a38b7a 100644 --- a/components/printing/test/mock_printer.cc +++ b/components/printing/test/mock_printer.cc
@@ -40,6 +40,13 @@ } } +void UpdatePageSizeAndScaling(const gfx::Size& page_size, + int scale_factor, + PrintMsg_Print_Params* params) { + params->page_size = page_size; + params->scale_factor = static_cast<double>(scale_factor) / 100.0; +} + } // namespace MockPrinterPage::MockPrinterPage(const void* source_data, @@ -161,7 +168,9 @@ void MockPrinter::UpdateSettings(int cookie, PrintMsg_PrintPages_Params* params, const std::vector<int>& pages, - int margins_type) { + int margins_type, + const gfx::Size& page_size, + int scale_factor) { if (document_cookie_ == -1) { document_cookie_ = CreateDocumentCookie(); } @@ -169,6 +178,8 @@ params->pages = pages; SetPrintParams(&(params->params)); UpdateMargins(margins_type, dpi_, &(params->params)); + if (!page_size.IsEmpty()) + UpdatePageSizeAndScaling(page_size, scale_factor, ¶ms->params); printer_status_ = PRINTER_PRINTING; }
diff --git a/components/printing/test/mock_printer.h b/components/printing/test/mock_printer.h index 5eaba45..9492a6b 100644 --- a/components/printing/test/mock_printer.h +++ b/components/printing/test/mock_printer.h
@@ -85,7 +85,9 @@ void UpdateSettings(int cookie, PrintMsg_PrintPages_Params* params, const std::vector<int>& page_range_array, - int margins_type); + int margins_type, + const gfx::Size& page_size, + int scale_factor); void SetPrintedPagesCount(int cookie, int number_pages); void PrintPage(const PrintHostMsg_DidPrintPage_Params& params);
diff --git a/components/printing/test/print_mock_render_thread.cc b/components/printing/test/print_mock_render_thread.cc index cc8205a..74013e34 100644 --- a/components/printing/test/print_mock_render_thread.cc +++ b/components/printing/test/print_mock_render_thread.cc
@@ -15,6 +15,7 @@ #include "printing/features/features.h" #include "printing/page_range.h" #include "printing/print_job_constants.h" +#include "printing/units.h" #include "testing/gtest/include/gtest/gtest.h" #if BUILDFLAG(ENABLE_PRINTING) @@ -162,9 +163,32 @@ new_ranges.push_back(range); } } - std::vector<int> pages(printing::PageRange::GetPages(new_ranges)); - printer_->UpdateSettings(document_cookie, params, pages, margins_type); + // Get media size + const base::DictionaryValue* media_size_value = nullptr; + gfx::Size page_size; + if (job_settings.GetDictionary(printing::kSettingMediaSize, + &media_size_value)) { + int width_microns = 0; + int height_microns = 0; + if (media_size_value->GetInteger(printing::kSettingMediaSizeWidthMicrons, + &width_microns) && + media_size_value->GetInteger(printing::kSettingMediaSizeHeightMicrons, + &height_microns)) { + float device_microns_per_unit = + (printing::kHundrethsMMPerInch * 10.0f) / printing::kDefaultPdfDpi; + page_size = gfx::Size(width_microns / device_microns_per_unit, + height_microns / device_microns_per_unit); + } + } + + // Get scaling + int scale_factor = 100; + job_settings.GetInteger(printing::kSettingScaleFactor, &scale_factor); + + std::vector<int> pages(printing::PageRange::GetPages(new_ranges)); + printer_->UpdateSettings(document_cookie, params, pages, margins_type, + page_size, scale_factor); job_settings.GetBoolean(printing::kSettingShouldPrintSelectionOnly, ¶ms->params.selection_only); job_settings.GetBoolean(printing::kSettingShouldPrintBackgrounds,
diff --git a/components/printing/test/print_web_view_helper_browsertest.cc b/components/printing/test/print_web_view_helper_browsertest.cc index 279ae825..ce387743 100644 --- a/components/printing/test/print_web_view_helper_browsertest.cc +++ b/components/printing/test/print_web_view_helper_browsertest.cc
@@ -24,6 +24,7 @@ #include "ipc/ipc_listener.h" #include "printing/features/features.h" #include "printing/print_job_constants.h" +#include "printing/units.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/WebMouseEvent.h" #include "third_party/WebKit/public/platform/WebString.h" @@ -210,6 +211,20 @@ } #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) +#if defined(OS_WIN) + // Verifies that the correct page size was returned. + void VerifyPrintedPageSize(const gfx::Size& page_size) { + const IPC::Message* print_msg = + render_thread_->sink().GetUniqueMessageMatching( + PrintHostMsg_DidPrintPage::ID); + PrintHostMsg_DidPrintPage::Param post_did_print_page_param; + PrintHostMsg_DidPrintPage::Read(print_msg, &post_did_print_page_param); + gfx::Size page_size_received = + std::get<0>(post_did_print_page_param).page_size; + EXPECT_EQ(page_size, page_size_received); + } +#endif + // Verifies whether the pages printed or not. void VerifyPagesPrinted(bool printed) { const IPC::Message* print_msg = @@ -971,6 +986,41 @@ VerifyPagesPrinted(true); } +// Tests that when printing non-default scaling values, the page size returned +// by PrintWebViewHelper is still the real physical page size. See +// crbug.com/686384 +TEST_F(MAYBE_PrintWebViewHelperPreviewTest, OnPrintForPrintPreviewWithScaling) { + LoadHTML(kPrintPreviewHTML); + + // Fill in some dummy values. + base::DictionaryValue dict; + CreatePrintSettingsDictionary(&dict); + + // Media size + gfx::Size page_size_in = gfx::Size(240, 480); + float device_microns_per_unit = + (printing::kHundrethsMMPerInch * 10.0f) / printing::kDefaultPdfDpi; + int height_microns = + static_cast<int>(page_size_in.height() * device_microns_per_unit); + int width_microns = + static_cast<int>(page_size_in.width() * device_microns_per_unit); + auto media_size = base::MakeUnique<base::DictionaryValue>(); + media_size->SetInteger(kSettingMediaSizeHeightMicrons, height_microns); + media_size->SetInteger(kSettingMediaSizeWidthMicrons, width_microns); + + // Non default scaling value + dict.SetInteger(kSettingScaleFactor, 80); + dict.Set(kSettingMediaSize, media_size.release()); + + OnPrintForPrintPreview(dict); + + VerifyPrintFailed(false); + VerifyPagesPrinted(true); +#if defined(OS_WIN) + VerifyPrintedPageSize(page_size_in); +#endif +} + // Tests that printing from print preview fails and receiving error messages // through that channel all works. TEST_F(MAYBE_PrintWebViewHelperPreviewTest, OnPrintForPrintPreviewFail) {
diff --git a/components/sessions/core/session_backend.cc b/components/sessions/core/session_backend.cc index 43db0ae..be991f6 100644 --- a/components/sessions/core/session_backend.cc +++ b/components/sessions/core/session_backend.cc
@@ -56,8 +56,7 @@ } // Reads the contents of the file specified in the constructor, returning // true on success, and filling up |commands| with commands. - bool Read(sessions::BaseSessionService::SessionType type, - std::vector<std::unique_ptr<sessions::SessionCommand>>* commands); + bool Read(std::vector<std::unique_ptr<sessions::SessionCommand>>* commands); private: // Reads a single command, returning it. A return value of NULL indicates @@ -91,13 +90,11 @@ }; bool SessionFileReader::Read( - sessions::BaseSessionService::SessionType type, std::vector<std::unique_ptr<sessions::SessionCommand>>* commands) { if (!file_->IsValid()) return false; FileHeader header; int read_count; - TimeTicks start_time = TimeTicks::Now(); read_count = file_->ReadAtCurrentPos(reinterpret_cast<char*>(&header), sizeof(header)); if (read_count != sizeof(header) || header.signature != kFileSignature || @@ -110,13 +107,6 @@ read_commands.push_back(std::move(command)); if (!errored_) read_commands.swap(*commands); - if (type == sessions::BaseSessionService::TAB_RESTORE) { - UMA_HISTOGRAM_TIMES("TabRestore.read_session_file_time", - TimeTicks::Now() - start_time); - } else { - UMA_HISTOGRAM_TIMES("SessionRestore.read_session_file_time", - TimeTicks::Now() - start_time); - } return !errored_; } @@ -262,7 +252,7 @@ std::vector<std::unique_ptr<sessions::SessionCommand>>* commands) { Init(); SessionFileReader file_reader(GetLastSessionPath()); - return file_reader.Read(type_, commands); + return file_reader.Read(commands); } void SessionBackend::DeleteLastSession() { @@ -278,19 +268,8 @@ const base::FilePath last_session_path = GetLastSessionPath(); if (base::PathExists(last_session_path)) base::DeleteFile(last_session_path, false); - if (base::PathExists(current_session_path)) { - int64_t file_size; - if (base::GetFileSize(current_session_path, &file_size)) { - if (type_ == sessions::BaseSessionService::TAB_RESTORE) { - UMA_HISTOGRAM_COUNTS("TabRestore.last_session_file_size", - static_cast<int>(file_size / 1024)); - } else { - UMA_HISTOGRAM_COUNTS("SessionRestore.last_session_file_size", - static_cast<int>(file_size / 1024)); - } - } + if (base::PathExists(current_session_path)) last_session_valid_ = base::Move(current_session_path, last_session_path); - } if (base::PathExists(current_session_path)) base::DeleteFile(current_session_path, false); @@ -303,7 +282,7 @@ std::vector<std::unique_ptr<sessions::SessionCommand>>* commands) { Init(); SessionFileReader file_reader(GetCurrentSessionPath()); - return file_reader.Read(type_, commands); + return file_reader.Read(commands); } bool SessionBackend::AppendCommandsToFile( @@ -313,10 +292,6 @@ int wrote; const size_type content_size = static_cast<size_type>((*i)->size()); const size_type total_size = content_size + sizeof(id_type); - if (type_ == sessions::BaseSessionService::TAB_RESTORE) - UMA_HISTOGRAM_COUNTS("TabRestore.command_size", total_size); - else - UMA_HISTOGRAM_COUNTS("SessionRestore.command_size", total_size); wrote = file->WriteAtCurrentPos(reinterpret_cast<const char*>(&total_size), sizeof(total_size)); if (wrote != sizeof(total_size)) {
diff --git a/components/ukm/ukm_service.cc b/components/ukm/ukm_service.cc index bd9b2c8..c58eef84 100644 --- a/components/ukm/ukm_service.cc +++ b/components/ukm/ukm_service.cc
@@ -277,8 +277,9 @@ // TODO(holte): Handle data usage on cellular, etc. if (!log_uploader_) { log_uploader_ = client_->CreateUploader( - GetServerUrl(), kMimeType, base::Bind(&UkmService::OnLogUploadComplete, - self_ptr_factory_.GetWeakPtr())); + GetServerUrl(), kMimeType, metrics::MetricsLogUploader::UKM, + base::Bind(&UkmService::OnLogUploadComplete, + self_ptr_factory_.GetWeakPtr())); } log_upload_in_progress_ = true;
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index b39ba86..63e138d 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -572,6 +572,11 @@ // Select an appropriate renderer to show the error page. RenderFrameHostImpl* render_frame_host = frame_tree_node_->render_manager()->GetFrameHostForNavigation(*this); + + // Don't ask the renderer to commit an URL if the browser will kill it when + // it does. + DCHECK(render_frame_host->CanCommitURL(common_params_.url)); + NavigatorImpl::CheckWebUIRendererDoesNotDisplayNormalURL(render_frame_host, common_params_.url);
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 1448dd8..069f5b5 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -2403,15 +2403,6 @@ render_view_host_->is_waiting_for_close_ack_ = false; } -bool RenderFrameHostImpl::CanCommitURL(const GURL& url) { - // TODO(creis): We should also check for WebUI pages here. Also, when the - // out-of-process iframes implementation is ready, we should check for - // cross-site URLs that are not allowed to commit in this process. - - // Give the client a chance to disallow URLs from committing. - return GetContentClient()->browser()->CanCommitURL(GetProcess(), url); -} - bool RenderFrameHostImpl::CanCommitOrigin( const url::Origin& origin, const GURL& url) { @@ -2912,6 +2903,15 @@ Send(new FrameMsg_ClearFocusedElement(GetRoutingID())); } +bool RenderFrameHostImpl::CanCommitURL(const GURL& url) { + // TODO(creis): We should also check for WebUI pages here. Also, when the + // out-of-process iframes implementation is ready, we should check for + // cross-site URLs that are not allowed to commit in this process. + + // Give the client a chance to disallow URLs from committing. + return GetContentClient()->browser()->CanCommitURL(GetProcess(), url); +} + bool RenderFrameHostImpl::IsSameSiteInstance( RenderFrameHostImpl* other_render_frame_host) { // As a sanity check, make sure the frame belongs to the same BrowserContext.
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 60f8694..103a23ed 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -607,6 +607,11 @@ void ClearFocusedElement(); + // Returns whether the given URL is allowed to commit in the current process. + // This is a more conservative check than RenderProcessHost::FilterURL, since + // it will be used to kill processes that commit unauthorized URLs. + bool CanCommitURL(const GURL& url); + // PlzNavigate: returns the PreviewsState of the last successful navigation // that made a network request. The PreviewsState is a bitmask of potentially // several Previews optimizations. @@ -777,11 +782,6 @@ // relevant. void ResetWaitingState(); - // Returns whether the given URL is allowed to commit in the current process. - // This is a more conservative check than RenderProcessHost::FilterURL, since - // it will be used to kill processes that commit unauthorized URLs. - bool CanCommitURL(const GURL& url); - // Returns whether the given origin is allowed to commit in the current // RenderFrameHost. The |url| is used to ensure it matches the origin in cases // where it is applicable. This is a more conservative check than
diff --git a/content/browser/media/session/media_session_service_impl_browsertest.cc b/content/browser/media/session/media_session_service_impl_browsertest.cc new file mode 100644 index 0000000..959bbae --- /dev/null +++ b/content/browser/media/session/media_session_service_impl_browsertest.cc
@@ -0,0 +1,29 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/command_line.h" +#include "content/public/test/content_browser_test.h" +#include "content/public/test/content_browser_test_utils.h" +#include "content/shell/browser/shell.h" + +namespace content { + +class MediaSessionServiceImplBrowserTest : public ContentBrowserTest { + protected: + void SetUpCommandLine(base::CommandLine* command_line) override { + ContentBrowserTest::SetUpCommandLine(command_line); + command_line->AppendSwitchASCII("--enable-blink-features", "MediaSession"); + } +}; + +// Two windows from the same BrowserContext. +IN_PROC_BROWSER_TEST_F(MediaSessionServiceImplBrowserTest, + CrashMessageOnUnload) { + NavigateToURL(shell(), GetTestUrl("media/session", "embedder.html")); + // Navigate to a chrome:// URL to avoid render process re-use. + NavigateToURL(shell(), GURL("chrome://flags")); + // Should not crash. +} + +} // namespace content
diff --git a/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc b/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc index a2ca470..7e213f0 100644 --- a/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc +++ b/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
@@ -88,17 +88,10 @@ MakeTypicalCall("testCanvasCapture(drawWebGL);", kCanvasCaptureTestHtmlFile); } -#if defined(OS_MACOSX) -// This test causes GL related issues in Mac: https://crbug.com/695452. -#define MAYBE_VerifyCanvasCaptureOffscreenCanvasCommitFrames \ - DISABLED_VerifyCanvasCaptureOffscreenCanvasCommitFrames -#else -#define MAYBE_VerifyCanvasCaptureOffscreenCanvasCommitFrames \ - VerifyCanvasCaptureOffscreenCanvasCommitFrames -#endif - -IN_PROC_BROWSER_TEST_F(WebRtcCaptureFromElementBrowserTest, - MAYBE_VerifyCanvasCaptureOffscreenCanvasCommitFrames) { +// This test causes GL related issues on Win and Mac: https://crbug.com/695452. +IN_PROC_BROWSER_TEST_F( + WebRtcCaptureFromElementBrowserTest, + DISABLED_VerifyCanvasCaptureOffscreenCanvasCommitFrames) { MakeTypicalCall("testCanvasCapture(drawOffscreenCanvasCommit);", kCanvasCaptureTestHtmlFile); }
diff --git a/content/child/resource_dispatcher.cc b/content/child/resource_dispatcher.cc index 04759bb..2a52bbd 100644 --- a/content/child/resource_dispatcher.cc +++ b/content/child/resource_dispatcher.cc
@@ -668,10 +668,8 @@ } if (ipc_type == blink::WebURLRequest::LoadingIPCType::Mojo) { - scoped_refptr<base::SingleThreadTaskRunner> task_runner = - loading_task_runner ? loading_task_runner : main_thread_task_runner_; std::unique_ptr<URLLoaderClientImpl> client( - new URLLoaderClientImpl(request_id, this, std::move(task_runner))); + new URLLoaderClientImpl(request_id, this, main_thread_task_runner_)); mojom::URLLoaderAssociatedPtr url_loader; mojom::URLLoaderClientAssociatedPtrInfo client_ptr_info; client->Bind(&client_ptr_info);
diff --git a/content/child/url_loader_client_impl.cc b/content/child/url_loader_client_impl.cc index c1d25c8..ab1e930 100644 --- a/content/child/url_loader_client_impl.cc +++ b/content/child/url_loader_client_impl.cc
@@ -30,7 +30,7 @@ void URLLoaderClientImpl::Bind( mojom::URLLoaderClientAssociatedPtrInfo* client_ptr_info) { - binding_.Bind(client_ptr_info, task_runner_.get()); + binding_.Bind(client_ptr_info); } void URLLoaderClientImpl::SetDefersLoading() {
diff --git a/content/public/test/test_utils.cc b/content/public/test/test_utils.cc index 1d2da32a..4afe2321 100644 --- a/content/public/test/test_utils.cc +++ b/content/public/test/test_utils.cc
@@ -292,8 +292,8 @@ return; running_ = true; - run_loop_.reset(new base::RunLoop); - run_loop_->Run(); + message_loop_runner_ = new MessageLoopRunner; + message_loop_runner_->Run(); EXPECT_TRUE(seen_); } @@ -310,7 +310,7 @@ if (!running_) return; - run_loop_->Quit(); + message_loop_runner_->Quit(); running_ = false; }
diff --git a/content/public/test/test_utils.h b/content/public/test/test_utils.h index ed1f8e6..29f5965 100644 --- a/content/public/test/test_utils.h +++ b/content/public/test/test_utils.h
@@ -235,7 +235,7 @@ NotificationSource source_; NotificationDetails details_; - std::unique_ptr<base::RunLoop> run_loop_; + scoped_refptr<MessageLoopRunner> message_loop_runner_; DISALLOW_COPY_AND_ASSIGN(WindowedNotificationObserver); };
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index f62e2f3..abbbbfa 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -586,8 +586,8 @@ "media/media_stream_center.h", "media/media_stream_constraints_util.cc", "media/media_stream_constraints_util.h", - "media/media_stream_constraints_util_video_source.cc", - "media/media_stream_constraints_util_video_source.h", + "media/media_stream_constraints_util_video_device.cc", + "media/media_stream_constraints_util_video_device.h", "media/media_stream_dispatcher.cc", "media/media_stream_dispatcher.h", "media/media_stream_dispatcher_eventhandler.h",
diff --git a/content/renderer/media/media_stream_constraints_util.h b/content/renderer/media/media_stream_constraints_util.h index 7b24be2..a3f75a6e 100644 --- a/content/renderer/media/media_stream_constraints_util.h +++ b/content/renderer/media/media_stream_constraints_util.h
@@ -69,6 +69,30 @@ const blink::WebMediaConstraints& constraints, const blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*picker); +template <typename ConstraintType> +bool ConstraintHasMax(const ConstraintType& constraint) { + return constraint.hasMax() || constraint.hasExact(); +} + +template <typename ConstraintType> +bool ConstraintHasMin(const ConstraintType& constraint) { + return constraint.hasMin() || constraint.hasExact(); +} + +template <typename ConstraintType> +auto ConstraintMax(const ConstraintType& constraint) + -> decltype(constraint.max()) { + DCHECK(ConstraintHasMax(constraint)); + return constraint.hasExact() ? constraint.exact() : constraint.max(); +} + +template <typename ConstraintType> +auto ConstraintMin(const ConstraintType& constraint) + -> decltype(constraint.min()) { + DCHECK(ConstraintHasMin(constraint)); + return constraint.hasExact() ? constraint.exact() : constraint.min(); +} + } // namespace content #endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_CONSTRAINTS_UTIL_H_
diff --git a/content/renderer/media/media_stream_constraints_util_video_source.cc b/content/renderer/media/media_stream_constraints_util_video_device.cc similarity index 84% rename from content/renderer/media/media_stream_constraints_util_video_source.cc rename to content/renderer/media/media_stream_constraints_util_video_device.cc index 59826d5..3e2f3e8 100644 --- a/content/renderer/media/media_stream_constraints_util_video_source.cc +++ b/content/renderer/media/media_stream_constraints_util_video_device.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/media/media_stream_constraints_util_video_source.h" +#include "content/renderer/media/media_stream_constraints_util_video_device.h" #include <algorithm> #include <cmath> @@ -10,6 +10,7 @@ #include <utility> #include <vector> +#include "content/renderer/media/media_stream_constraints_util.h" #include "content/renderer/media/media_stream_video_source.h" #include "third_party/WebKit/public/platform/WebMediaConstraints.h" #include "third_party/WebKit/public/platform/WebString.h" @@ -49,28 +50,73 @@ } } -template <typename ConstraintType> -bool ConstraintHasMax(const ConstraintType& constraint) { - return constraint.hasMax() || constraint.hasExact(); -} +struct VideoDeviceCaptureSourceSettings { + public: + VideoDeviceCaptureSourceSettings() + : facing_mode_(::mojom::FacingMode::NONE), + power_line_frequency_(media::PowerLineFrequency::FREQUENCY_DEFAULT) {} -template <typename ConstraintType> -bool ConstraintHasMin(const ConstraintType& constraint) { - return constraint.hasMin() || constraint.hasExact(); -} + VideoDeviceCaptureSourceSettings( + const std::string& device_id, + const media::VideoCaptureFormat& format, + ::mojom::FacingMode facing_mode, + media::PowerLineFrequency power_line_frequency) + : device_id_(device_id), + format_(format), + facing_mode_(facing_mode), + power_line_frequency_(power_line_frequency) {} -template <typename ConstraintType> -auto ConstraintMax(const ConstraintType& constraint) - -> decltype(constraint.max()) { - DCHECK(ConstraintHasMax(constraint)); - return constraint.hasExact() ? constraint.exact() : constraint.max(); -} + VideoDeviceCaptureSourceSettings( + const VideoDeviceCaptureSourceSettings& other) = default; + VideoDeviceCaptureSourceSettings& operator=( + const VideoDeviceCaptureSourceSettings& other) = default; + VideoDeviceCaptureSourceSettings(VideoDeviceCaptureSourceSettings&& other) = + default; + VideoDeviceCaptureSourceSettings& operator=( + VideoDeviceCaptureSourceSettings&& other) = default; + ~VideoDeviceCaptureSourceSettings() = default; -template <typename ConstraintType> -auto ConstraintMin(const ConstraintType& constraint) - -> decltype(constraint.min()) { - DCHECK(ConstraintHasMin(constraint)); - return constraint.hasExact() ? constraint.exact() : constraint.min(); + // These accessor-like methods transform types to what Blink constraint + // classes expect. + blink::WebString GetFacingMode() const { return ToWebString(facing_mode_); } + long GetPowerLineFrequency() const { + return static_cast<long>(power_line_frequency_); + } + long GetWidth() const { return format_.frame_size.width(); } + long GetHeight() const { return format_.frame_size.height(); } + double GetFrameRate() const { return format_.frame_rate; } + blink::WebString GetDeviceId() const { + return blink::WebString::fromASCII(device_id_.data()); + } + blink::WebString GetVideoKind() const { + return GetVideoKindForFormat(format_); + } + + // Accessors. + const media::VideoCaptureFormat& format() const { return format_; } + const std::string& device_id() const { return device_id_; } + ::mojom::FacingMode facing_mode() const { return facing_mode_; } + media::PowerLineFrequency power_line_frequency() const { + return power_line_frequency_; + } + + private: + std::string device_id_; + media::VideoCaptureFormat format_; + ::mojom::FacingMode facing_mode_; + media::PowerLineFrequency power_line_frequency_; +}; + +VideoDeviceCaptureSourceSelectionResult ResultFromSettings( + const VideoDeviceCaptureSourceSettings& settings) { + VideoDeviceCaptureSourceSelectionResult result; + result.capture_params.power_line_frequency = settings.power_line_frequency(); + result.capture_params.requested_format = settings.format(); + result.device_id = settings.device_id(); + result.facing_mode = settings.facing_mode(); + result.failed_constraint_name = nullptr; + + return result; } // Generic distance function between two numeric values. Based on the fitness @@ -324,7 +370,7 @@ // Otherwise the distance is a finite value. Candidates with lower distance // satisfy |constraint_set| in a "better" way. double CandidateSourceDistance( - const VideoCaptureSourceSettings& candidate, + const VideoDeviceCaptureSourceSettings& candidate, const blink::WebMediaTrackConstraintSet& constraint_set, const char** failed_constraint_name) { return DeviceSourceDistance(candidate.device_id(), candidate.facing_mode(), @@ -470,7 +516,7 @@ // setting in |candidate| and the corresponding constraint in |constraint_set|. // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. double CandidateFitnessDistance( - const VideoCaptureSourceSettings& candidate, + const VideoDeviceCaptureSourceSettings& candidate, const blink::WebMediaTrackConstraintSet& constraint_set) { DCHECK(std::isfinite( CandidateSourceDistance(candidate, constraint_set, nullptr))); @@ -502,7 +548,7 @@ // height and frame rate). // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. double CandidateNativeFitnessDistance( - const VideoCaptureSourceSettings& candidate, + const VideoDeviceCaptureSourceSettings& candidate, const blink::WebMediaTrackConstraintSet& constraint_set) { DCHECK(std::isfinite( CandidateSourceDistance(candidate, constraint_set, nullptr))); @@ -524,9 +570,10 @@ // These entries are to be used as the final tie breaker for candidates that // are equally good according to the spec and the custom distance functions // between candidates and constraints. -void AppendDistanceFromDefault(const VideoCaptureSourceSettings& candidate, - const VideoCaptureCapabilities& capabilities, - DistanceVector* distance_vector) { +void AppendDistanceFromDefault( + const VideoDeviceCaptureSourceSettings& candidate, + const VideoDeviceCaptureCapabilities& capabilities, + DistanceVector* distance_vector) { // Favor IDs that appear first in the enumeration. for (size_t i = 0; i < capabilities.device_capabilities.size(); ++i) { if (candidate.device_id() == @@ -570,82 +617,36 @@ : blink::WebString::fromASCII(kVideoKindColor); } -VideoCaptureCapabilities::VideoCaptureCapabilities() = default; -VideoCaptureCapabilities::VideoCaptureCapabilities( - VideoCaptureCapabilities&& other) = default; -VideoCaptureCapabilities::~VideoCaptureCapabilities() = default; -VideoCaptureCapabilities& VideoCaptureCapabilities::operator=( - VideoCaptureCapabilities&& other) = default; - -VideoCaptureSourceSettings::VideoCaptureSourceSettings( - const VideoCaptureSourceSettings& other) = default; -VideoCaptureSourceSettings::VideoCaptureSourceSettings( - VideoCaptureSourceSettings&& other) = default; -VideoCaptureSourceSettings::~VideoCaptureSourceSettings() = default; -VideoCaptureSourceSettings& VideoCaptureSourceSettings::operator=( - const VideoCaptureSourceSettings& other) = default; -VideoCaptureSourceSettings& VideoCaptureSourceSettings::operator=( - VideoCaptureSourceSettings&& other) = default; - -VideoCaptureSourceSettings::VideoCaptureSourceSettings() - : facing_mode_(::mojom::FacingMode::NONE), - power_line_frequency_(media::PowerLineFrequency::FREQUENCY_DEFAULT) {} - -VideoCaptureSourceSettings::VideoCaptureSourceSettings( - const std::string& device_id, - const media::VideoCaptureFormat& format, - ::mojom::FacingMode facing_mode, - media::PowerLineFrequency power_line_frequency) - : device_id_(device_id), - format_(format), - facing_mode_(facing_mode), - power_line_frequency_(power_line_frequency) {} - -blink::WebString VideoCaptureSourceSettings::GetFacingMode() const { - return ToWebString(facing_mode_); -} - -long VideoCaptureSourceSettings::GetPowerLineFrequency() const { - return static_cast<long>(power_line_frequency_); -} - -long VideoCaptureSourceSettings::GetWidth() const { - return format_.frame_size.width(); -} - -long VideoCaptureSourceSettings::GetHeight() const { - return format_.frame_size.height(); -} - -double VideoCaptureSourceSettings::GetFrameRate() const { - return format_.frame_rate; -} - -blink::WebString VideoCaptureSourceSettings::GetDeviceId() const { - return blink::WebString::fromASCII(device_id_.data()); -} - -blink::WebString VideoCaptureSourceSettings::GetVideoKind() const { - return GetVideoKindForFormat(format_); -} +VideoDeviceCaptureCapabilities::VideoDeviceCaptureCapabilities() = default; +VideoDeviceCaptureCapabilities::VideoDeviceCaptureCapabilities( + VideoDeviceCaptureCapabilities&& other) = default; +VideoDeviceCaptureCapabilities::~VideoDeviceCaptureCapabilities() = default; +VideoDeviceCaptureCapabilities& VideoDeviceCaptureCapabilities::operator=( + VideoDeviceCaptureCapabilities&& other) = default; const char kDefaultFailedConstraintName[] = ""; -VideoCaptureSourceSelectionResult::VideoCaptureSourceSelectionResult() - : failed_constraint_name(kDefaultFailedConstraintName) {} -VideoCaptureSourceSelectionResult::VideoCaptureSourceSelectionResult( - const VideoCaptureSourceSelectionResult& other) = default; -VideoCaptureSourceSelectionResult::VideoCaptureSourceSelectionResult( - VideoCaptureSourceSelectionResult&& other) = default; -VideoCaptureSourceSelectionResult::~VideoCaptureSourceSelectionResult() = - default; -VideoCaptureSourceSelectionResult& VideoCaptureSourceSelectionResult::operator=( - const VideoCaptureSourceSelectionResult& other) = default; -VideoCaptureSourceSelectionResult& VideoCaptureSourceSelectionResult::operator=( - VideoCaptureSourceSelectionResult&& other) = default; +VideoDeviceCaptureSourceSelectionResult:: + VideoDeviceCaptureSourceSelectionResult() + : failed_constraint_name(kDefaultFailedConstraintName), + facing_mode(::mojom::FacingMode::NONE) {} +VideoDeviceCaptureSourceSelectionResult:: + VideoDeviceCaptureSourceSelectionResult( + const VideoDeviceCaptureSourceSelectionResult& other) = default; +VideoDeviceCaptureSourceSelectionResult:: + VideoDeviceCaptureSourceSelectionResult( + VideoDeviceCaptureSourceSelectionResult&& other) = default; +VideoDeviceCaptureSourceSelectionResult:: + ~VideoDeviceCaptureSourceSelectionResult() = default; +VideoDeviceCaptureSourceSelectionResult& +VideoDeviceCaptureSourceSelectionResult::operator=( + const VideoDeviceCaptureSourceSelectionResult& other) = default; +VideoDeviceCaptureSourceSelectionResult& +VideoDeviceCaptureSourceSelectionResult::operator=( + VideoDeviceCaptureSourceSelectionResult&& other) = default; -VideoCaptureSourceSelectionResult SelectVideoCaptureSourceSettings( - const VideoCaptureCapabilities& capabilities, +VideoDeviceCaptureSourceSelectionResult SelectVideoDeviceCaptureSourceSettings( + const VideoDeviceCaptureCapabilities& capabilities, const blink::WebMediaConstraints& constraints) { // This function works only if infinity is defined for the double type. DCHECK(std::numeric_limits<double>::has_infinity); @@ -667,7 +668,7 @@ DistanceVector best_distance(2 * constraints.advanced().size() + 3 + kNumDefaultDistanceEntries); std::fill(best_distance.begin(), best_distance.end(), HUGE_VAL); - VideoCaptureSourceSelectionResult result; + VideoDeviceCaptureSourceSelectionResult result; const char* failed_constraint_name = result.failed_constraint_name; for (auto& device : capabilities.device_capabilities) { @@ -701,9 +702,9 @@ // Custom distances must be added to the candidate distance vector after // all the spec-mandated values. DistanceVector advanced_custom_distance_vector; - VideoCaptureSourceSettings candidate(device->device_id, format, - device->facing_mode, - power_line_frequency); + VideoDeviceCaptureSourceSettings candidate(device->device_id, format, + device->facing_mode, + power_line_frequency); DistanceVector candidate_distance_vector; // First criteria for valid candidates is satisfaction of advanced // constraint sets. @@ -736,14 +737,13 @@ DCHECK_EQ(best_distance.size(), candidate_distance_vector.size()); if (candidate_distance_vector < best_distance) { best_distance = candidate_distance_vector; - result.settings = std::move(candidate); - result.failed_constraint_name = nullptr; + result = ResultFromSettings(candidate); } } } } - if (!result.has_value()) + if (!result.HasValue()) result.failed_constraint_name = failed_constraint_name; return result;
diff --git a/content/renderer/media/media_stream_constraints_util_video_source.h b/content/renderer/media/media_stream_constraints_util_video_device.h similarity index 66% rename from content/renderer/media/media_stream_constraints_util_video_source.h rename to content/renderer/media/media_stream_constraints_util_video_device.h index b3df2ff8..af55fdc 100644 --- a/content/renderer/media/media_stream_constraints_util_video_source.h +++ b/content/renderer/media/media_stream_constraints_util_video_device.h
@@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_CONSTRAINTS_UTIL_VIDEO_SOURCE_H_ -#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_CONSTRAINTS_UTIL_VIDEO_SOURCE_H_ +#ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_CONSTRAINTS_UTIL_VIDEO_DEVICE_H_ +#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_CONSTRAINTS_UTIL_VIDEO_DEVICE_H_ -#include <iosfwd> #include <string> #include <vector> @@ -25,69 +24,51 @@ blink::WebString CONTENT_EXPORT GetVideoKindForFormat(const media::VideoCaptureFormat& format); -struct CONTENT_EXPORT VideoCaptureCapabilities { - VideoCaptureCapabilities(); - VideoCaptureCapabilities(VideoCaptureCapabilities&& other); - ~VideoCaptureCapabilities(); - VideoCaptureCapabilities& operator=(VideoCaptureCapabilities&& other); +struct CONTENT_EXPORT VideoDeviceCaptureCapabilities { + VideoDeviceCaptureCapabilities(); + VideoDeviceCaptureCapabilities(VideoDeviceCaptureCapabilities&& other); + ~VideoDeviceCaptureCapabilities(); + VideoDeviceCaptureCapabilities& operator=( + VideoDeviceCaptureCapabilities&& other); // Each field is independent of each other. std::vector<::mojom::VideoInputDeviceCapabilitiesPtr> device_capabilities; std::vector<media::PowerLineFrequency> power_line_capabilities; }; -class CONTENT_EXPORT VideoCaptureSourceSettings { - public: - VideoCaptureSourceSettings(); - VideoCaptureSourceSettings(const VideoCaptureSourceSettings& other); - VideoCaptureSourceSettings(VideoCaptureSourceSettings&& other); - VideoCaptureSourceSettings(const std::string& device_id, - const media::VideoCaptureFormat& format, - ::mojom::FacingMode facing_mode, - media::PowerLineFrequency power_line_frequency); - ~VideoCaptureSourceSettings(); - VideoCaptureSourceSettings& operator=( - const VideoCaptureSourceSettings& other); - VideoCaptureSourceSettings& operator=(VideoCaptureSourceSettings&& other); +struct CONTENT_EXPORT VideoDeviceCaptureSourceSelectionResult { + VideoDeviceCaptureSourceSelectionResult(); + VideoDeviceCaptureSourceSelectionResult( + const VideoDeviceCaptureSourceSelectionResult& other); + VideoDeviceCaptureSourceSelectionResult( + VideoDeviceCaptureSourceSelectionResult&& other); + ~VideoDeviceCaptureSourceSelectionResult(); + VideoDeviceCaptureSourceSelectionResult& operator=( + const VideoDeviceCaptureSourceSelectionResult& other); + VideoDeviceCaptureSourceSelectionResult& operator=( + VideoDeviceCaptureSourceSelectionResult&& other); - // Accessors for easier interaction with blink constraint classes. - blink::WebString GetFacingMode() const; - long GetPowerLineFrequency() const; - long GetWidth() const; - long GetHeight() const; - double GetFrameRate() const; - blink::WebString GetDeviceId() const; - blink::WebString GetVideoKind() const; + bool HasValue() const { return failed_constraint_name == nullptr; } - const media::VideoCaptureFormat& format() const { return format_; } - const std::string& device_id() const { return device_id_; } - ::mojom::FacingMode facing_mode() const { return facing_mode_; } - media::PowerLineFrequency power_line_frequency() const { - return power_line_frequency_; + // Convenience accessors for fields embedded in |capture_params|. + const media::VideoCaptureFormat& Format() const { + return capture_params.requested_format; + } + int Width() const { + return capture_params.requested_format.frame_size.width(); + } + int Height() const { + return capture_params.requested_format.frame_size.height(); + } + float FrameRate() const { return capture_params.requested_format.frame_rate; } + media::PowerLineFrequency PowerLineFrequency() const { + return capture_params.power_line_frequency; } - private: - std::string device_id_; - media::VideoCaptureFormat format_; - ::mojom::FacingMode facing_mode_; - media::PowerLineFrequency power_line_frequency_; -}; - -struct CONTENT_EXPORT VideoCaptureSourceSelectionResult { - VideoCaptureSourceSelectionResult(); - VideoCaptureSourceSelectionResult( - const VideoCaptureSourceSelectionResult& other); - VideoCaptureSourceSelectionResult(VideoCaptureSourceSelectionResult&& other); - ~VideoCaptureSourceSelectionResult(); - VideoCaptureSourceSelectionResult& operator=( - const VideoCaptureSourceSelectionResult& other); - VideoCaptureSourceSelectionResult& operator=( - VideoCaptureSourceSelectionResult&& other); - - bool has_value() const { return failed_constraint_name == nullptr; } - - VideoCaptureSourceSettings settings; const char* failed_constraint_name; + std::string device_id; + ::mojom::FacingMode facing_mode; + media::VideoCaptureParams capture_params; }; // This function performs source and source-settings selection based on @@ -152,10 +133,11 @@ // settings that include the device ID, power-line frequency, resolution, and // frame rate, in that order. Note that there is no default facing mode or // aspect ratio. -VideoCaptureSourceSelectionResult CONTENT_EXPORT -SelectVideoCaptureSourceSettings(const VideoCaptureCapabilities& capabilities, - const blink::WebMediaConstraints& constraints); +VideoDeviceCaptureSourceSelectionResult CONTENT_EXPORT +SelectVideoDeviceCaptureSourceSettings( + const VideoDeviceCaptureCapabilities& capabilities, + const blink::WebMediaConstraints& constraints); } // namespace content -#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_CONSTRAINTS_UTIL_VIDEO_SOURCE_H_ +#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_CONSTRAINTS_UTIL_VIDEO_DEVICE_H_
diff --git a/content/renderer/media/media_stream_constraints_util_video_source_unittest.cc b/content/renderer/media/media_stream_constraints_util_video_device_unittest.cc similarity index 67% rename from content/renderer/media/media_stream_constraints_util_video_source_unittest.cc rename to content/renderer/media/media_stream_constraints_util_video_device_unittest.cc index cc92442f..5247f39 100644 --- a/content/renderer/media/media_stream_constraints_util_video_source_unittest.cc +++ b/content/renderer/media/media_stream_constraints_util_video_device_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/media/media_stream_constraints_util_video_source.h" +#include "content/renderer/media/media_stream_constraints_util_video_device.h" #include <algorithm> #include <utility> @@ -23,7 +23,7 @@ const char kDeviceID4[] = "fake_device_4"; } -class MediaStreamConstraintsUtilVideoSourceTest : public testing::Test { +class MediaStreamConstraintsUtilVideoDeviceTest : public testing::Test { public: void SetUp() override { // Default device. It is default because it is the first in the enumeration. @@ -110,13 +110,13 @@ } protected: - VideoCaptureSourceSelectionResult SelectSettings() { + VideoDeviceCaptureSourceSelectionResult SelectSettings() { blink::WebMediaConstraints constraints = constraint_factory_.CreateWebMediaConstraints(); - return SelectVideoCaptureSourceSettings(capabilities_, constraints); + return SelectVideoDeviceCaptureSourceSettings(capabilities_, constraints); } - VideoCaptureCapabilities capabilities_; + VideoDeviceCaptureCapabilities capabilities_; const mojom::VideoInputDeviceCapabilities* default_device_; const mojom::VideoInputDeviceCapabilities* low_res_device_; const mojom::VideoInputDeviceCapabilities* high_res_device_; @@ -130,109 +130,109 @@ }; // The Unconstrained test checks the default selection criteria. -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, Unconstrained) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, Unconstrained) { constraint_factory_.Reset(); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // Should select the default device with closest-to-default settings. - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); - EXPECT_EQ(default_device_->facing_mode, result.settings.facing_mode()); - EXPECT_EQ(*default_closest_format_, result.settings.format()); + EXPECT_EQ(default_device_->device_id, result.device_id); + EXPECT_EQ(default_device_->facing_mode, result.facing_mode); + EXPECT_EQ(*default_closest_format_, result.Format()); } // The "Overconstrained" tests verify that failure of any single required // constraint results in failure to select a candidate. -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, OverconstrainedOnDeviceID) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, OverconstrainedOnDeviceID) { constraint_factory_.Reset(); constraint_factory_.basic().deviceId.setExact( blink::WebString::fromASCII("NONEXISTING")); auto result = SelectSettings(); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_EQ(constraint_factory_.basic().deviceId.name(), result.failed_constraint_name); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, OverconstrainedOnFacingMode) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, OverconstrainedOnFacingMode) { constraint_factory_.Reset(); // No device in |capabilities_| has facing mode equal to LEFT. constraint_factory_.basic().facingMode.setExact( blink::WebString::fromASCII("left")); auto result = SelectSettings(); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_EQ(constraint_factory_.basic().facingMode.name(), result.failed_constraint_name); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, OverconstrainedOnVideoKind) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, OverconstrainedOnVideoKind) { constraint_factory_.Reset(); // No device in |capabilities_| has video kind infrared. constraint_factory_.basic().videoKind.setExact( blink::WebString::fromASCII("infrared")); auto result = SelectSettings(); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_EQ(constraint_factory_.basic().videoKind.name(), result.failed_constraint_name); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, OverconstrainedOnHeight) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, OverconstrainedOnHeight) { constraint_factory_.Reset(); constraint_factory_.basic().height.setExact(123467890); auto result = SelectSettings(); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_EQ(constraint_factory_.basic().height.name(), result.failed_constraint_name); constraint_factory_.Reset(); constraint_factory_.basic().height.setMin(123467890); result = SelectSettings(); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_EQ(constraint_factory_.basic().height.name(), result.failed_constraint_name); constraint_factory_.Reset(); constraint_factory_.basic().height.setMax(0); result = SelectSettings(); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_EQ(constraint_factory_.basic().height.name(), result.failed_constraint_name); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, OverconstrainedOnWidth) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, OverconstrainedOnWidth) { constraint_factory_.Reset(); constraint_factory_.basic().width.setExact(123467890); auto result = SelectSettings(); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_EQ(constraint_factory_.basic().width.name(), result.failed_constraint_name); constraint_factory_.Reset(); constraint_factory_.basic().width.setMin(123467890); result = SelectSettings(); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_EQ(constraint_factory_.basic().width.name(), result.failed_constraint_name); constraint_factory_.Reset(); constraint_factory_.basic().width.setMax(0); result = SelectSettings(); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_EQ(constraint_factory_.basic().width.name(), result.failed_constraint_name); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, OverconstrainedOnAspectRatio) { constraint_factory_.Reset(); constraint_factory_.basic().aspectRatio.setExact(123467890.0); auto result = SelectSettings(); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_EQ(constraint_factory_.basic().aspectRatio.name(), result.failed_constraint_name); constraint_factory_.Reset(); constraint_factory_.basic().aspectRatio.setMin(123467890.0); result = SelectSettings(); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_EQ(constraint_factory_.basic().aspectRatio.name(), result.failed_constraint_name); @@ -241,132 +241,132 @@ double kLowAspectRatio = 0.01; constraint_factory_.basic().aspectRatio.setMax(kLowAspectRatio); result = SelectSettings(); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_EQ(constraint_factory_.basic().aspectRatio.name(), result.failed_constraint_name); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, OverconstrainedOnFrameRate) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, OverconstrainedOnFrameRate) { constraint_factory_.Reset(); constraint_factory_.basic().frameRate.setExact(123467890.0); auto result = SelectSettings(); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_EQ(constraint_factory_.basic().frameRate.name(), result.failed_constraint_name); constraint_factory_.Reset(); constraint_factory_.basic().frameRate.setMin(123467890.0); result = SelectSettings(); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_EQ(constraint_factory_.basic().frameRate.name(), result.failed_constraint_name); constraint_factory_.Reset(); constraint_factory_.basic().frameRate.setMax(0.0); result = SelectSettings(); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_EQ(constraint_factory_.basic().frameRate.name(), result.failed_constraint_name); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, OverconstrainedOnPowerLineFrequency) { constraint_factory_.Reset(); constraint_factory_.basic().googPowerLineFrequency.setExact(123467890); auto result = SelectSettings(); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_EQ(constraint_factory_.basic().googPowerLineFrequency.name(), result.failed_constraint_name); constraint_factory_.Reset(); constraint_factory_.basic().googPowerLineFrequency.setMin(123467890); result = SelectSettings(); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_EQ(constraint_factory_.basic().googPowerLineFrequency.name(), result.failed_constraint_name); constraint_factory_.Reset(); constraint_factory_.basic().googPowerLineFrequency.setMax(-1); result = SelectSettings(); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_EQ(constraint_factory_.basic().googPowerLineFrequency.name(), result.failed_constraint_name); } // The "Mandatory" and "Ideal" tests check that various selection criteria work // for each individual constraint in the basic constraint set. -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryDeviceID) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryDeviceID) { constraint_factory_.Reset(); constraint_factory_.basic().deviceId.setExact( blink::WebString::fromASCII(default_device_->device_id)); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*default_closest_format_, result.settings.format()); + EXPECT_TRUE(result.HasValue()); + EXPECT_EQ(default_device_->device_id, result.device_id); + EXPECT_EQ(*default_closest_format_, result.Format()); EXPECT_EQ(media::PowerLineFrequency::FREQUENCY_DEFAULT, - result.settings.power_line_frequency()); + result.PowerLineFrequency()); constraint_factory_.basic().deviceId.setExact( blink::WebString::fromASCII(low_res_device_->device_id)); result = SelectSettings(); - EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*low_res_closest_format_, result.settings.format()); + EXPECT_EQ(low_res_device_->device_id, result.device_id); + EXPECT_EQ(*low_res_closest_format_, result.Format()); EXPECT_EQ(media::PowerLineFrequency::FREQUENCY_DEFAULT, - result.settings.power_line_frequency()); + result.PowerLineFrequency()); constraint_factory_.basic().deviceId.setExact( blink::WebString::fromASCII(high_res_device_->device_id)); result = SelectSettings(); - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*high_res_closest_format_, result.settings.format()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(*high_res_closest_format_, result.Format()); EXPECT_EQ(media::PowerLineFrequency::FREQUENCY_DEFAULT, - result.settings.power_line_frequency()); + result.PowerLineFrequency()); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryFacingMode) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryFacingMode) { constraint_factory_.Reset(); constraint_factory_.basic().facingMode.setExact( blink::WebString::fromASCII("environment")); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - EXPECT_EQ(::mojom::FacingMode::ENVIRONMENT, result.settings.facing_mode()); + EXPECT_TRUE(result.HasValue()); + EXPECT_EQ(::mojom::FacingMode::ENVIRONMENT, result.facing_mode); // Only the low-res device supports environment facing mode. Should select // default settings for everything else. - EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*low_res_closest_format_, result.settings.format()); + EXPECT_EQ(low_res_device_->device_id, result.device_id); + EXPECT_EQ(*low_res_closest_format_, result.Format()); EXPECT_EQ(media::PowerLineFrequency::FREQUENCY_DEFAULT, - result.settings.power_line_frequency()); + result.PowerLineFrequency()); constraint_factory_.basic().facingMode.setExact( blink::WebString::fromASCII("user")); result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - EXPECT_EQ(::mojom::FacingMode::USER, result.settings.facing_mode()); + EXPECT_TRUE(result.HasValue()); + EXPECT_EQ(::mojom::FacingMode::USER, result.facing_mode); // Only the high-res device supports user facing mode. Should select default // settings for everything else. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*high_res_closest_format_, result.settings.format()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(*high_res_closest_format_, result.Format()); EXPECT_EQ(media::PowerLineFrequency::FREQUENCY_DEFAULT, - result.settings.power_line_frequency()); + result.PowerLineFrequency()); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryVideoKind) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryVideoKind) { constraint_factory_.Reset(); constraint_factory_.basic().videoKind.setExact( blink::WebString::fromASCII("depth")); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - EXPECT_EQ(kDeviceID4, result.settings.device_id()); - EXPECT_EQ(media::PIXEL_FORMAT_Y16, result.settings.format().pixel_format); + EXPECT_TRUE(result.HasValue()); + EXPECT_EQ(kDeviceID4, result.device_id); + EXPECT_EQ(media::PIXEL_FORMAT_Y16, result.Format().pixel_format); constraint_factory_.basic().videoKind.setExact( blink::WebString::fromASCII("color")); result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); + EXPECT_TRUE(result.HasValue()); + EXPECT_EQ(default_device_->device_id, result.device_id); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryPowerLineFrequency) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryPowerLineFrequency) { constraint_factory_.Reset(); const media::PowerLineFrequency kPowerLineFrequencies[] = { media::PowerLineFrequency::FREQUENCY_50HZ, @@ -375,73 +375,73 @@ constraint_factory_.basic().googPowerLineFrequency.setExact( static_cast<long>(power_line_frequency)); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - EXPECT_EQ(power_line_frequency, result.settings.power_line_frequency()); + EXPECT_TRUE(result.HasValue()); + EXPECT_EQ(power_line_frequency, result.PowerLineFrequency()); // The default device and settings closest to the default should be // selected. - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); - EXPECT_EQ(default_device_->facing_mode, result.settings.facing_mode()); - EXPECT_EQ(*default_closest_format_, result.settings.format()); + EXPECT_EQ(default_device_->device_id, result.device_id); + EXPECT_EQ(default_device_->facing_mode, result.facing_mode); + EXPECT_EQ(*default_closest_format_, result.Format()); } } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryExactHeight) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryExactHeight) { constraint_factory_.Reset(); const int kHeight = MediaStreamVideoSource::kDefaultHeight; constraint_factory_.basic().height.setExact(kHeight); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // All devices in |capabilities_| support the requested height. The algorithm // should prefer the first device that supports the requested height natively, // which is the low-res device. - EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(kHeight, result.settings.GetHeight()); + EXPECT_EQ(low_res_device_->device_id, result.device_id); + EXPECT_EQ(kHeight, result.Height()); const int kLargeHeight = 1500; constraint_factory_.basic().height.setExact(kLargeHeight); result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // Only the high-res device at the highest resolution supports the requested // height, even if not natively. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*high_res_highest_format_, result.settings.format()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(*high_res_highest_format_, result.Format()); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryMinHeight) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryMinHeight) { constraint_factory_.Reset(); const int kHeight = MediaStreamVideoSource::kDefaultHeight; constraint_factory_.basic().height.setMin(kHeight); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // All devices in |capabilities_| support the requested height range. The // algorithm should prefer the default device. - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); - EXPECT_LE(kHeight, result.settings.GetHeight()); + EXPECT_EQ(default_device_->device_id, result.device_id); + EXPECT_LE(kHeight, result.Height()); const int kLargeHeight = 1500; constraint_factory_.basic().height.setMin(kLargeHeight); result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // Only the high-res device at the highest resolution supports the requested // height range. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*high_res_highest_format_, result.settings.format()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(*high_res_highest_format_, result.Format()); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryMaxHeight) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryMaxHeight) { constraint_factory_.Reset(); const int kLowHeight = 20; constraint_factory_.basic().height.setMax(kLowHeight); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // All devices in |capabilities_| support the requested height range. The // algorithm should prefer the settings that natively exceed the requested // maximum by the lowest amount. In this case it is the low-res device. - EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(low_res_device_->formats[0], result.settings.format()); + EXPECT_EQ(low_res_device_->device_id, result.device_id); + EXPECT_EQ(low_res_device_->formats[0], result.Format()); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryHeightRange) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryHeightRange) { constraint_factory_.Reset(); { const int kMinHeight = 480; @@ -449,15 +449,15 @@ constraint_factory_.basic().height.setMin(kMinHeight); constraint_factory_.basic().height.setMax(kMaxHeight); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - EXPECT_GE(result.settings.GetHeight(), kMinHeight); - EXPECT_LE(result.settings.GetHeight(), kMaxHeight); + EXPECT_TRUE(result.HasValue()); + EXPECT_GE(result.Height(), kMinHeight); + EXPECT_LE(result.Height(), kMaxHeight); // All devices in |capabilities_| support the constraint range. The // algorithm should prefer the default device since it has at least one // native format (the closest-to-default format) included in the requested // range. - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*default_closest_format_, result.settings.format()); + EXPECT_EQ(default_device_->device_id, result.device_id); + EXPECT_EQ(*default_closest_format_, result.Format()); } { @@ -466,15 +466,15 @@ constraint_factory_.basic().height.setMin(kMinHeight); constraint_factory_.basic().height.setMax(kMaxHeight); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - EXPECT_GE(result.settings.GetHeight(), kMinHeight); - EXPECT_LE(result.settings.GetHeight(), kMaxHeight); + EXPECT_TRUE(result.HasValue()); + EXPECT_GE(result.Height(), kMinHeight); + EXPECT_LE(result.Height(), kMaxHeight); // In this case, the algorithm should prefer the low-res device since it is // the first device with a native format (800x600) included in the requested // range. - EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(800, result.settings.GetWidth()); - EXPECT_EQ(600, result.settings.GetHeight()); + EXPECT_EQ(low_res_device_->device_id, result.device_id); + EXPECT_EQ(800, result.Width()); + EXPECT_EQ(600, result.Height()); } { @@ -483,132 +483,132 @@ constraint_factory_.basic().height.setMin(kMinHeight); constraint_factory_.basic().height.setMax(kMaxHeight); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - EXPECT_GE(result.settings.GetHeight(), kMinHeight); - EXPECT_LE(result.settings.GetHeight(), kMaxHeight); + EXPECT_TRUE(result.HasValue()); + EXPECT_GE(result.Height(), kMinHeight); + EXPECT_LE(result.Height(), kMaxHeight); // In this case, the algorithm should prefer the high-res device since it is // the only device with a native format (1280x720) included in the requested // range. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(1280, result.settings.GetWidth()); - EXPECT_EQ(720, result.settings.GetHeight()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(1280, result.Width()); + EXPECT_EQ(720, result.Height()); } } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, IdealHeight) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, IdealHeight) { constraint_factory_.Reset(); { const int kIdealHeight = 480; constraint_factory_.basic().height.setIdeal(kIdealHeight); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // The algorithm should select the first device that supports the ideal // height natively. - EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(kIdealHeight, result.settings.GetHeight()); + EXPECT_EQ(low_res_device_->device_id, result.device_id); + EXPECT_EQ(kIdealHeight, result.Height()); } { const int kIdealHeight = 481; constraint_factory_.basic().height.setIdeal(kIdealHeight); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // In this case, the default device is selected because it can satisfy the // ideal at a lower cost than the other devices (500 vs 600 or 720). // Note that a native resolution of 480 is further from the ideal than // 500 cropped to 480. - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*default_closest_format_, result.settings.format()); + EXPECT_EQ(default_device_->device_id, result.device_id); + EXPECT_EQ(*default_closest_format_, result.Format()); } { const int kIdealHeight = 1079; constraint_factory_.basic().height.setIdeal(kIdealHeight); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // In this case, the high-res device has two configurations that satisfy // the ideal value (1920x1080 and 2304x1536). Select the one with shortest // native distance to the ideal value (1920x1080). - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(1920, result.settings.GetWidth()); - EXPECT_EQ(1080, result.settings.GetHeight()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(1920, result.Width()); + EXPECT_EQ(1080, result.Height()); } { const int kIdealHeight = 1200; constraint_factory_.basic().height.setIdeal(kIdealHeight); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // The algorithm must the select the only device that can satisfy the ideal, // which is the high-res device at the highest resolution. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*high_res_highest_format_, result.settings.format()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(*high_res_highest_format_, result.Format()); } } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryExactWidth) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryExactWidth) { constraint_factory_.Reset(); const int kWidth = 640; constraint_factory_.basic().width.setExact(kWidth); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // All devices in |capabilities_| support the requested width. The algorithm // should prefer the first device that supports the requested width natively, // which is the low-res device. - EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(kWidth, result.settings.GetWidth()); + EXPECT_EQ(low_res_device_->device_id, result.device_id); + EXPECT_EQ(kWidth, result.Width()); const int kLargeWidth = 2000; constraint_factory_.basic().width.setExact(kLargeWidth); result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - EXPECT_LE(kLargeWidth, result.settings.GetWidth()); + EXPECT_TRUE(result.HasValue()); + EXPECT_LE(kLargeWidth, result.Width()); // Only the high-res device at the highest resolution supports the requested // width, even if not natively. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*high_res_highest_format_, result.settings.format()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(*high_res_highest_format_, result.Format()); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryMinWidth) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryMinWidth) { constraint_factory_.Reset(); const int kWidth = 640; constraint_factory_.basic().width.setMin(kWidth); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // All devices in |capabilities_| support the requested width range. The // algorithm should prefer the default device at 1000x1000, which is the // first configuration that satisfies the minimum width. - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); - EXPECT_LE(kWidth, result.settings.GetWidth()); - EXPECT_EQ(1000, result.settings.GetWidth()); - EXPECT_EQ(1000, result.settings.GetHeight()); + EXPECT_EQ(default_device_->device_id, result.device_id); + EXPECT_LE(kWidth, result.Width()); + EXPECT_EQ(1000, result.Width()); + EXPECT_EQ(1000, result.Height()); const int kLargeWidth = 2000; constraint_factory_.basic().width.setMin(kLargeWidth); result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // Only the high-res device at the highest resolution supports the requested // minimum width. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_LE(kLargeWidth, result.settings.GetWidth()); - EXPECT_EQ(*high_res_highest_format_, result.settings.format()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_LE(kLargeWidth, result.Width()); + EXPECT_EQ(*high_res_highest_format_, result.Format()); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryMaxWidth) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryMaxWidth) { constraint_factory_.Reset(); const int kLowWidth = 30; constraint_factory_.basic().width.setMax(kLowWidth); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // All devices in |capabilities_| support the requested width range. The // algorithm should prefer the settings that natively exceed the requested // maximum by the lowest amount. In this case it is the low-res device at its // lowest resolution. - EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(low_res_device_->formats[0], result.settings.format()); + EXPECT_EQ(low_res_device_->device_id, result.device_id); + EXPECT_EQ(low_res_device_->formats[0], result.Format()); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryWidthRange) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryWidthRange) { constraint_factory_.Reset(); { const int kMinWidth = 640; @@ -616,15 +616,15 @@ constraint_factory_.basic().width.setMin(kMinWidth); constraint_factory_.basic().width.setMax(kMaxWidth); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - EXPECT_GE(result.settings.GetWidth(), kMinWidth); - EXPECT_LE(result.settings.GetWidth(), kMaxWidth); + EXPECT_TRUE(result.HasValue()); + EXPECT_GE(result.Width(), kMinWidth); + EXPECT_LE(result.Width(), kMaxWidth); // All devices in |capabilities_| support the constraint range. The // algorithm should prefer the default device since it has at least one // native format (1000x1000) included in the requested range. - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); - EXPECT_EQ(1000, result.settings.GetWidth()); - EXPECT_EQ(1000, result.settings.GetHeight()); + EXPECT_EQ(default_device_->device_id, result.device_id); + EXPECT_EQ(1000, result.Width()); + EXPECT_EQ(1000, result.Height()); } { @@ -633,15 +633,15 @@ constraint_factory_.basic().width.setMin(kMinWidth); constraint_factory_.basic().width.setMax(kMaxWidth); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - EXPECT_GE(result.settings.GetWidth(), kMinWidth); - EXPECT_LE(result.settings.GetWidth(), kMaxWidth); + EXPECT_TRUE(result.HasValue()); + EXPECT_GE(result.Width(), kMinWidth); + EXPECT_LE(result.Width(), kMaxWidth); // In this case, the algorithm should prefer the low-res device since it is // the first device with a native format (800x600) included in the requested // range. - EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(800, result.settings.GetWidth()); - EXPECT_EQ(600, result.settings.GetHeight()); + EXPECT_EQ(low_res_device_->device_id, result.device_id); + EXPECT_EQ(800, result.Width()); + EXPECT_EQ(600, result.Height()); } { @@ -650,135 +650,134 @@ constraint_factory_.basic().width.setMin(kMinWidth); constraint_factory_.basic().width.setMax(kMaxWidth); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - EXPECT_GE(result.settings.GetWidth(), kMinWidth); - EXPECT_LE(result.settings.GetWidth(), kMaxWidth); + EXPECT_TRUE(result.HasValue()); + EXPECT_GE(result.Width(), kMinWidth); + EXPECT_LE(result.Width(), kMaxWidth); // In this case, the algorithm should prefer the high-res device since it is // the only device with a native format (1920x1080) included in the // requested range. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(1920, result.settings.GetWidth()); - EXPECT_EQ(1080, result.settings.GetHeight()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(1920, result.Width()); + EXPECT_EQ(1080, result.Height()); } } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, IdealWidth) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, IdealWidth) { constraint_factory_.Reset(); { const int kIdealWidth = 320; constraint_factory_.basic().width.setIdeal(kIdealWidth); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // The algorithm should select the first device that supports the ideal // width natively, which is the low-res device at 320x240. - EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(kIdealWidth, result.settings.GetWidth()); + EXPECT_EQ(low_res_device_->device_id, result.device_id); + EXPECT_EQ(kIdealWidth, result.Width()); } { const int kIdealWidth = 321; constraint_factory_.basic().width.setIdeal(kIdealWidth); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // In this case, the default device is selected because it can satisfy the // ideal at a lower cost than the other devices (500 vs 640). // Note that a native resolution of 320 is further from the ideal value of // 321 than 500 cropped to 321. - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*default_closest_format_, result.settings.format()); + EXPECT_EQ(default_device_->device_id, result.device_id); + EXPECT_EQ(*default_closest_format_, result.Format()); } { const int kIdealWidth = 2000; constraint_factory_.basic().width.setIdeal(kIdealWidth); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // The algorithm must the select the only device that can satisfy the ideal. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*high_res_highest_format_, result.settings.format()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(*high_res_highest_format_, result.Format()); } { const int kIdealWidth = 3000; constraint_factory_.basic().width.setIdeal(kIdealWidth); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // The algorithm must the select the device and setting with less distance // to the ideal. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*high_res_highest_format_, result.settings.format()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(*high_res_highest_format_, result.Format()); } } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryExactFrameRate) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryExactFrameRate) { constraint_factory_.Reset(); const double kFrameRate = MediaStreamVideoSource::kDefaultFrameRate; constraint_factory_.basic().frameRate.setExact(kFrameRate); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // All devices in |capabilities_| support the requested frame rate. The // algorithm should prefer the first device that supports the requested frame // rate natively, which is the low-res device at 640x480x30Hz. - EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(kFrameRate, result.settings.GetFrameRate()); - EXPECT_EQ(640, result.settings.GetWidth()); - EXPECT_EQ(480, result.settings.GetHeight()); + EXPECT_EQ(low_res_device_->device_id, result.device_id); + EXPECT_EQ(kFrameRate, result.FrameRate()); + EXPECT_EQ(640, result.Width()); + EXPECT_EQ(480, result.Height()); const double kLargeFrameRate = 50; constraint_factory_.basic().frameRate.setExact(kLargeFrameRate); result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // Only the high-res device supports the requested frame rate, even if not // natively. The least expensive configuration that supports the requested // frame rate is 1280x720x60Hz. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(60.0, result.settings.GetFrameRate()); - EXPECT_EQ(1280, result.settings.GetWidth()); - EXPECT_EQ(720, result.settings.GetHeight()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(60.0, result.FrameRate()); + EXPECT_EQ(1280, result.Width()); + EXPECT_EQ(720, result.Height()); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryMinFrameRate) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryMinFrameRate) { constraint_factory_.Reset(); const double kFrameRate = MediaStreamVideoSource::kDefaultFrameRate; constraint_factory_.basic().frameRate.setMin(kFrameRate); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // All devices in |capabilities_| support the requested frame-rate range. The // algorithm should prefer the default device. - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); + EXPECT_EQ(default_device_->device_id, result.device_id); // The format closest to the default satisfies the constraint. - EXPECT_EQ(*default_closest_format_, result.settings.format()); + EXPECT_EQ(*default_closest_format_, result.Format()); const double kLargeFrameRate = 50; constraint_factory_.basic().frameRate.setMin(kLargeFrameRate); result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // Only the high-res device supports the requested frame-rate range. // The least expensive configuration is 1280x720x60Hz. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_LE(kLargeFrameRate, result.settings.GetFrameRate()); - EXPECT_EQ(1280, result.settings.GetWidth()); - EXPECT_EQ(720, result.settings.GetHeight()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_LE(kLargeFrameRate, result.FrameRate()); + EXPECT_EQ(1280, result.Width()); + EXPECT_EQ(720, result.Height()); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryMaxFrameRate) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryMaxFrameRate) { constraint_factory_.Reset(); const double kLowFrameRate = 10; constraint_factory_.basic().frameRate.setMax(kLowFrameRate); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // All devices in |capabilities_| support the requested frame-rate range. The // algorithm should prefer the settings that natively exceed the requested // maximum by the lowest amount. In this case it is the high-res device with // default resolution . - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(kLowFrameRate, result.settings.GetFrameRate()); - EXPECT_EQ(MediaStreamVideoSource::kDefaultHeight, - result.settings.GetHeight()); - EXPECT_EQ(MediaStreamVideoSource::kDefaultWidth, result.settings.GetWidth()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(kLowFrameRate, result.FrameRate()); + EXPECT_EQ(MediaStreamVideoSource::kDefaultHeight, result.Height()); + EXPECT_EQ(MediaStreamVideoSource::kDefaultWidth, result.Width()); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryFrameRateRange) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryFrameRateRange) { constraint_factory_.Reset(); { const double kMinFrameRate = 10; @@ -786,14 +785,14 @@ constraint_factory_.basic().frameRate.setMin(kMinFrameRate); constraint_factory_.basic().frameRate.setMax(kMaxFrameRate); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - EXPECT_LE(kMinFrameRate, result.settings.GetFrameRate()); - EXPECT_GE(kMaxFrameRate, result.settings.GetFrameRate()); + EXPECT_TRUE(result.HasValue()); + EXPECT_LE(kMinFrameRate, result.FrameRate()); + EXPECT_GE(kMaxFrameRate, result.FrameRate()); // All devices in |capabilities_| support the constraint range. The // algorithm should prefer the default device since its closest-to-default // format has a frame rate included in the requested range. - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*default_closest_format_, result.settings.format()); + EXPECT_EQ(default_device_->device_id, result.device_id); + EXPECT_EQ(*default_closest_format_, result.Format()); } { @@ -802,14 +801,14 @@ constraint_factory_.basic().frameRate.setMin(kMinFrameRate); constraint_factory_.basic().frameRate.setMax(kMaxFrameRate); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - EXPECT_GE(result.settings.GetFrameRate(), kMinFrameRate); - EXPECT_LE(result.settings.GetFrameRate(), kMaxFrameRate); + EXPECT_TRUE(result.HasValue()); + EXPECT_GE(result.FrameRate(), kMinFrameRate); + EXPECT_LE(result.FrameRate(), kMaxFrameRate); // In this case, the algorithm should prefer the low-res device since it is // the first device with a native frame rate included in the requested // range. The default resolution should be preferred as secondary criterion. - EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*low_res_closest_format_, result.settings.format()); + EXPECT_EQ(low_res_device_->device_id, result.device_id); + EXPECT_EQ(*low_res_closest_format_, result.Format()); } { @@ -818,86 +817,86 @@ constraint_factory_.basic().frameRate.setMin(kMinFrameRate); constraint_factory_.basic().frameRate.setMax(kMaxFrameRate); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - EXPECT_GE(result.settings.GetFrameRate(), kMinFrameRate); - EXPECT_LE(result.settings.GetFrameRate(), kMaxFrameRate); + EXPECT_TRUE(result.HasValue()); + EXPECT_GE(result.FrameRate(), kMinFrameRate); + EXPECT_LE(result.FrameRate(), kMaxFrameRate); // In this case, the algorithm should prefer the high-res device since it is // the only device with a native format included in the requested range. // The 1280x720 resolution should be selected due to closeness to default // settings, which is the second tie-breaker criterion that applies. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(1280, result.settings.GetWidth()); - EXPECT_EQ(720, result.settings.GetHeight()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(1280, result.Width()); + EXPECT_EQ(720, result.Height()); } } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, IdealFrameRate) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, IdealFrameRate) { constraint_factory_.Reset(); { const double kIdealFrameRate = MediaStreamVideoSource::kDefaultFrameRate; constraint_factory_.basic().frameRate.setIdeal(kIdealFrameRate); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // The algorithm should select the first configuration that supports the // ideal frame rate natively, which is the low-res device. Default // resolution should be selected as secondary criterion. - EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*low_res_closest_format_, result.settings.format()); + EXPECT_EQ(low_res_device_->device_id, result.device_id); + EXPECT_EQ(*low_res_closest_format_, result.Format()); } { const double kIdealFrameRate = 31; constraint_factory_.basic().frameRate.setIdeal(kIdealFrameRate); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // In this case, the default device is selected because it can satisfy the // ideal at a lower cost than the other devices (40 vs 60). // Note that a native frame rate of 30 is further from the ideal than // 31 adjusted to 30. - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*default_closest_format_, result.settings.format()); + EXPECT_EQ(default_device_->device_id, result.device_id); + EXPECT_EQ(*default_closest_format_, result.Format()); } { const double kIdealFrameRate = 55; constraint_factory_.basic().frameRate.setIdeal(kIdealFrameRate); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // The high-res device format 1280x720x60.0 must be selected because its // frame rate can satisfy the ideal frame rate and has resolution closest // to the default. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(1280, result.settings.GetWidth()); - EXPECT_EQ(720, result.settings.GetHeight()); - EXPECT_EQ(60, result.settings.GetFrameRate()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(1280, result.Width()); + EXPECT_EQ(720, result.Height()); + EXPECT_EQ(60, result.FrameRate()); } { const double kIdealFrameRate = 100; constraint_factory_.basic().frameRate.setIdeal(kIdealFrameRate); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // The algorithm must select settings with frame rate closest to the ideal. // The high-res device format 1280x720x60.0 must be selected because its // frame rate it closest to the ideal value and it has resolution closest to // the default. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(1280, result.settings.GetWidth()); - EXPECT_EQ(720, result.settings.GetHeight()); - EXPECT_EQ(60, result.settings.GetFrameRate()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(1280, result.Width()); + EXPECT_EQ(720, result.Height()); + EXPECT_EQ(60, result.FrameRate()); } } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryExactAspectRatio) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryExactAspectRatio) { constraint_factory_.Reset(); const double kAspectRatio = 4.0 / 3.0; constraint_factory_.basic().aspectRatio.setExact(kAspectRatio); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); double min_width = 1.0; - double max_width = result.settings.GetWidth(); + double max_width = result.Width(); double min_height = 1.0; - double max_height = result.settings.GetHeight(); + double max_height = result.Height(); double min_aspect_ratio = min_width / max_height; double max_aspect_ratio = max_width / min_height; // The requested aspect ratio must be within the supported range. @@ -906,22 +905,22 @@ // All devices in |capabilities_| support the requested aspect ratio. // The algorithm should prefer the first device that supports the requested // aspect ratio. - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*default_closest_format_, result.settings.format()); + EXPECT_EQ(default_device_->device_id, result.device_id); + EXPECT_EQ(*default_closest_format_, result.Format()); - const long kMinWidth = 500; - const long kMaxWidth = 1000; - const long kMaxHeight = 500; + const int kMinWidth = 500; + const int kMaxWidth = 1000; + const int kMaxHeight = 500; constraint_factory_.basic().height.setMax(kMaxHeight); constraint_factory_.basic().width.setMin(kMinWidth); constraint_factory_.basic().width.setMax(kMaxWidth); constraint_factory_.basic().aspectRatio.setExact(kAspectRatio); result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - min_width = std::max(1L, kMinWidth); - max_width = std::min(result.settings.GetWidth(), kMaxWidth); + EXPECT_TRUE(result.HasValue()); + min_width = std::max(1, kMinWidth); + max_width = std::min(result.Width(), kMaxWidth); min_height = 1.0; - max_height = std::min(result.settings.GetHeight(), kMaxHeight); + max_height = std::min(result.Height(), kMaxHeight); min_aspect_ratio = min_width / max_height; max_aspect_ratio = max_width / min_height; // The requested aspect ratio must be within the supported range. @@ -929,21 +928,21 @@ EXPECT_LE(kAspectRatio, max_aspect_ratio); // The default device can support the requested aspect ratio with the default // settings (500x500) using cropping. - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*default_closest_format_, result.settings.format()); + EXPECT_EQ(default_device_->device_id, result.device_id); + EXPECT_EQ(*default_closest_format_, result.Format()); - const long kMinHeight = 480; + const int kMinHeight = 480; constraint_factory_.basic().height.setMin(kMinHeight); constraint_factory_.basic().height.setMax(kMaxHeight); constraint_factory_.basic().width.setMin(kMinWidth); constraint_factory_.basic().width.setMax(kMaxWidth); constraint_factory_.basic().aspectRatio.setExact(kAspectRatio); result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - min_width = std::max(1L, kMinWidth); - max_width = std::min(result.settings.GetWidth(), kMaxWidth); - min_height = std::max(1L, kMinHeight); - max_height = std::min(result.settings.GetHeight(), kMaxHeight); + EXPECT_TRUE(result.HasValue()); + min_width = std::max(1, kMinWidth); + max_width = std::min(result.Width(), kMaxWidth); + min_height = std::max(1, kMinHeight); + max_height = std::min(result.Height(), kMaxHeight); min_aspect_ratio = min_width / max_height; max_aspect_ratio = max_width / min_height; // The requested aspect ratio must be within the supported range. @@ -955,17 +954,17 @@ // resolution of 640x480. Higher resolutions for the default device are more // penalized by the constraints than the default native resolution of the // low-res device. - EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*low_res_closest_format_, result.settings.format()); + EXPECT_EQ(low_res_device_->device_id, result.device_id); + EXPECT_EQ(*low_res_closest_format_, result.Format()); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryMinAspectRatio) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryMinAspectRatio) { constraint_factory_.Reset(); const double kAspectRatio = 4.0 / 3.0; constraint_factory_.basic().aspectRatio.setMin(kAspectRatio); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - double max_width = result.settings.GetWidth(); + EXPECT_TRUE(result.HasValue()); + double max_width = result.Width(); double min_height = 1.0; double max_aspect_ratio = max_width / min_height; // Minimum constraint aspect ratio must be less than or equal to the maximum @@ -974,22 +973,22 @@ // All devices in |capabilities_| support the requested aspect-ratio range. // The algorithm should prefer the first device that supports the requested // aspect-ratio range, which in this case is the default device. - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*default_closest_format_, result.settings.format()); + EXPECT_EQ(default_device_->device_id, result.device_id); + EXPECT_EQ(*default_closest_format_, result.Format()); - const long kMinWidth = 500; - const long kMaxWidth = 1000; - const long kMinHeight = 480; - const long kMaxHeight = 500; + const int kMinWidth = 500; + const int kMaxWidth = 1000; + const int kMinHeight = 480; + const int kMaxHeight = 500; constraint_factory_.basic().width.setMin(kMinWidth); constraint_factory_.basic().width.setMax(kMaxWidth); constraint_factory_.basic().height.setMin(kMinHeight); constraint_factory_.basic().height.setMax(kMaxHeight); constraint_factory_.basic().aspectRatio.setMin(kAspectRatio); result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - max_width = std::min(result.settings.GetWidth(), kMaxWidth); - min_height = std::max(1L, kMinHeight); + EXPECT_TRUE(result.HasValue()); + max_width = std::min(result.Width(), kMaxWidth); + min_height = std::max(1, kMinHeight); max_aspect_ratio = max_width / min_height; // Minimum constraint aspect ratio must be less than or equal to the minimum // supported by the source. @@ -1000,18 +999,18 @@ // resolution of 640x480. // Higher resolutions for the default device are more penalized by the // constraints than the default native resolution of the low-res device. - EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*low_res_closest_format_, result.settings.format()); + EXPECT_EQ(low_res_device_->device_id, result.device_id); + EXPECT_EQ(*low_res_closest_format_, result.Format()); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryMaxAspectRatio) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryMaxAspectRatio) { constraint_factory_.Reset(); const double kAspectRatio = 0.5; constraint_factory_.basic().aspectRatio.setMax(kAspectRatio); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); double min_width = 1.0; - double max_height = result.settings.GetHeight(); + double max_height = result.Height(); double min_aspect_ratio = min_width / max_height; // Minimum constraint aspect ratio must be less than or equal to the maximum // supported by the source. @@ -1019,20 +1018,20 @@ // All devices in |capabilities_| support the requested aspect-ratio range. // The algorithm should prefer the first device that supports the requested // aspect-ratio range, which in this case is the default device. - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*default_closest_format_, result.settings.format()); + EXPECT_EQ(default_device_->device_id, result.device_id); + EXPECT_EQ(*default_closest_format_, result.Format()); - const long kExactWidth = 360; - const long kMinHeight = 360; - const long kMaxHeight = 720; + const int kExactWidth = 360; + const int kMinHeight = 360; + const int kMaxHeight = 720; constraint_factory_.basic().width.setExact(kExactWidth); constraint_factory_.basic().height.setMin(kMinHeight); constraint_factory_.basic().height.setMax(kMaxHeight); constraint_factory_.basic().aspectRatio.setMax(kAspectRatio); result = SelectSettings(); - EXPECT_TRUE(result.has_value()); - min_width = std::max(1L, kExactWidth); - max_height = std::min(result.settings.GetHeight(), kMaxHeight); + EXPECT_TRUE(result.HasValue()); + min_width = std::max(1, kExactWidth); + max_height = std::min(result.Height(), kMaxHeight); min_aspect_ratio = min_width / max_height; // Minimum constraint aspect ratio must be less than or equal to the minimum // supported by the source. @@ -1043,12 +1042,12 @@ // The high-res device with a native resolution of 1280x720 can support // 360x720 with cropping with less penalty than the default device at // 1000x1000. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(1280, result.settings.GetWidth()); - EXPECT_EQ(720, result.settings.GetHeight()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(1280, result.Width()); + EXPECT_EQ(720, result.Height()); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryAspectRatioRange) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryAspectRatioRange) { constraint_factory_.Reset(); { const double kMinAspectRatio = 0.5; @@ -1057,11 +1056,11 @@ constraint_factory_.basic().aspectRatio.setMin(kMinAspectRatio); constraint_factory_.basic().aspectRatio.setMax(kMaxAspectRatio); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); double min_width = 1.0; - double max_width = result.settings.GetWidth(); + double max_width = result.Width(); double min_height = 1.0; - double max_height = result.settings.GetHeight(); + double max_height = result.Height(); double min_aspect_ratio = min_width / max_height; double max_aspect_ratio = max_width / min_height; // Constraint aspect-ratio range must have nonempty intersection with @@ -1071,8 +1070,8 @@ // All devices in |capabilities_| support the requested aspect-ratio range. // The algorithm should prefer the first device that supports the requested // aspect-ratio range, which in this case is the default device. - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*default_closest_format_, result.settings.format()); + EXPECT_EQ(default_device_->device_id, result.device_id); + EXPECT_EQ(*default_closest_format_, result.Format()); } { @@ -1085,11 +1084,11 @@ constraint_factory_.basic().aspectRatio.setMin(kMinAspectRatio); constraint_factory_.basic().aspectRatio.setMax(kMaxAspectRatio); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); double min_width = 1.0; - double max_width = result.settings.GetWidth(); + double max_width = result.Width(); double min_height = 1.0; - double max_height = result.settings.GetHeight(); + double max_height = result.Height(); double min_aspect_ratio = min_width / max_height; double max_aspect_ratio = max_width / min_height; // Constraint aspect-ratio range must have nonempty intersection with @@ -1098,23 +1097,23 @@ EXPECT_GE(kMaxAspectRatio, min_aspect_ratio); // The only device that supports the resolution and aspect ratio constraint // is the high-res device. The 1920x1080 is the least expensive format. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(1920, result.settings.GetWidth()); - EXPECT_EQ(1080, result.settings.GetHeight()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(1920, result.Width()); + EXPECT_EQ(1080, result.Height()); } } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, IdealAspectRatio) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, IdealAspectRatio) { constraint_factory_.Reset(); { const double kIdealAspectRatio = 0.5; constraint_factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); double min_width = 1.0; - double max_width = result.settings.GetWidth(); + double max_width = result.Width(); double min_height = 1.0; - double max_height = result.settings.GetHeight(); + double max_height = result.Height(); double min_aspect_ratio = min_width / max_height; double max_aspect_ratio = max_width / min_height; // All devices in |capabilities_| support the ideal aspect-ratio. @@ -1122,43 +1121,43 @@ // settings. EXPECT_LE(kIdealAspectRatio, max_aspect_ratio); EXPECT_GE(kIdealAspectRatio, min_aspect_ratio); - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*default_closest_format_, result.settings.format()); + EXPECT_EQ(default_device_->device_id, result.device_id); + EXPECT_EQ(*default_closest_format_, result.Format()); } { const double kIdealAspectRatio = 1500.0; constraint_factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // The only device that supports the ideal aspect ratio is the high-res // device. The least expensive way to support it with the 1920x1080 format // cropped to 1500x1. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(1920, result.settings.GetWidth()); - EXPECT_EQ(1080, result.settings.GetHeight()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(1920, result.Width()); + EXPECT_EQ(1080, result.Height()); } { const double kIdealAspectRatio = 2000.0; constraint_factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // The only device that supports the ideal aspect ratio is the high-res // device with its highest resolution, cropped to 2000x1. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*high_res_highest_format_, result.settings.format()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(*high_res_highest_format_, result.Format()); } { const double kIdealAspectRatio = 4000.0; constraint_factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // The configuration closest to the ideal aspect ratio is is the high-res // device with its highest resolution, cropped to 2304x1. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*high_res_highest_format_, result.settings.format()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(*high_res_highest_format_, result.Format()); } { @@ -1166,13 +1165,13 @@ constraint_factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio); constraint_factory_.basic().height.setExact(400); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // The first device to support the ideal aspect ratio and the resolution // constraint is the low-res device. The 800x600 format cropped to 800x400 // is the lest expensive way to achieve it. - EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(800, result.settings.GetWidth()); - EXPECT_EQ(600, result.settings.GetHeight()); + EXPECT_EQ(low_res_device_->device_id, result.device_id); + EXPECT_EQ(800, result.Width()); + EXPECT_EQ(600, result.Height()); } { @@ -1180,19 +1179,19 @@ constraint_factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio); constraint_factory_.basic().height.setExact(400); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // The only device that supports the ideal aspect ratio and the resolution // constraint is the high-res device. The 1280x720 cropped to 1200x400 is // the lest expensive way to achieve it. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(1280, result.settings.GetWidth()); - EXPECT_EQ(720, result.settings.GetHeight()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(1280, result.Width()); + EXPECT_EQ(720, result.Height()); } } // The "Advanced" tests check selection criteria involving advanced constraint // sets. -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, AdvancedExactResolution) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, AdvancedExactResolution) { { constraint_factory_.Reset(); blink::WebMediaTrackConstraintSet& advanced1 = @@ -1206,62 +1205,62 @@ auto result = SelectSettings(); // No device supports the advanced constraint sets. // Tie-breaker rule that applies is closeness to default settings. - EXPECT_EQ(default_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*default_closest_format_, result.settings.format()); + EXPECT_EQ(default_device_->device_id, result.device_id); + EXPECT_EQ(*default_closest_format_, result.Format()); blink::WebMediaTrackConstraintSet& advanced3 = constraint_factory_.AddAdvanced(); advanced3.width.setExact(1920); advanced3.height.setExact(1080); result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // The high-res device natively supports the third advanced constraint set // and should be selected. // First tie-breaker rule that applies is support for advanced constraints // that appear first. Second tie-breaker rule is custom distance to advanced // constraint sets that appear first. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(1920, result.settings.GetWidth()); - EXPECT_EQ(1080, result.settings.GetHeight()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(1920, result.Width()); + EXPECT_EQ(1080, result.Height()); blink::WebMediaTrackConstraintSet& advanced4 = constraint_factory_.AddAdvanced(); advanced4.width.setExact(640); advanced4.height.setExact(480); result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // First tie-breaker rule that applies is support for advanced constraints // that appear first, which leaves out configurations that only support the // fourth advanced constraint set in favor of configurations that support // the third set. // Second tie-breaker rule is custom distance to advanced constraint sets // that appear first. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(1920, result.settings.GetWidth()); - EXPECT_EQ(1080, result.settings.GetHeight()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(1920, result.Width()); + EXPECT_EQ(1080, result.Height()); constraint_factory_.basic().width.setIdeal(800); constraint_factory_.basic().height.setIdeal(600); result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // The ideal value is supported by the same configuration, so nothing // changes. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(1920, result.settings.GetWidth()); - EXPECT_EQ(1080, result.settings.GetHeight()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(1920, result.Width()); + EXPECT_EQ(1080, result.Height()); constraint_factory_.basic().width.setIdeal(2000); constraint_factory_.basic().height.setIdeal(1500); result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // The closest configuration to the ideal resolution is the high-res device // at the highest resolution. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(*high_res_highest_format_, result.settings.format()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(*high_res_highest_format_, result.Format()); } } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, AdvancedResolutionAndFrameRate) { { constraint_factory_.Reset(); @@ -1277,36 +1276,36 @@ advanced3.width.setExact(2304); advanced3.height.setExact(1536); auto result = SelectSettings(); - EXPECT_TRUE(result.has_value()); + EXPECT_TRUE(result.HasValue()); // The high-res device is the only one that satisfies the first advanced // set. 2304x1536x10.0 satisfies sets 1 and 3, while 1920x1080x60.0 // satisfies sets 1, and 2. The latter must be selected, regardless of // any other criteria. - EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); - EXPECT_EQ(1920, result.settings.GetWidth()); - EXPECT_EQ(1080, result.settings.GetHeight()); - EXPECT_EQ(60.0, result.settings.GetFrameRate()); + EXPECT_EQ(high_res_device_->device_id, result.device_id); + EXPECT_EQ(1920, result.Width()); + EXPECT_EQ(1080, result.Height()); + EXPECT_EQ(60.0, result.FrameRate()); } } // The "NoDevices" tests verify that the algorithm returns the expected result // when there are no candidates to choose from. -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, NoDevicesNoConstraints) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, NoDevicesNoConstraints) { constraint_factory_.Reset(); - VideoCaptureCapabilities capabilities; - auto result = SelectVideoCaptureSourceSettings( + VideoDeviceCaptureCapabilities capabilities; + auto result = SelectVideoDeviceCaptureSourceSettings( capabilities, constraint_factory_.CreateWebMediaConstraints()); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_TRUE(std::string(result.failed_constraint_name).empty()); } -TEST_F(MediaStreamConstraintsUtilVideoSourceTest, NoDevicesWithConstraints) { +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, NoDevicesWithConstraints) { constraint_factory_.Reset(); constraint_factory_.basic().height.setExact(100); - VideoCaptureCapabilities capabilities; - auto result = SelectVideoCaptureSourceSettings( + VideoDeviceCaptureCapabilities capabilities; + auto result = SelectVideoDeviceCaptureSourceSettings( capabilities, constraint_factory_.CreateWebMediaConstraints()); - EXPECT_FALSE(result.has_value()); + EXPECT_FALSE(result.HasValue()); EXPECT_TRUE(std::string(result.failed_constraint_name).empty()); }
diff --git a/content/renderer/media/media_stream_video_source.cc b/content/renderer/media/media_stream_video_source.cc index 0c2dd59..3c962ff0 100644 --- a/content/renderer/media/media_stream_video_source.cc +++ b/content/renderer/media/media_stream_video_source.cc
@@ -13,7 +13,7 @@ #include "base/strings/string_number_conversions.h" #include "base/trace_event/trace_event.h" #include "content/child/child_process.h" -#include "content/renderer/media/media_stream_constraints_util_video_source.h" +#include "content/renderer/media/media_stream_constraints_util_video_device.h" #include "content/renderer/media/media_stream_video_track.h" #include "content/renderer/media/video_track_adapter.h"
diff --git a/content/renderer/media/media_stream_video_track.cc b/content/renderer/media/media_stream_video_track.cc index c6fc030..599018f61 100644 --- a/content/renderer/media/media_stream_video_track.cc +++ b/content/renderer/media/media_stream_video_track.cc
@@ -11,7 +11,7 @@ #include "base/macros.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" -#include "content/renderer/media/media_stream_constraints_util_video_source.h" +#include "content/renderer/media/media_stream_constraints_util_video_device.h" namespace content {
diff --git a/content/renderer/media/user_media_client_impl.cc b/content/renderer/media/user_media_client_impl.cc index 691e768..d8cc904 100644 --- a/content/renderer/media/user_media_client_impl.cc +++ b/content/renderer/media/user_media_client_impl.cc
@@ -26,7 +26,7 @@ #include "content/renderer/media/local_media_stream_audio_source.h" #include "content/renderer/media/media_stream.h" #include "content/renderer/media/media_stream_constraints_util.h" -#include "content/renderer/media/media_stream_constraints_util_video_source.h" +#include "content/renderer/media/media_stream_constraints_util_video_device.h" #include "content/renderer/media/media_stream_dispatcher.h" #include "content/renderer/media/media_stream_video_capturer_source.h" #include "content/renderer/media/media_stream_video_track.h" @@ -366,7 +366,7 @@ DCHECK(controls->video.requested); DCHECK(IsDeviceSource(controls->video.stream_source)); - VideoCaptureCapabilities capabilities; + VideoDeviceCaptureCapabilities capabilities; capabilities.device_capabilities = std::move(video_input_capabilities); capabilities.power_line_capabilities = { media::PowerLineFrequency::FREQUENCY_DEFAULT, @@ -375,7 +375,8 @@ base::PostTaskAndReplyWithResult( worker_task_runner_.get(), FROM_HERE, - base::Bind(&SelectVideoCaptureSourceSettings, std::move(capabilities), + base::Bind(&SelectVideoDeviceCaptureSourceSettings, + std::move(capabilities), user_media_request.videoConstraints()), base::Bind(&UserMediaClientImpl::FinalizeSelectVideoDeviceSourceSettings, weak_factory_.GetWeakPtr(), request_id, user_media_request, @@ -387,10 +388,10 @@ const blink::WebUserMediaRequest& user_media_request, std::unique_ptr<StreamControls> controls, const RequestSettings& request_settings, - const VideoCaptureSourceSelectionResult& selection_result) { + const VideoDeviceCaptureSourceSelectionResult& selection_result) { DCHECK(CalledOnValidThread()); - if (selection_result.has_value()) { - controls->video.device_id = selection_result.settings.device_id(); + if (selection_result.HasValue()) { + controls->video.device_id = selection_result.device_id; } else { // TODO(guidou): Abort the request in all cases where |selection_result| // has no value, as the spec mandates.
diff --git a/content/renderer/media/user_media_client_impl.h b/content/renderer/media/user_media_client_impl.h index db866f2..7c72248 100644 --- a/content/renderer/media/user_media_client_impl.h +++ b/content/renderer/media/user_media_client_impl.h
@@ -39,7 +39,7 @@ class MediaStreamAudioSource; class MediaStreamDispatcher; class MediaStreamVideoSource; -struct VideoCaptureSourceSelectionResult; +struct VideoDeviceCaptureSourceSelectionResult; // UserMediaClientImpl is a delegate for the Media Stream GetUserMedia API. // It ties together WebKit and MediaStreamManager @@ -315,7 +315,7 @@ const blink::WebUserMediaRequest& user_media_request, std::unique_ptr<StreamControls> controls, const RequestSettings& request_settings, - const VideoCaptureSourceSelectionResult& selection_result); + const VideoDeviceCaptureSourceSelectionResult& selection_result); void FinalizeRequestUserMedia( int request_id,
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 59ae8b6..0fdae4b 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -616,6 +616,7 @@ "../browser/media/session/audio_focus_delegate_default_browsertest.cc", "../browser/media/session/media_session_impl_browsertest.cc", "../browser/media/session/media_session_impl_visibility_browsertest.cc", + "../browser/media/session/media_session_service_impl_browsertest.cc", "../browser/media/session/mock_media_session_player_observer.cc", "../browser/media/session/mock_media_session_player_observer.h", "../browser/memory/memory_coordinator_impl_browsertest.cc", @@ -1575,7 +1576,7 @@ "../renderer/media/media_stream_audio_processor_unittest.cc", "../renderer/media/media_stream_audio_unittest.cc", "../renderer/media/media_stream_constraints_util_unittest.cc", - "../renderer/media/media_stream_constraints_util_video_source_unittest.cc", + "../renderer/media/media_stream_constraints_util_video_device_unittest.cc", "../renderer/media/media_stream_dispatcher_unittest.cc", "../renderer/media/media_stream_video_capturer_source_unittest.cc", "../renderer/media/media_stream_video_renderer_sink_unittest.cc",
diff --git a/content/test/data/media/session/embed-unload.html b/content/test/data/media/session/embed-unload.html new file mode 100644 index 0000000..676280f --- /dev/null +++ b/content/test/data/media/session/embed-unload.html
@@ -0,0 +1,7 @@ +<!DOCTYPE html> +<script> +navigator.mediaSession.playbackState = 'playing'; +window.addEventListener('unload', function() { + navigator.mediaSession.playbackState = 'none'; +}); +</script>
diff --git a/content/test/data/media/session/embedder.html b/content/test/data/media/session/embedder.html new file mode 100644 index 0000000..b2577d9b --- /dev/null +++ b/content/test/data/media/session/embedder.html
@@ -0,0 +1,2 @@ +<!DOCTYPE html> +<iframe src=embed-unload.html></iframe>
diff --git a/device/generic_sensor/platform_sensor.cc b/device/generic_sensor/platform_sensor.cc index ab3e1cd6..34afa2d6 100644 --- a/device/generic_sensor/platform_sensor.cc +++ b/device/generic_sensor/platform_sensor.cc
@@ -33,6 +33,10 @@ return GetDefaultConfiguration().frequency(); } +double PlatformSensor::GetMinimumSupportedFrequency() { + return 1.0 / (60 * 60); +} + bool PlatformSensor::StartListening(Client* client, const PlatformSensorConfiguration& config) { DCHECK(clients_.HasObserver(client));
diff --git a/device/generic_sensor/platform_sensor.h b/device/generic_sensor/platform_sensor.h index 62320a5..2df4ade 100644 --- a/device/generic_sensor/platform_sensor.h +++ b/device/generic_sensor/platform_sensor.h
@@ -48,6 +48,10 @@ // The default implementation returns default frequency. virtual double GetMaximumSupportedFrequency(); + // Can be overriden to return the sensor minimum sampling frequency. + // The default implementation returns '1.0 / (60 * 60)', i.e. once per hour. + virtual double GetMinimumSupportedFrequency(); + mojom::SensorType GetType() const; bool StartListening(Client* client,
diff --git a/device/generic_sensor/public/interfaces/sensor_provider.mojom b/device/generic_sensor/public/interfaces/sensor_provider.mojom index 7b89d3aa..8e9a3c2 100644 --- a/device/generic_sensor/public/interfaces/sensor_provider.mojom +++ b/device/generic_sensor/public/interfaces/sensor_provider.mojom
@@ -24,6 +24,9 @@ // capabilities. double maximum_frequency; + // Minimum sampling frequency for the sensor. + double minimum_frequency; + // Each sensor's read buffer contains 4 tightly packed 64-bit floating // point fields (please see sensor_reading.h) and a seqlock, so its size is // 5 * 8 = 40 bytes.
diff --git a/device/generic_sensor/sensor_provider_impl.cc b/device/generic_sensor/sensor_provider_impl.cc index 7322901..8f36c47f 100644 --- a/device/generic_sensor/sensor_provider_impl.cc +++ b/device/generic_sensor/sensor_provider_impl.cc
@@ -95,11 +95,13 @@ init_params->default_configuration = sensor->GetDefaultConfiguration(); double maximum_frequency = sensor->GetMaximumSupportedFrequency(); - DCHECK(maximum_frequency > 0); + DCHECK_GT(maximum_frequency, 0.0); if (maximum_frequency > mojom::SensorConfiguration::kMaxAllowedFrequency) maximum_frequency = mojom::SensorConfiguration::kMaxAllowedFrequency; init_params->maximum_frequency = maximum_frequency; + init_params->minimum_frequency = sensor->GetMinimumSupportedFrequency(); + DCHECK_GT(init_params->minimum_frequency, 0.0); NotifySensorCreated(std::move(init_params), sensor_impl->GetClient(), callback);
diff --git a/extensions/test/extension_test_notification_observer.cc b/extensions/test/extension_test_notification_observer.cc index 8c79ac54..0e4d75d0c 100644 --- a/extensions/test/extension_test_notification_observer.cc +++ b/extensions/test/extension_test_notification_observer.cc
@@ -141,9 +141,6 @@ void ExtensionTestNotificationObserver::Wait() { observer_->Wait(); - // TODO(https://crbug.com/695073): Find out why tests fail without it. - content::RunAllPendingInMessageLoop(); - registrar_.RemoveAll(); observer_.reset(); } @@ -190,15 +187,16 @@ return; condition_ = condition; - base::RunLoop run_loop; - quit_closure_ = run_loop.QuitClosure(); + scoped_refptr<content::MessageLoopRunner> runner( + new content::MessageLoopRunner); + quit_closure_ = runner->QuitClosure(); std::unique_ptr<base::CallbackList<void()>::Subscription> subscription; if (notification_set) { subscription = notification_set->callback_list().Add(base::Bind( &ExtensionTestNotificationObserver::MaybeQuit, base::Unretained(this))); } - run_loop.Run(); + runner->Run(); condition_.Reset(); quit_closure_.Reset();
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn index 22067c0b..f5b45ac 100644 --- a/ios/chrome/browser/BUILD.gn +++ b/ios/chrome/browser/BUILD.gn
@@ -8,19 +8,6 @@ import("//rlz/features/features.gni") import("//third_party/protobuf/proto_library.gni") -declare_args() { - google_test_gaia_client_id = "" - google_test_gaia_client_secret = "" - google_staging_api_url = "" - google_staging_lso_url = "" - google_test_api_url = "" - google_test_lso_url = "" - google_test_oauth_client_id = "" - google_test_oauth_client_secret = "" - google_test_oauth_url = "" - google_test_sync_url = "" -} - source_set("browser") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ @@ -79,7 +66,6 @@ "xcallback_parameters.mm", ] deps = [ - ":google_api_keys_header", ":settings_resources", "//base", "//components/autofill/core/browser", @@ -194,20 +180,6 @@ } } -buildflag_header("google_api_keys_header") { - header = "google_api_keys.h" - flags = [ - "GOOGLE_STAGING_API_URL=\"$google_staging_api_url\"", - "GOOGLE_STAGING_LSO_URL=\"$google_staging_lso_url\"", - "GOOGLE_TEST_API_URL=\"$google_test_api_url\"", - "GOOGLE_TEST_LSO_URL=\"$google_test_lso_url\"", - "GOOGLE_TEST_OAUTH_CLIENT_ID=\"$google_test_oauth_client_id\"", - "GOOGLE_TEST_OAUTH_CLIENT_SECRET=\"$google_test_oauth_client_secret\"", - "GOOGLE_TEST_OAUTH_URL=\"$google_test_oauth_url\"", - "GOOGLE_TEST_SYNC_URL=\"$google_test_sync_url\"", - ] -} - bundle_data("settings_resources") { sources = [ "resources/Settings.bundle/Experimental.plist",
diff --git a/ios/chrome/browser/about_flags.mm b/ios/chrome/browser/about_flags.mm index 5a97a54..b89a3be 100644 --- a/ios/chrome/browser/about_flags.mm +++ b/ios/chrome/browser/about_flags.mm
@@ -28,11 +28,9 @@ #include "components/ntp_tiles/switches.h" #include "components/reading_list/core/reading_list_switches.h" #include "components/strings/grit/components_strings.h" -#include "components/sync/driver/sync_driver_switches.h" -#include "google_apis/gaia/gaia_switches.h" #include "ios/chrome/browser/chrome_switches.h" -#include "ios/chrome/browser/google_api_keys.h" #include "ios/chrome/grit/ios_strings.h" +#include "ios/public/provider/chrome/browser/chrome_browser_provider.h" #include "ios/web/public/user_agent.h" #include "ios/web/public/web_view_creation_util.h" @@ -75,29 +73,6 @@ void AppendSwitchesFromExperimentalSettings(base::CommandLine* command_line) { NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; - // GAIA staging environment. - NSString* kGAIAEnvironment = @"GAIAEnvironment"; - NSString* gaia_environment = [defaults stringForKey:kGAIAEnvironment]; - if ([gaia_environment isEqualToString:@"Staging"]) { - command_line->AppendSwitchASCII(switches::kGoogleApisUrl, - BUILDFLAG(GOOGLE_STAGING_API_URL)); - command_line->AppendSwitchASCII(switches::kLsoUrl, - BUILDFLAG(GOOGLE_STAGING_LSO_URL)); - } else if ([gaia_environment isEqualToString:@"Test"]) { - command_line->AppendSwitchASCII(switches::kGaiaUrl, - BUILDFLAG(GOOGLE_TEST_OAUTH_URL)); - command_line->AppendSwitchASCII(switches::kGoogleApisUrl, - BUILDFLAG(GOOGLE_TEST_API_URL)); - command_line->AppendSwitchASCII(switches::kLsoUrl, - BUILDFLAG(GOOGLE_TEST_LSO_URL)); - command_line->AppendSwitchASCII(switches::kSyncServiceURL, - BUILDFLAG(GOOGLE_TEST_SYNC_URL)); - command_line->AppendSwitchASCII(switches::kOAuth2ClientID, - BUILDFLAG(GOOGLE_TEST_OAUTH_CLIENT_ID)); - command_line->AppendSwitchASCII(switches::kOAuth2ClientSecret, - BUILDFLAG(GOOGLE_TEST_OAUTH_CLIENT_SECRET)); - } - // Populate command line flag for the tab strip auto scroll new tabs // experiment from the configuration plist. if ([defaults boolForKey:@"TabStripAutoScrollNewTabsDisabled"]) @@ -255,6 +230,9 @@ base::CommandLine temp_command_line(flags); command_line->AppendArguments(temp_command_line, false); } + + ios::GetChromeBrowserProvider()->AppendSwitchesFromExperimentalSettings( + defaults, command_line); } bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {
diff --git a/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.h b/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.h index a656e1f..59fe49be 100644 --- a/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.h +++ b/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.h
@@ -15,6 +15,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" +#include "components/metrics/metrics_log_uploader.h" #include "components/metrics/metrics_service_client.h" #include "components/metrics/profiler/tracking_synchronizer_observer.h" #include "components/omnibox/browser/omnibox_event_global_tracker.h" @@ -73,6 +74,7 @@ std::unique_ptr<metrics::MetricsLogUploader> CreateUploader( const std::string& server_url, const std::string& mime_type, + metrics::MetricsLogUploader::MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete) override; base::TimeDelta GetStandardUploadInterval() override; base::string16 GetRegistryBackupKey() override;
diff --git a/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm b/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm index 22078e4..010a20f 100644 --- a/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm +++ b/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm
@@ -27,6 +27,7 @@ #include "components/keyed_service/core/service_access_type.h" #include "components/metrics/call_stack_profile_metrics_provider.h" #include "components/metrics/drive_metrics_provider.h" +#include "components/metrics/metrics_log_uploader.h" #include "components/metrics/metrics_pref_names.h" #include "components/metrics/metrics_reporting_default_state.h" #include "components/metrics/metrics_service.h" @@ -164,10 +165,11 @@ IOSChromeMetricsServiceClient::CreateUploader( const std::string& server_url, const std::string& mime_type, + metrics::MetricsLogUploader::MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete) { return base::MakeUnique<metrics::NetMetricsLogUploader>( - GetApplicationContext()->GetSystemURLRequestContext(), - server_url, mime_type, on_upload_complete); + GetApplicationContext()->GetSystemURLRequestContext(), server_url, + mime_type, service_type, on_upload_complete); } base::TimeDelta IOSChromeMetricsServiceClient::GetStandardUploadInterval() {
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_navigation_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_navigation_controller.mm index 5993c41e..4928dc8 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_navigation_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_navigation_controller.mm
@@ -28,4 +28,10 @@ return NO; } +#pragma mark - UIResponder + +- (BOOL)canBecomeFirstResponder { + return YES; +} + @end
diff --git a/ios/chrome/browser/ui/browser_view_controller_unittest.mm b/ios/chrome/browser/ui/browser_view_controller_unittest.mm index ca22cbc..cbe5c55e 100644 --- a/ios/chrome/browser/ui/browser_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/browser_view_controller_unittest.mm
@@ -156,10 +156,6 @@ [[[tabModel stub] andReturnValue:OCMOCK_VALUE(enabled)] webUsageEnabled]; [[[tabModel stub] andReturn:currentTab] currentTab]; [[[tabModel stub] andReturn:currentTab] tabAtIndex:0]; - GURL URL("http://www.google.com"); - [[[tabModel stub] andReturn:currentTab] addTabWithURL:URL - referrer:web::Referrer() - windowName:[OCMArg any]]; [[tabModel stub] addObserver:[OCMArg any]]; [[tabModel stub] removeObserver:[OCMArg any]]; [[tabModel stub] saveSessionImmediately:NO]; @@ -199,8 +195,8 @@ newTabStripControllerWithTabModel:[OCMArg any]]; [[[factory stub] andReturn:nil] newPreloadController]; [[[factory stub] andReturnValue:OCMOCK_VALUE(toolbarModelIOS_)] - newToolbarModelIOSWithDelegate:(ToolbarModelDelegateIOS*) - [OCMArg anyPointer]]; + newToolbarModelIOSWithDelegate:static_cast<ToolbarModelDelegateIOS*>( + [OCMArg anyPointer])]; [[[factory stub] andReturn:nil] newWebToolbarControllerWithDelegate:[OCMArg any] urlLoader:[OCMArg any] @@ -306,7 +302,7 @@ } TEST_F(BrowserViewControllerTest, TestTabDeselected) { - OCMockObject* tabMock = (OCMockObject*)tab_.get(); + OCMockObject* tabMock = static_cast<OCMockObject*>(tab_.get()); [[tabMock expect] wasHidden]; NSDictionary* userInfoWithThisTab = [NSDictionary dictionaryWithObject:tab_ forKey:kTabModelTabKey]; @@ -366,10 +362,10 @@ // load on a handset, but not stop the load on a tablet. TEST_F(BrowserViewControllerTest, TestLocationBarBeganEdit_whenPageLoadIsInProgress) { - OCMockObject* tabMock = (OCMockObject*)tab_.get(); + OCMockObject* tabMock = static_cast<OCMockObject*>(tab_.get()); // Have the TestToolbarModel indicate that a page load is in progress. - ((TestToolbarModelIOS*)toolbarModelIOS_)->set_is_loading(true); + static_cast<TestToolbarModelIOS*>(toolbarModelIOS_)->set_is_loading(true); // The tab should only stop loading on handsets. if (!IsIPadIdiom()) @@ -383,10 +379,10 @@ // to stop the load on a handset or a tablet. TEST_F(BrowserViewControllerTest, TestLocationBarBeganEdit_whenPageLoadIsComplete) { - OCMockObject* tabMock = (OCMockObject*)tab_.get(); + OCMockObject* tabMock = static_cast<OCMockObject*>(tab_.get()); // Have the TestToolbarModel indicate that the page load is complete. - ((TestToolbarModelIOS*)toolbarModelIOS_)->set_is_loading(false); + static_cast<TestToolbarModelIOS*>(toolbarModelIOS_)->set_is_loading(false); // Don't set any expectation for stopLoading to be called on the mock tab. [bvc_ locationBarBeganEdit:nil]; @@ -399,8 +395,8 @@ TEST_F(BrowserViewControllerTest, TestSharePageCommandHandling) { GURL expectedUrl("http://www.testurl.net"); NSString* expectedTitle = @"title"; - [(BVCTestTabMock*)tab_.get() setUrl:expectedUrl]; - OCMockObject* tabMock = (OCMockObject*)tab_.get(); + [static_cast<BVCTestTabMock*>(tab_.get()) setUrl:expectedUrl]; + OCMockObject* tabMock = static_cast<OCMockObject*>(tab_.get()); ios::ChromeBrowserState* ptr = chrome_browser_state_.get(); [[[tabMock stub] andReturnValue:OCMOCK_VALUE(ptr)] browserState]; [[[tabMock stub] andReturn:expectedTitle] title]; @@ -410,14 +406,15 @@ CGSizeMake(300, 400), [UIColor blueColor]); [[[tabMock stub] andReturn:tabSnapshot] generateSnapshotWithOverlay:NO visibleFrameOnly:YES]; - OCMockObject* shareControllerMock = (OCMockObject*)shareController_.get(); + OCMockObject* shareControllerMock = + static_cast<OCMockObject*>(shareController_.get()); // Passing non zero/nil |fromRect| and |inView| parameters to satisfy protocol // requirements. BOOL (^shareDataChecker) (id value) = ^BOOL(id value) { if (![value isMemberOfClass:ShareToData.class]) return NO; - ShareToData* shareToData = (ShareToData*)value; + ShareToData* shareToData = static_cast<ShareToData*>(value); CGSize size = CGSizeMake(40, 40); BOOL thumbnailDataIsEqual = ui::test::uiimage_utils::UIImagesAreEqual( shareToData.thumbnailGenerator(size), @@ -446,13 +443,14 @@ GURL expectedUrl("http://www.testurl.net"); NSString* expectedTitle = @"title"; // Sets WebState to nil because [tab close] clears the WebState. - [(BVCTestTabMock*)tab_.get() setWebState:nil]; - [(BVCTestTabMock*)tab_.get() setUrl:expectedUrl]; - OCMockObject* tabMock = (OCMockObject*)tab_.get(); + [static_cast<BVCTestTabMock*>(tab_.get()) setWebState:nil]; + [static_cast<BVCTestTabMock*>(tab_.get()) setUrl:expectedUrl]; + OCMockObject* tabMock = static_cast<OCMockObject*>(tab_.get()); [[[tabMock stub] andReturn:expectedTitle] title]; [[[tabMock stub] andReturn:expectedTitle] originalTitle]; // Explicitly disallow the execution of the ShareController. - OCMockObject* shareControllerMock = (OCMockObject*)shareController_.get(); + OCMockObject* shareControllerMock = + static_cast<OCMockObject*>(shareController_.get()); [[shareControllerMock reject] shareWithData:[OCMArg any] controller:bvc_ @@ -489,7 +487,7 @@ alertCoordinatorWithTitle:errorTitle message:errorMessage viewController:OCMOCK_ANY]; - [((AlertCoordinator*)[mockCoordinator expect])start]; + [static_cast<AlertCoordinator*>([mockCoordinator expect]) start]; [bvc_ shareDidComplete:ShareTo::SHARE_ERROR successMessage:@"dummy"]; EXPECT_OCMOCK_VERIFY(dependencyFactory_); @@ -535,7 +533,8 @@ } TEST_F(BrowserViewControllerTest, TestClearPresentedState) { - OCMockObject* shareControllerMock = (OCMockObject*)shareController_.get(); + OCMockObject* shareControllerMock = + static_cast<OCMockObject*>(shareController_.get()); [[shareControllerMock expect] cancelShareAnimated:NO]; EXPECT_CALL(*this, OnCompletionCalled()); [bvc_ clearPresentedStateWithCompletion:^{
diff --git a/ios/chrome/browser/ui/history/history_panel_view_controller.mm b/ios/chrome/browser/ui/history/history_panel_view_controller.mm index 2989f1e..59ff508b 100644 --- a/ios/chrome/browser/ui/history/history_panel_view_controller.mm +++ b/ios/chrome/browser/ui/history/history_panel_view_controller.mm
@@ -409,6 +409,10 @@ #pragma mark - UIResponder +- (BOOL)canBecomeFirstResponder { + return YES; +} + - (NSArray*)keyCommands { __weak HistoryPanelViewController* weakSelf = self; return @[ [UIKeyCommand cr_keyCommandWithInput:UIKeyInputEscape
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm index 6e0eb577..499549b 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm
@@ -164,6 +164,10 @@ #pragma mark - UIResponder +- (BOOL)canBecomeFirstResponder { + return YES; +} + - (NSArray*)keyCommands { __weak ReadingListViewController* weakSelf = self; return @[ [UIKeyCommand
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm index e80c01d0..b1b25e5 100644 --- a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
@@ -656,4 +656,10 @@ return [NSValue valueWithPointer:controller]; } +#pragma mark - UIResponder + +- (BOOL)canBecomeFirstResponder { + return YES; +} + @end
diff --git a/ios/chrome/today_extension/today_metrics_logger.mm b/ios/chrome/today_extension/today_metrics_logger.mm index 17b47bc..8022d43 100644 --- a/ios/chrome/today_extension/today_metrics_logger.mm +++ b/ios/chrome/today_extension/today_metrics_logger.mm
@@ -71,6 +71,7 @@ std::unique_ptr<metrics::MetricsLogUploader> CreateUploader( const std::string& server_url, const std::string& mime_type, + metrics::MetricsLogUploader::MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete) override; base::TimeDelta GetStandardUploadInterval() override; @@ -151,6 +152,7 @@ TodayMetricsServiceClient::CreateUploader( const std::string& server_url, const std::string& mime_type, + metrics::MetricsLogUploader::MetricServiceType service_type, const base::Callback<void(int)>& on_upload_complete) { NOTREACHED(); return nullptr;
diff --git a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm index dd85b85..706910fe 100644 --- a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm +++ b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -11,6 +11,7 @@ #include "base/mac/foundation_util.h" #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.h" #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_collection_view_layout.h" +#import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_overlay_view.h" #import "ios/clean/chrome/browser/ui/actions/settings_actions.h" #import "ios/clean/chrome/browser/ui/actions/tab_grid_actions.h" #import "ios/clean/chrome/browser/ui/commands/settings_commands.h" @@ -35,6 +36,7 @@ UICollectionViewDelegate, SessionCellDelegate> @property(nonatomic, weak) UICollectionView* grid; +@property(nonatomic, weak) UIView* noTabsOverlay; @property(nonatomic, strong) MDCFloatingButton* floatingNewTabButton; @end @@ -45,6 +47,7 @@ @synthesize tabGridCommandHandler = _tabGridCommandHandler; @synthesize tabCommandHandler = _tabCommandHandler; @synthesize grid = _grid; +@synthesize noTabsOverlay = _noTabsOverlay; @synthesize floatingNewTabButton = _floatingNewTabButton; - (void)viewDidLoad { @@ -103,7 +106,15 @@ - (NSInteger)collectionView:(UICollectionView*)collectionView numberOfItemsInSection:(NSInteger)section { - return [self.dataSource numberOfTabsInTabGrid]; + NSInteger items = [self.dataSource numberOfTabsInTabGrid]; + // HACK: Do not make showing noTabsOverlay a side effect of the dataSource + // callback. + if (items) { + [self removeNoTabsOverlay]; + } else { + [self showNoTabsOverlay]; + } + return items; } - (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView @@ -176,4 +187,28 @@ [self.grid performBatchUpdates:updateBlock completion:nil]; } +#pragma mark - Private + +// Shows an overlay covering the entire tab grid that informs the user that +// there are no tabs. +- (void)showNoTabsOverlay { + // PLACEHOLDER: The new tab grid will have a completely different zero tab + // overlay from the tab switcher. Also, the overlay will be above the recent + // tabs section. + TabSwitcherPanelOverlayView* overlayView = + [[TabSwitcherPanelOverlayView alloc] initWithFrame:self.grid.bounds + browserState:nil]; + overlayView.overlayType = + TabSwitcherPanelOverlayType::OVERLAY_PANEL_USER_NO_OPEN_TABS; + overlayView.autoresizingMask = + UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [self.grid addSubview:overlayView]; + self.noTabsOverlay = overlayView; +} + +// Removes the noTabsOverlay covering the entire tab grid. +- (void)removeNoTabsOverlay { + [self.noTabsOverlay removeFromSuperview]; +} + @end
diff --git a/media/midi/dynamically_initialized_midi_manager_win.cc b/media/midi/dynamically_initialized_midi_manager_win.cc index 26a4c835e..2a83b00 100644 --- a/media/midi/dynamically_initialized_midi_manager_win.cc +++ b/media/midi/dynamically_initialized_midi_manager_win.cc
@@ -26,6 +26,10 @@ namespace { +// Assumes that nullptr represents an invalid MIDI handle. +constexpr HMIDIIN kInvalidInHandle = nullptr; +constexpr HMIDIOUT kInvalidOutHandle = nullptr; + // Global variables to identify MidiManager instance. constexpr int kInvalidInstanceId = -1; int g_active_instance_id = kInvalidInstanceId; @@ -47,6 +51,9 @@ constexpr int kTaskRunner = 0; // Obtains base::Lock instance pointer to ensure tasks run safely on TaskRunner. +// Since all tasks on TaskRunner run behind a lock of *GetTaskLock(), we can +// access all members even on the I/O thread if a lock of *GetTaskLock() is +// obtained. base::Lock* GetTaskLock() { static base::Lock* lock = new base::Lock; return lock; @@ -69,6 +76,36 @@ // TODO(toyoshim): Factor out TaskRunner related functionaliries above, and // deprecate MidiScheduler. It should be available via MidiManager::scheduler(). +// Helper functions to close MIDI device handles on TaskRunner asynchronously. +void FinalizeInPort(HMIDIIN handle) { + midiInClose(handle); +} + +void FinalizeOutPort(HMIDIOUT handle) { + midiOutClose(handle); +} + +// Handles MIDI input port callbacks that runs on a system provided thread. +void CALLBACK HandleMidiInCallback(HMIDIIN hmi, + UINT msg, + DWORD_PTR instance, + DWORD_PTR param1, + DWORD_PTR param2) { + // TODO(toyoshim): Following patches will implement actual functions. +} + +// Handles MIDI output port callbacks that runs on a system provided thread. +void CALLBACK HandleMidiOutCallback(HMIDIOUT hmo, + UINT msg, + DWORD_PTR instance, + DWORD_PTR param1, + DWORD_PTR param2) { + // TODO(toyoshim): Following patches will implement actual functions. +} + +// All instances of Port subclasses are always accessed behind a lock of +// *GetTaskLock(). Port and subclasses implementation do not need to +// consider thread safety. class Port { public: Port(const std::string& type, @@ -162,7 +199,8 @@ caps.wPid, caps.vDriverVersion, base::WideToUTF8( - base::string16(caps.szPname, wcslen(caps.szPname)))) {} + base::string16(caps.szPname, wcslen(caps.szPname)))), + in_handle_(kInvalidInHandle) {} static std::vector<std::unique_ptr<InPort>> EnumerateActivePorts() { std::vector<std::unique_ptr<InPort>> ports; @@ -180,6 +218,13 @@ return ports; } + void Finalize(scoped_refptr<base::SingleThreadTaskRunner> runner) { + if (in_handle_ != kInvalidInHandle) { + runner->PostTask(FROM_HERE, base::Bind(&FinalizeInPort, in_handle_)); + in_handle_ = kInvalidInHandle; + } + } + void NotifyPortStateSet(DynamicallyInitializedMidiManagerWin* manager) { manager->PostReplyTask( base::Bind(&DynamicallyInitializedMidiManagerWin::SetInputPortState, @@ -191,6 +236,34 @@ base::Bind(&DynamicallyInitializedMidiManagerWin::AddInputPort, base::Unretained(manager), info_)); } + + // Port overrides: + bool Disconnect() override { + if (in_handle_ != kInvalidInHandle) { + // Following API call may fail because device was already disconnected. + // But just in case. + midiInClose(in_handle_); + in_handle_ = kInvalidInHandle; + } + return Port::Disconnect(); + } + + void Open() override { + // TODO(toyoshim): Pass instance_id to implement HandleMidiInCallback. + MMRESULT result = + midiInOpen(&in_handle_, device_id_, + reinterpret_cast<DWORD_PTR>(&HandleMidiInCallback), 0, + CALLBACK_FUNCTION); + if (result == MMSYSERR_NOERROR) { + Port::Open(); + } else { + in_handle_ = kInvalidInHandle; + Disconnect(); + } + } + + private: + HMIDIIN in_handle_; }; // TODO(toyoshim): Following patches will implement actual functions. @@ -204,7 +277,8 @@ caps.vDriverVersion, base::WideToUTF8( base::string16(caps.szPname, wcslen(caps.szPname)))), - software_(caps.wTechnology == MOD_SWSYNTH) {} + software_(caps.wTechnology == MOD_SWSYNTH), + out_handle_(kInvalidOutHandle) {} static std::vector<std::unique_ptr<OutPort>> EnumerateActivePorts() { std::vector<std::unique_ptr<OutPort>> ports; @@ -222,19 +296,13 @@ return ports; } - // Port overrides: - bool Connect() override { - // Until |software| option is supported, disable Microsoft GS Wavetable - // Synth that has a known security issue. - if (software_ && manufacturer_id_ == MM_MICROSOFT && - (product_id_ == MM_MSFT_WDMAUDIO_MIDIOUT || - product_id_ == MM_MSFT_GENERIC_MIDISYNTH)) { - return false; + void Finalize(scoped_refptr<base::SingleThreadTaskRunner> runner) { + if (out_handle_ != kInvalidOutHandle) { + runner->PostTask(FROM_HERE, base::Bind(&FinalizeOutPort, out_handle_)); + out_handle_ = kInvalidOutHandle; } - return Port::Connect(); } - // Port Overrides: void NotifyPortStateSet(DynamicallyInitializedMidiManagerWin* manager) { manager->PostReplyTask( base::Bind(&DynamicallyInitializedMidiManagerWin::SetOutputPortState, @@ -247,7 +315,43 @@ base::Unretained(manager), info_)); } + // Port overrides: + bool Connect() override { + // Until |software| option is supported, disable Microsoft GS Wavetable + // Synth that has a known security issue. + if (software_ && manufacturer_id_ == MM_MICROSOFT && + (product_id_ == MM_MSFT_WDMAUDIO_MIDIOUT || + product_id_ == MM_MSFT_GENERIC_MIDISYNTH)) { + return false; + } + return Port::Connect(); + } + + bool Disconnect() override { + if (out_handle_ != kInvalidOutHandle) { + // Following API call may fail because device was already disconnected. + // But just in case. + midiOutClose(out_handle_); + out_handle_ = kInvalidOutHandle; + } + return Port::Disconnect(); + } + + void Open() override { + MMRESULT result = + midiOutOpen(&out_handle_, device_id_, + reinterpret_cast<DWORD_PTR>(&HandleMidiOutCallback), 0, + CALLBACK_FUNCTION); + if (result == MMSYSERR_NOERROR) { + Port::Open(); + } else { + out_handle_ = kInvalidOutHandle; + Disconnect(); + } + } + const bool software_; + HMIDIOUT out_handle_; }; DynamicallyInitializedMidiManagerWin::DynamicallyInitializedMidiManagerWin( @@ -304,7 +408,18 @@ // Ensures that no task runs on TaskRunner so to destruct the instance safely. // Tasks that did not started yet will do nothing after invalidate the // instance ID above. + // Behind the lock below, we can safely access all members for finalization + // even on the I/O thread. base::AutoLock lock(*GetTaskLock()); + + // Posts tasks that finalize each device port without MidiManager instance + // on TaskRunner. If another MidiManager instance is created, its + // initialization runs on the same task runner after all tasks posted here + // finish. + for (const auto& port : input_ports_) + port->Finalize(service()->GetTaskRunner(kTaskRunner)); + for (const auto& port : output_ports_) + port->Finalize(service()->GetTaskRunner(kTaskRunner)); } void DynamicallyInitializedMidiManagerWin::DispatchSendMidiData(
diff --git a/net/base/sdch_manager.cc b/net/base/sdch_manager.cc index d577db84..11e9e3b7 100644 --- a/net/base/sdch_manager.cc +++ b/net/base/sdch_manager.cc
@@ -4,6 +4,7 @@ #include "net/base/sdch_manager.h" +#include <inttypes.h> #include <limits.h> #include <utility> @@ -335,7 +336,8 @@ size_t total_count = dictionaries_.size(); if (total_count == 0) return; - std::string name = base::StringPrintf("net/sdch_manager_%p", this); + std::string name = base::StringPrintf("net/sdch_manager_0x%" PRIxPTR, + reinterpret_cast<uintptr_t>(this)); base::trace_event::MemoryAllocatorDump* dump = pmd->GetAllocatorDump(name); if (dump == nullptr) { dump = pmd->CreateAllocatorDump(name); @@ -350,6 +352,7 @@ base::trace_event::MemoryAllocatorDump::kUnitsObjects, total_count); } + // Create an empty row under parent's dump so size can be attributed correctly // if |this| is shared between URLRequestContexts. base::trace_event::MemoryAllocatorDump* empty_row_dump =
diff --git a/net/base/sdch_manager_unittest.cc b/net/base/sdch_manager_unittest.cc index 31162841..72913a3 100644 --- a/net/base/sdch_manager_unittest.cc +++ b/net/base/sdch_manager_unittest.cc
@@ -4,6 +4,7 @@ #include "net/base/sdch_manager.h" +#include <inttypes.h> #include <limits.h> #include <memory> @@ -640,7 +641,18 @@ sdch_manager()->RemoveObserver(&observer); } -TEST_F(SdchManagerTest, DumpMemoryStats) { +class SdchManagerMemoryDumpTest + : public SdchManagerTest, + public testing::WithParamInterface< + base::trace_event::MemoryDumpLevelOfDetail> {}; + +INSTANTIATE_TEST_CASE_P( + /* no prefix */, + SdchManagerMemoryDumpTest, + ::testing::Values(base::trace_event::MemoryDumpLevelOfDetail::DETAILED, + base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND)); + +TEST_P(SdchManagerMemoryDumpTest, DumpMemoryStats) { MockSdchObserver observer; sdch_manager()->AddObserver(&observer); @@ -655,20 +667,20 @@ EXPECT_EQ(target_gurl, observer.last_dictionary_url()); EXPECT_EQ(server_hash, observer.last_server_hash()); - base::trace_event::MemoryDumpArgs dump_args = { - base::trace_event::MemoryDumpLevelOfDetail::DETAILED}; + base::trace_event::MemoryDumpArgs dump_args = {GetParam()}; std::unique_ptr<base::trace_event::ProcessMemoryDump> pmd( new base::trace_event::ProcessMemoryDump(nullptr, dump_args)); base::trace_event::MemoryAllocatorDump* parent = - pmd->CreateAllocatorDump("parent"); + pmd->CreateAllocatorDump("net/url_request_context_0x123"); sdch_manager()->DumpMemoryStats(pmd.get(), parent->absolute_name()); const base::trace_event::MemoryAllocatorDump* sub_dump = - pmd->GetAllocatorDump("parent/sdch_manager"); + pmd->GetAllocatorDump("net/url_request_context_0x123/sdch_manager"); ASSERT_NE(nullptr, sub_dump); const base::trace_event::MemoryAllocatorDump* dump = pmd->GetAllocatorDump( - base::StringPrintf("net/sdch_manager_%p", sdch_manager())); + base::StringPrintf("net/sdch_manager_0x%" PRIxPTR, + reinterpret_cast<uintptr_t>(sdch_manager()))); std::unique_ptr<base::Value> raw_attrs = dump->attributes_for_testing()->ToBaseValue(); base::DictionaryValue* attrs;
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc index f7acbde..71509a42 100644 --- a/net/http/http_cache_unittest.cc +++ b/net/http/http_cache_unittest.cc
@@ -23,6 +23,7 @@ #include "base/strings/stringprintf.h" #include "base/test/simple_test_clock.h" #include "base/trace_event/memory_allocator_dump.h" +#include "base/trace_event/memory_dump_request_args.h" #include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_event_argument.h" #include "net/base/cache_type.h" @@ -8357,8 +8358,18 @@ response_info.cache_entry_status); } +class HttpCacheMemoryDumpTest + : public testing::TestWithParam< + base::trace_event::MemoryDumpLevelOfDetail> {}; + +INSTANTIATE_TEST_CASE_P( + /* no prefix */, + HttpCacheMemoryDumpTest, + ::testing::Values(base::trace_event::MemoryDumpLevelOfDetail::DETAILED, + base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND)); + // Basic test to make sure HttpCache::DumpMemoryStats doesn't crash. -TEST(HttpCache, DumpMemoryStats) { +TEST_P(HttpCacheMemoryDumpTest, DumpMemoryStats) { MockHttpCache cache; cache.FailConditionalizations(); RunTransactionTest(cache.http_cache(), kTypicalGET_Transaction); @@ -8372,17 +8383,17 @@ EXPECT_EQ(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE, response_info.cache_entry_status); - base::trace_event::MemoryDumpArgs dump_args = { - base::trace_event::MemoryDumpLevelOfDetail::DETAILED}; + base::trace_event::MemoryDumpArgs dump_args = {GetParam()}; std::unique_ptr<base::trace_event::ProcessMemoryDump> process_memory_dump( new base::trace_event::ProcessMemoryDump(nullptr, dump_args)); base::trace_event::MemoryAllocatorDump* parent_dump = - process_memory_dump->CreateAllocatorDump("parent"); + process_memory_dump->CreateAllocatorDump("net/url_request_context_0x123"); cache.http_cache()->DumpMemoryStats(process_memory_dump.get(), parent_dump->absolute_name()); const base::trace_event::MemoryAllocatorDump* dump = - process_memory_dump->GetAllocatorDump("parent/http_cache"); + process_memory_dump->GetAllocatorDump( + "net/url_request_context_0x123/http_cache"); ASSERT_NE(nullptr, dump); std::unique_ptr<base::Value> raw_attrs = dump->attributes_for_testing()->ToBaseValue();
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index fda084ea..b57653a 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc
@@ -4,6 +4,8 @@ #include "net/http/http_network_session.h" +#include <inttypes.h> + #include <utility> #include "base/atomic_sequence_num.h" @@ -423,7 +425,8 @@ void HttpNetworkSession::DumpMemoryStats( base::trace_event::ProcessMemoryDump* pmd, const std::string& parent_absolute_name) const { - std::string name = base::StringPrintf("net/http_network_session_%p", this); + std::string name = base::StringPrintf("net/http_network_session_0x%" PRIxPTR, + reinterpret_cast<uintptr_t>(this)); base::trace_event::MemoryAllocatorDump* http_network_session_dump = pmd->GetAllocatorDump(name); if (http_network_session_dump == nullptr) { @@ -439,6 +442,7 @@ quic_stream_factory_.DumpMemoryStats( pmd, http_network_session_dump->absolute_name()); } + // Create an empty row under parent's dump so size can be attributed correctly // if |this| is shared between URLRequestContexts. base::trace_event::MemoryAllocatorDump* empty_row_dump =
diff --git a/net/spdy/spdy_session_pool_unittest.cc b/net/spdy/spdy_session_pool_unittest.cc index 51362da..e7840946 100644 --- a/net/spdy/spdy_session_pool_unittest.cc +++ b/net/spdy/spdy_session_pool_unittest.cc
@@ -671,7 +671,18 @@ spdy_session_pool_->CloseCurrentSessions(ERR_ABORTED); } -TEST_F(SpdySessionPoolTest, DumpMemoryStats) { +class SpdySessionMemoryDumpTest + : public SpdySessionPoolTest, + public testing::WithParamInterface< + base::trace_event::MemoryDumpLevelOfDetail> {}; + +INSTANTIATE_TEST_CASE_P( + /* no prefix */, + SpdySessionMemoryDumpTest, + ::testing::Values(base::trace_event::MemoryDumpLevelOfDetail::DETAILED, + base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND)); + +TEST_P(SpdySessionMemoryDumpTest, DumpMemoryStats) { SpdySessionKey key(HostPortPair("https://www.example.org", 443), ProxyServer::Direct(), PRIVACY_MODE_DISABLED); @@ -692,12 +703,12 @@ base::RunLoop().RunUntilIdle(); EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key)); - base::trace_event::MemoryDumpArgs dump_args = { - base::trace_event::MemoryDumpLevelOfDetail::DETAILED}; + base::trace_event::MemoryDumpArgs dump_args = {GetParam()}; std::unique_ptr<base::trace_event::ProcessMemoryDump> process_memory_dump( new base::trace_event::ProcessMemoryDump(nullptr, dump_args)); base::trace_event::MemoryAllocatorDump* parent_dump = - process_memory_dump->CreateAllocatorDump("parent"); + process_memory_dump->CreateAllocatorDump( + "net/http_network_session_0x123"); spdy_session_pool_->DumpMemoryStats(process_memory_dump.get(), parent_dump->absolute_name());
diff --git a/net/ssl/ssl_client_session_cache_unittest.cc b/net/ssl/ssl_client_session_cache_unittest.cc index 5158782..07ae81b 100644 --- a/net/ssl/ssl_client_session_cache_unittest.cc +++ b/net/ssl/ssl_client_session_cache_unittest.cc
@@ -354,8 +354,19 @@ EXPECT_EQ(0u, cache.size()); } +class SSLClientSessionCacheMemoryDumpTest + : public SSLClientSessionCacheTest, + public testing::WithParamInterface< + base::trace_event::MemoryDumpLevelOfDetail> {}; + +INSTANTIATE_TEST_CASE_P( + /* no prefix */, + SSLClientSessionCacheMemoryDumpTest, + ::testing::Values(base::trace_event::MemoryDumpLevelOfDetail::DETAILED, + base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND)); + // Basic test for dumping memory stats. -TEST_F(SSLClientSessionCacheTest, TestDumpMemoryStats) { +TEST_P(SSLClientSessionCacheMemoryDumpTest, TestDumpMemoryStats) { SSLClientSessionCache::Config config; SSLClientSessionCache cache(config); @@ -372,8 +383,7 @@ EXPECT_EQ(session3.get(), cache.Lookup("key3", nullptr).get()); EXPECT_EQ(3u, cache.size()); - base::trace_event::MemoryDumpArgs dump_args = { - base::trace_event::MemoryDumpLevelOfDetail::DETAILED}; + base::trace_event::MemoryDumpArgs dump_args = {GetParam()}; std::unique_ptr<base::trace_event::ProcessMemoryDump> process_memory_dump( new base::trace_event::ProcessMemoryDump(nullptr, dump_args)); cache.DumpMemoryStats(process_memory_dump.get());
diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc index 300c050e..a7b0233 100644 --- a/net/url_request/url_request_context.cc +++ b/net/url_request/url_request_context.cc
@@ -4,6 +4,8 @@ #include "net/url_request/url_request_context.h" +#include <inttypes.h> + #include "base/compiler_specific.h" #include "base/debug/alias.h" #include "base/memory/ptr_util.h" @@ -12,6 +14,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_allocator_dump.h" #include "base/trace_event/memory_dump_manager.h" +#include "base/trace_event/memory_dump_request_args.h" #include "base/trace_event/process_memory_dump.h" #include "net/base/sdch_manager.h" #include "net/cookies/cookie_store.h" @@ -138,11 +141,21 @@ base::trace_event::ProcessMemoryDump* pmd) { if (name_.empty()) name_ = "unknown"; - base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump( - base::StringPrintf("net/url_request_context/%s_%p", name_.c_str(), this)); + + SSLClientSocketImpl::DumpSSLClientSessionMemoryStats(pmd); + + std::string dump_name = base::StringPrintf( + "net/url_request_context_0x%" PRIxPTR, reinterpret_cast<uintptr_t>(this)); + base::trace_event::MemoryAllocatorDump* dump = + pmd->CreateAllocatorDump(dump_name); dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameObjectCount, base::trace_event::MemoryAllocatorDump::kUnitsObjects, url_requests_->size()); + if (args.level_of_detail != + base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND) { + dump->AddString("origin", + base::trace_event::MemoryAllocatorDump::kTypeString, name_); + } HttpTransactionFactory* transaction_factory = http_transaction_factory(); if (transaction_factory) { HttpNetworkSession* network_session = transaction_factory->GetSession(); @@ -152,9 +165,8 @@ if (http_cache) http_cache->DumpMemoryStats(pmd, dump->absolute_name()); } - SSLClientSocketImpl::DumpSSLClientSessionMemoryStats(pmd); if (sdch_manager_) - sdch_manager_->DumpMemoryStats(pmd, dump->absolute_name()); + sdch_manager_->DumpMemoryStats(pmd, dump_name); return true; }
diff --git a/net/url_request/url_request_context_unittest.cc b/net/url_request/url_request_context_unittest.cc index bae1685..147e350 100644 --- a/net/url_request/url_request_context_unittest.cc +++ b/net/url_request/url_request_context_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include "base/memory/ptr_util.h" +#include "base/trace_event/memory_dump_request_args.h" #include "base/trace_event/process_memory_dump.h" #include "net/proxy/proxy_config_service_fixed.h" #include "net/url_request/url_request_context_builder.h" @@ -14,10 +15,19 @@ namespace net { +class URLRequestContextMemoryDumpTest + : public testing::TestWithParam< + base::trace_event::MemoryDumpLevelOfDetail> {}; + +INSTANTIATE_TEST_CASE_P( + /* no prefix */, + URLRequestContextMemoryDumpTest, + ::testing::Values(base::trace_event::MemoryDumpLevelOfDetail::DETAILED, + base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND)); + // Checks if the dump provider runs without crashing and dumps root objects. -TEST(URLRequestContextTest, MemoryDumpProvider) { - base::trace_event::MemoryDumpArgs dump_args = { - base::trace_event::MemoryDumpLevelOfDetail::DETAILED}; +TEST_P(URLRequestContextMemoryDumpTest, MemoryDumpProvider) { + base::trace_event::MemoryDumpArgs dump_args = {GetParam()}; std::unique_ptr<base::trace_event::ProcessMemoryDump> process_memory_dump( new base::trace_event::ProcessMemoryDump(nullptr, dump_args)); URLRequestContextBuilder builder;
diff --git a/skia/ext/raster_handle_allocator_win.cc b/skia/ext/raster_handle_allocator_win.cc index f5c4bdd..22d9bf4 100644 --- a/skia/ext/raster_handle_allocator_win.cc +++ b/skia/ext/raster_handle_allocator_win.cc
@@ -108,6 +108,10 @@ } }; +void unmap_view_proc(void* pixels, void*) { + UnmapViewOfFile(pixels); +} + } // namespace namespace skia { @@ -137,8 +141,13 @@ DCHECK(shared_section != NULL); void* pixels = MapViewOfFile(shared_section, FILE_MAP_WRITE, 0, 0, row_bytes * height); - if (pixels) - return SkCanvas::MakeRasterDirect(info, pixels, row_bytes); + if (pixels) { + SkBitmap bitmap; + if (bitmap.installPixels(info, pixels, row_bytes, nullptr, + unmap_view_proc, nullptr)) { + return base::MakeUnique<SkCanvas>(bitmap); + } + } } if (failure_type == CRASH_ON_FAILURE)
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 9de4709..951707fb 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1262,6 +1262,21 @@ ] } ], + "NTPPreferAmpUrls": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "NTPPreferAmpUrls" + ] + } + ] + } + ], "NTPRecentForeignTabs": [ { "platforms": [
diff --git a/third_party/WebKit/LayoutTests/editing/selection/extend-crash.html b/third_party/WebKit/LayoutTests/editing/selection/extend-crash.html new file mode 100644 index 0000000..b92dcc9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/editing/selection/extend-crash.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<div contenteditable="true">foo</div> +<script> +test(() => { + // Note that this test can be removed when crbug.com/690272 is fixed. + let selection = getSelection(); + let editor = document.querySelector('div'); + editor.addEventListener('focus', () => { selection.removeAllRanges(); }); + selection.collapse(editor, 0); + assert_throws('InvalidStateError', () => { selection.extend(editor, 1);}); +}, 'Focus event handler should not make inconsistent state of Selection, and extend() should not crash.'); +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/redirect-with-delay.html b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/redirect-with-delay.html new file mode 100644 index 0000000..bd3cc035 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/redirect-with-delay.html
@@ -0,0 +1,21 @@ +<!doctype html> +<script src = "/resources/testharness.js"></script> +<script src = "/resources/testharnessreport.js"></script> +<script> +let test = async_test('CSP should be enforced to the iframe'); +let counter = 0; +const global = window; + +function check() { + ++counter; + if (counter !== 2) + return; + const iframe = document.querySelector('iframe'); + assert_true(global.script_loaded, 'in the main frame'); + assert_equals(iframe.contentWindow.script_loaded, undefined, 'in the iframe'); + test.done(); +} +</script> + +<script src="http://localhost:8000/security/contentSecurityPolicy/resources/redirect.pl?type=script&wait=true" async onload="test.step(check)"></script> +<iframe src="resources/redirect-with-delay-iframe.html" onload="test.step(check)"></iframe>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/resources/redirect-with-delay-iframe.html b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/resources/redirect-with-delay-iframe.html new file mode 100644 index 0000000..8882d48d --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/resources/redirect-with-delay-iframe.html
@@ -0,0 +1,4 @@ +<!doctype html> +<meta http-equiv = "Content-Security-Policy" content = "script-src http://localhost:8000/ 'unsafe-inline'"> +<script src="http://localhost:8000/security/contentSecurityPolicy/resources/redirect.pl?type=script&wait=true"></script> +
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/resources/redirect.pl b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/resources/redirect.pl index 81304916..a2e593e 100755 --- a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/resources/redirect.pl +++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/resources/redirect.pl
@@ -5,6 +5,11 @@ my $cgi = new CGI; my $resourceType = $cgi->param("type"); +my $wait = $cgi->param("wait"); + +if ($wait) { + sleep(2); +} if ($resourceType eq "script") { print "Location: http://127.0.0.1:8000/security/contentSecurityPolicy/resources/script-redirect-not-allowed.js";
diff --git a/third_party/WebKit/LayoutTests/sensor/resources/generic-sensor-tests.js b/third_party/WebKit/LayoutTests/sensor/resources/generic-sensor-tests.js index 8971afa..1e27c4d0 100644 --- a/third_party/WebKit/LayoutTests/sensor/resources/generic-sensor-tests.js +++ b/third_party/WebKit/LayoutTests/sensor/resources/generic-sensor-tests.js
@@ -5,11 +5,6 @@ // is called so that the value read in JavaScript are the values expected (the ones // sent by |updateReading|). function runGenericSensorTests(sensorType, updateReading, verifyReading) { - test(() => assert_throws( - new RangeError(), - () => new sensorType({frequency: -60})), - 'Test that negative frequency causes exception from constructor.'); - sensor_test(sensor => { sensor.mockSensorProvider.setGetSensorShouldFail(true); let sensorObject = new sensorType; @@ -97,6 +92,30 @@ }, 'Test that frequency is capped to the maximum supported from frequency.'); sensor_test(sensor => { + let minSupportedFrequency = 2; + sensor.mockSensorProvider.setMinimumSupportedFrequency(minSupportedFrequency); + let sensorObject = new sensorType({frequency: -1}); + sensorObject.start(); + let testPromise = sensor.mockSensorProvider.getCreatedSensor() + .then(mockSensor => { return mockSensor.addConfigurationCalled(); }) + .then(mockSensor => { + return new Promise((resolve, reject) => { + let wrapper = new CallbackWrapper(() => { + let configuration = mockSensor.active_sensor_configurations_[0]; + assert_equals(configuration.frequency, minSupportedFrequency); + sensorObject.stop(); + assert_equals(sensorObject.state, 'idle'); + resolve(mockSensor); + }, reject); + sensorObject.onactivate = wrapper.callback; + sensorObject.onerror = reject; + }); + }) + .then(mockSensor => { return mockSensor.removeConfigurationCalled(); }); + return testPromise; + }, 'Test that frequency is limited to the minimum supported from frequency.'); + + sensor_test(sensor => { let sensorObject = new sensorType({frequency: 60}); assert_equals(sensorObject.state, 'unconnected'); sensorObject.start();
diff --git a/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js b/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js index e514fe0..7d3c97e4 100644 --- a/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js +++ b/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js
@@ -249,6 +249,7 @@ this.resolve_func_ = null; this.is_continuous_ = false; this.max_frequency_ = 60; + this.min_frequency_ = 1; this.binding_ = new bindings.Binding(sensor_provider.SensorProvider, this); } @@ -288,6 +289,7 @@ buffer_offset: offset, mode: reporting_mode, default_configuration: default_config, + minimum_frequency: this.min_frequency_, maximum_frequency: this.max_frequency_}); if (this.resolve_func_ !== null) { @@ -319,6 +321,7 @@ this.get_sensor_should_fail_ = false; this.resolve_func_ = null; this.max_frequency_ = 60; + this.min_frequency_ = 1; this.is_continuous_ = false; this.binding_.close(); } @@ -349,6 +352,11 @@ setMaximumSupportedFrequency(frequency) { this.max_frequency_ = frequency; } + + // Sets the minimum frequency for a concrete sensor. + setMinimumSupportedFrequency(frequency) { + this.min_frequency_ = frequency; + } } let mockSensorProvider = new MockSensorProvider;
diff --git a/third_party/WebKit/Source/core/dom/Range.cpp b/third_party/WebKit/Source/core/dom/Range.cpp index c439b5d0..4e1d44a 100644 --- a/third_party/WebKit/Source/core/dom/Range.cpp +++ b/third_party/WebKit/Source/core/dom/Range.cpp
@@ -57,6 +57,51 @@ namespace blink { +class RangeUpdateScope { + STACK_ALLOCATED(); + RangeUpdateScope(Range* range) { + DCHECK(range); + if (++s_scopeCount == 1) { + m_range = range; + m_oldDocument = range->ownerDocument(); +#if DCHECK_IS_ON() + s_range = range; + } else { + DCHECK_EQ(s_range, range); +#endif + } + } + + ~RangeUpdateScope() { + DCHECK_GE(s_scopeCount, 1); + if (--s_scopeCount > 0) + return; + m_range->removeFromSelectionIfInDifferentRoot(*m_oldDocument); + m_range->updateSelectionIfAddedToSelection(); +#if DCHECK_IS_ON() + s_range = nullptr; +#endif + } + + private: + static int s_scopeCount; +#if DCHECK_IS_ON() + // This raw pointer is safe because + // - s_range has a valid pointer only if RangeUpdateScope instance is live. + // - RangeUpdateScope is used only in Range member functions. + static Range* s_range; +#endif + Member<Range> m_range; + Member<Document> m_oldDocument; + + DISALLOW_COPY_AND_ASSIGN(RangeUpdateScope); +}; + +int RangeUpdateScope::s_scopeCount = 0; +#if DCHECK_IS_ON() +Range* RangeUpdateScope::s_range; +#endif + inline Range::Range(Document& ownerDocument) : m_ownerDocument(&ownerDocument), m_start(m_ownerDocument), @@ -172,7 +217,7 @@ return; } - Document& oldDocument = ownerDocument(); + RangeUpdateScope scope(this); bool didMoveDocument = false; if (refNode->document() != m_ownerDocument) { setDocument(refNode->document()); @@ -185,12 +230,8 @@ m_start.set(refNode, offset, childNode); - if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) { - removeFromSelectionIfInDifferentRoot(oldDocument); + if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) collapse(true); - return; - } - updateSelectionIfAddedToSelection(); } void Range::setEnd(Node* refNode, @@ -203,8 +244,8 @@ return; } + RangeUpdateScope scope(this); bool didMoveDocument = false; - Document& oldDocument = ownerDocument(); if (refNode->document() != m_ownerDocument) { setDocument(refNode->document()); didMoveDocument = true; @@ -216,12 +257,8 @@ m_end.set(refNode, offset, childNode); - if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) { - removeFromSelectionIfInDifferentRoot(oldDocument); + if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) collapse(false); - return; - } - updateSelectionIfAddedToSelection(); } void Range::setStart(const Position& start, ExceptionState& exceptionState) { @@ -237,11 +274,11 @@ } void Range::collapse(bool toStart) { + RangeUpdateScope scope(this); if (toStart) m_end = m_start; else m_start = m_end; - updateSelectionIfAddedToSelection(); } bool Range::isNodeFullyContained(Node& node) const { @@ -1208,6 +1245,7 @@ return; } + RangeUpdateScope scope(this); setStartBefore(refNode); setEndAfter(refNode); } @@ -1242,14 +1280,12 @@ } } - Document& oldDocument = ownerDocument(); + RangeUpdateScope scope(this); if (m_ownerDocument != refNode->document()) setDocument(refNode->document()); m_start.setToStartOfNode(*refNode); m_end.setToEndOfNode(*refNode); - removeFromSelectionIfInDifferentRoot(oldDocument); - updateSelectionIfAddedToSelection(); } bool Range::selectNodeContents(Node* refNode, Position& start, Position& end) { @@ -1746,8 +1782,13 @@ DCHECK(startContainer()->document() == ownerDocument()); DCHECK(endContainer()->isConnected()); DCHECK(endContainer()->document() == ownerDocument()); - selection.setSelectedRange(EphemeralRange(this), VP_DEFAULT_AFFINITY); + bool didSet = selection.setSelectionDeprecated(SelectionInDOMTree::Builder() + .collapse(startPosition()) + .extend(endPosition()) + .build()); selection.cacheRangeOfDocument(this); + if (didSet) + selection.didSetSelectionDeprecated(); } void Range::removeFromSelectionIfInDifferentRoot(Document& oldDocument) {
diff --git a/third_party/WebKit/Source/core/dom/Range.h b/third_party/WebKit/Source/core/dom/Range.h index f76b3f020..f6db2360 100644 --- a/third_party/WebKit/Source/core/dom/Range.h +++ b/third_party/WebKit/Source/core/dom/Range.h
@@ -213,6 +213,8 @@ Member<Document> m_ownerDocument; // Cannot be null. RangeBoundaryPoint m_start; RangeBoundaryPoint m_end; + + friend class RangeUpdateScope; }; CORE_EXPORT bool areRangesEqual(const Range*, const Range*);
diff --git a/third_party/WebKit/Source/core/editing/DOMSelection.cpp b/third_party/WebKit/Source/core/editing/DOMSelection.cpp index 4540f0f..d835822 100644 --- a/third_party/WebKit/Source/core/editing/DOMSelection.cpp +++ b/third_party/WebKit/Source/core/editing/DOMSelection.cpp
@@ -75,6 +75,17 @@ return frame() && frame()->selection().isAvailable(); } +void DOMSelection::updateFrameSelection(const SelectionInDOMTree& selection, + Range* newCachedRange) const { + DCHECK(frame()); + FrameSelection& frameSelection = frame()->selection(); + // TODO(tkent): Specify FrameSelection::DoNotSetFocus. crbug.com/690272 + bool didSet = frameSelection.setSelectionDeprecated(selection); + cacheRangeIfSelectionOfDocument(newCachedRange); + if (didSet) + frameSelection.didSetSelectionDeprecated(); +} + const VisibleSelection& DOMSelection::visibleSelection() const { DCHECK(frame()); return frame()->selection().computeVisibleSelectionInDOMTreeDeprecated(); @@ -254,12 +265,12 @@ return; // 6. Set the context object's range to newRange. - frame()->selection().setSelection( + updateFrameSelection( SelectionInDOMTree::Builder() .collapse(Position(node, offset)) .setIsDirectional(frame()->selection().isDirectional()) - .build()); - cacheRangeIfSelectionOfDocument(newRange); + .build(), + newRange); } // https://www.w3.org/TR/selection-api/#dom-selection-collapsetoend @@ -283,8 +294,7 @@ // and then set the context object's range to the newly-created range. SelectionInDOMTree::Builder builder; builder.collapse(newRange->endPosition()); - frame()->selection().setSelection(builder.build()); - cacheRangeIfSelectionOfDocument(newRange); + updateFrameSelection(builder.build(), newRange); } // https://www.w3.org/TR/selection-api/#dom-selection-collapsetostart @@ -308,8 +318,7 @@ // and then set the context object's range to the newly-created range. SelectionInDOMTree::Builder builder; builder.collapse(newRange->startPosition()); - frame()->selection().setSelection(builder.build()); - cacheRangeIfSelectionOfDocument(newRange); + updateFrameSelection(builder.build(), newRange); } void DOMSelection::empty() { @@ -360,12 +369,6 @@ Position basePosition(baseNode, baseOffset); Position extentPosition(extentNode, extentOffset); - frame()->selection().setSelection( - SelectionInDOMTree::Builder() - .setBaseAndExtentDeprecated(basePosition, extentPosition) - .setIsDirectional(true) - .build()); - Range* newRange = Range::create(baseNode->document()); if (extentPosition.isNull()) { newRange->setStart(baseNode, baseOffset); @@ -377,7 +380,12 @@ newRange->setStart(extentNode, extentOffset); newRange->setEnd(baseNode, baseOffset); } - cacheRangeIfSelectionOfDocument(newRange); + updateFrameSelection( + SelectionInDOMTree::Builder() + .setBaseAndExtentDeprecated(basePosition, extentPosition) + .setIsDirectional(true) + .build(), + newRange); } void DOMSelection::modify(const String& alterString, @@ -509,8 +517,7 @@ builder.collapse(newFocus); else builder.collapse(oldAnchor).extend(newFocus); - frame()->selection().setSelection(builder.setIsDirectional(true).build()); - cacheRangeIfSelectionOfDocument(newRange); + updateFrameSelection(builder.setIsDirectional(true).build(), newRange); } Range* DOMSelection::getRangeAt(unsigned index, @@ -609,8 +616,11 @@ } if (rangeCount() == 0) { - selection.setSelectedRange(EphemeralRange(newRange), VP_DEFAULT_AFFINITY); - cacheRangeIfSelectionOfDocument(newRange); + updateFrameSelection(SelectionInDOMTree::Builder() + .collapse(newRange->startPosition()) + .extend(newRange->endPosition()) + .build(), + newRange); return; }
diff --git a/third_party/WebKit/Source/core/editing/DOMSelection.h b/third_party/WebKit/Source/core/editing/DOMSelection.h index c8c53d76..094a1e0 100644 --- a/third_party/WebKit/Source/core/editing/DOMSelection.h +++ b/third_party/WebKit/Source/core/editing/DOMSelection.h
@@ -108,6 +108,7 @@ bool isAvailable() const; + void updateFrameSelection(const SelectionInDOMTree&, Range*) const; // Convenience methods for accessors, does not check m_frame present. const VisibleSelection& visibleSelection() const; bool isBaseFirstInSelection() const;
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp index 84465a9..8fe6ece 100644 --- a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp +++ b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
@@ -1739,39 +1739,45 @@ return targetNode->layoutObject()->positionForPoint(selectionEndPoint); } -void updatePositionForNodeRemoval(Position& position, Node& node) { +Position computePositionForNodeRemoval(const Position& position, Node& node) { if (position.isNull()) - return; + return position; switch (position.anchorType()) { case PositionAnchorType::BeforeChildren: - if (node.isShadowIncludingInclusiveAncestorOf( - position.computeContainerNode())) - position = Position::inParentBeforeNode(node); - break; + if (!node.isShadowIncludingInclusiveAncestorOf( + position.computeContainerNode())) { + return position; + } + return Position::inParentBeforeNode(node); case PositionAnchorType::AfterChildren: - if (node.isShadowIncludingInclusiveAncestorOf( - position.computeContainerNode())) - position = Position::inParentAfterNode(node); - break; + if (!node.isShadowIncludingInclusiveAncestorOf( + position.computeContainerNode())) { + return position; + } + return Position::inParentAfterNode(node); case PositionAnchorType::OffsetInAnchor: if (position.computeContainerNode() == node.parentNode() && static_cast<unsigned>(position.offsetInContainerNode()) > - node.nodeIndex()) - position = Position(position.computeContainerNode(), - position.offsetInContainerNode() - 1); - else if (node.isShadowIncludingInclusiveAncestorOf( - position.computeContainerNode())) - position = Position::inParentBeforeNode(node); - break; + node.nodeIndex()) { + return Position(position.computeContainerNode(), + position.offsetInContainerNode() - 1); + } + if (!node.isShadowIncludingInclusiveAncestorOf( + position.computeContainerNode())) { + return position; + } + return Position::inParentBeforeNode(node); case PositionAnchorType::AfterAnchor: - if (node.isShadowIncludingInclusiveAncestorOf(position.anchorNode())) - position = Position::inParentAfterNode(node); - break; + if (!node.isShadowIncludingInclusiveAncestorOf(position.anchorNode())) + return position; + return Position::inParentAfterNode(node); case PositionAnchorType::BeforeAnchor: - if (node.isShadowIncludingInclusiveAncestorOf(position.anchorNode())) - position = Position::inParentBeforeNode(node); - break; + if (!node.isShadowIncludingInclusiveAncestorOf(position.anchorNode())) + return position; + return Position::inParentBeforeNode(node); } + NOTREACHED() << "We should handle all PositionAnchorType"; + return position; } bool isMailHTMLBlockquoteElement(const Node* node) {
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.h b/third_party/WebKit/Source/core/editing/EditingUtilities.h index a35dcfb..b8bf1cdf 100644 --- a/third_party/WebKit/Source/core/editing/EditingUtilities.h +++ b/third_party/WebKit/Source/core/editing/EditingUtilities.h
@@ -81,6 +81,8 @@ Element* rootEditableElementOf(const Position&); Element* rootEditableElementOf(const PositionInFlatTree&); Element* rootEditableElementOf(const VisiblePosition&); +ContainerNode* rootEditableElementOrTreeScopeRootNodeOf( + const VisibleSelection&); // highestEditableRoot returns the highest editable node. If the // rootEditableElement of the speicified Position is <body>, this returns the // <body>. Otherwise, this searches ancestors for the highest editable node in @@ -303,7 +305,7 @@ const Position&, const LayoutPoint& localPoint, Node* targetNode); -void updatePositionForNodeRemoval(Position&, Node&); +Position computePositionForNodeRemoval(const Position&, Node&); // ------------------------------------------------------------------------- // VisiblePosition
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.cpp b/third_party/WebKit/Source/core/editing/FrameSelection.cpp index 700cbd2d..791876c 100644 --- a/third_party/WebKit/Source/core/editing/FrameSelection.cpp +++ b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
@@ -139,15 +139,15 @@ return selectionRoot ? selectionRoot : document().documentElement(); } -ContainerNode* FrameSelection::rootEditableElementOrTreeScopeRootNode() const { - Element* selectionRoot = - computeVisibleSelectionInDOMTreeDeprecated().rootEditableElement(); +// TODO(yosin): We should move |rootEditableElementOrTreeScopeRootNodeOf()| to +// "EditingUtilities.cpp" +ContainerNode* rootEditableElementOrTreeScopeRootNodeOf( + const VisibleSelection& visibleSelection) { + Element* selectionRoot = visibleSelection.rootEditableElement(); if (selectionRoot) return selectionRoot; - Node* node = computeVisibleSelectionInDOMTreeDeprecated() - .base() - .computeContainerNode(); + Node* const node = visibleSelection.base().computeContainerNode(); return node ? &node->treeScope().rootNode() : 0; } @@ -186,6 +186,14 @@ SetSelectionOptions options, CursorAlignOnScroll align, TextGranularity granularity) { + if (setSelectionDeprecated(passedSelection, options, granularity)) + didSetSelectionDeprecated(options, align); +} + +bool FrameSelection::setSelectionDeprecated( + const SelectionInDOMTree& passedSelection, + SetSelectionOptions options, + TextGranularity granularity) { DCHECK(isAvailable()); passedSelection.assertValidFor(document()); @@ -211,7 +219,7 @@ const SelectionInDOMTree oldSelectionInDOMTree = m_selectionEditor->selectionInDOMTree(); if (oldSelectionInDOMTree == newSelection) - return; + return false; m_selectionEditor->setSelection(newSelection); scheduleVisualUpdateForPaintInvalidationIfNeeded(); @@ -223,7 +231,12 @@ m_frame->editor().respondToChangedSelection( oldSelectionInDOMTree.computeStartPosition(), options); DCHECK_EQ(currentDocument, document()); + return true; +} +void FrameSelection::didSetSelectionDeprecated(SetSelectionOptions options, + CursorAlignOnScroll align) { + const Document& currentDocument = document(); if (!selectionInDOMTree().isNone() && !(options & DoNotSetFocus)) { setFocusedNodeIfNeeded(); // |setFocusedNodeIfNeeded()| dispatches sync events "FocusOut" and
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.h b/third_party/WebKit/Source/core/editing/FrameSelection.h index da88306..d78e98a 100644 --- a/third_party/WebKit/Source/core/editing/FrameSelection.h +++ b/third_party/WebKit/Source/core/editing/FrameSelection.h
@@ -101,7 +101,6 @@ Document& document() const; LocalFrame* frame() const { return m_frame; } Element* rootEditableElementOrDocumentElement() const; - ContainerNode* rootEditableElementOrTreeScopeRootNode() const; // An implementation of |WebFrame::moveCaretSelection()| void moveCaretSelection(const IntPoint&); @@ -148,6 +147,19 @@ void selectAll(); void clear(); + // TODO(tkent): These two functions were added to fix crbug.com/695211 without + // changing focus behavior. Once we fix crbug.com/690272, we can remove these + // functions. + // setSelectionDeprecated() returns true if didSetSelectionDeprecated() should + // be called. + bool setSelectionDeprecated(const SelectionInDOMTree&, + SetSelectionOptions = CloseTyping | + ClearTypingStyle, + TextGranularity = CharacterGranularity); + void didSetSelectionDeprecated( + SetSelectionOptions = CloseTyping | ClearTypingStyle, + CursorAlignOnScroll = CursorAlignOnScroll::IfNeeded); + // Call this after doing user-triggered selections to make it easy to delete // the frame you entirely selected. void selectFrameElementInParentIfFullySelected();
diff --git a/third_party/WebKit/Source/core/editing/InputMethodController.cpp b/third_party/WebKit/Source/core/editing/InputMethodController.cpp index 8fd939a..be4e5a0 100644 --- a/third_party/WebKit/Source/core/editing/InputMethodController.cpp +++ b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
@@ -698,8 +698,8 @@ frame().selection().computeVisibleSelectionInDOMTreeDeprecated()); if (range.isNull()) return PlainTextRange(); - ContainerNode* editable = - frame().selection().rootEditableElementOrTreeScopeRootNode(); + ContainerNode* const editable = rootEditableElementOrTreeScopeRootNodeOf( + frame().selection().computeVisibleSelectionInDOMTreeDeprecated()); DCHECK(editable); return PlainTextRange::create(*editable, range); }
diff --git a/third_party/WebKit/Source/core/editing/SelectionEditor.cpp b/third_party/WebKit/Source/core/editing/SelectionEditor.cpp index 04dd0915..7d38c7e 100644 --- a/third_party/WebKit/Source/core/editing/SelectionEditor.cpp +++ b/third_party/WebKit/Source/core/editing/SelectionEditor.cpp
@@ -191,15 +191,6 @@ markCacheDirty(); } -static Position computePositionForNodeRemoval(const Position& position, - Node& nodeToBeRemoved) { - Position result = position; - // TODO(yosin): We should rename |updatePositionForNodeRemoval()| - // to |computePositionForNodeRemoval()| to avoid using output parameter. - updatePositionForNodeRemoval(result, nodeToBeRemoved); - return result; -} - void SelectionEditor::nodeWillBeRemoved(Node& nodeToBeRemoved) { if (m_selection.isNone()) return;
diff --git a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp index e8cd1338..fe67f4e2 100644 --- a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
@@ -432,7 +432,7 @@ Node& node) { int offset = position.isOffsetInAnchor() ? position.offsetInContainerNode() : 0; - updatePositionForNodeRemoval(position, node); + position = computePositionForNodeRemoval(position, node); if (offset == 0) return; position = Position(position.computeContainerNode(), offset);
diff --git a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp index 074bb7a..cb59bcd5 100644 --- a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
@@ -517,9 +517,11 @@ } // FIXME: Update the endpoints of the range being deleted. - updatePositionForNodeRemoval(m_endingPosition, *node); - updatePositionForNodeRemoval(m_leadingWhitespace, *node); - updatePositionForNodeRemoval(m_trailingWhitespace, *node); + m_endingPosition = computePositionForNodeRemoval(m_endingPosition, *node); + m_leadingWhitespace = + computePositionForNodeRemoval(m_leadingWhitespace, *node); + m_trailingWhitespace = + computePositionForNodeRemoval(m_trailingWhitespace, *node); CompositeEditCommand::removeNode(node, editingState, shouldAssumeContentIsAlwaysEditable); @@ -671,7 +673,7 @@ Node* nextNode = NodeTraversal::nextSkippingChildren(*node); // if we just removed a node from the end container, update end position // so the check above will work - updatePositionForNodeRemoval(m_downstreamEnd, *node); + m_downstreamEnd = computePositionForNodeRemoval(m_downstreamEnd, *node); removeNode(node, editingState); if (editingState->isAborted()) return;
diff --git a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp index 773302a6..a0a4b7a 100644 --- a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
@@ -1818,12 +1818,13 @@ previous->data().length() <= kMergeSizeLimit) { insertTextIntoNode(text, 0, previous->data()); - if (positionIsOffsetInAnchor) + if (positionIsOffsetInAnchor) { position = Position(position.computeContainerNode(), previous->length() + position.offsetInContainerNode()); - else - updatePositionForNodeRemoval(position, *previous); + } else { + position = computePositionForNodeRemoval(position, *previous); + } if (positionOnlyToBeUpdatedIsOffsetInAnchor) { if (positionOnlyToBeUpdated.computeContainerNode() == text) @@ -1834,7 +1835,8 @@ positionOnlyToBeUpdated = Position(text, positionOnlyToBeUpdated.offsetInContainerNode()); } else { - updatePositionForNodeRemoval(positionOnlyToBeUpdated, *previous); + positionOnlyToBeUpdated = + computePositionForNodeRemoval(positionOnlyToBeUpdated, *previous); } removeNode(previous, editingState); @@ -1850,15 +1852,17 @@ insertTextIntoNode(text, originalLength, next->data()); if (!positionIsOffsetInAnchor) - updatePositionForNodeRemoval(position, *next); + position = computePositionForNodeRemoval(position, *next); if (positionOnlyToBeUpdatedIsOffsetInAnchor && - positionOnlyToBeUpdated.computeContainerNode() == next) + positionOnlyToBeUpdated.computeContainerNode() == next) { positionOnlyToBeUpdated = Position(text, originalLength + positionOnlyToBeUpdated.offsetInContainerNode()); - else - updatePositionForNodeRemoval(positionOnlyToBeUpdated, *next); + } else { + positionOnlyToBeUpdated = + computePositionForNodeRemoval(positionOnlyToBeUpdated, *next); + } removeNode(next, editingState); if (editingState->isAborted())
diff --git a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp index 7313874..e47b8b2 100644 --- a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
@@ -85,8 +85,8 @@ frame->selection().computeVisibleSelectionInDOMTreeDeprecated()); if (range.isNull()) return PlainTextRange(); - ContainerNode* editable = - frame->selection().rootEditableElementOrTreeScopeRootNode(); + ContainerNode* const editable = rootEditableElementOrTreeScopeRootNodeOf( + frame->selection().computeVisibleSelectionInDOMTreeDeprecated()); DCHECK(editable); return PlainTextRange::create(*editable, range); }
diff --git a/third_party/WebKit/Source/core/frame/csp/CSPSourceTest.cpp b/third_party/WebKit/Source/core/frame/csp/CSPSourceTest.cpp index 36590e96..161c1e3 100644 --- a/third_party/WebKit/Source/core/frame/csp/CSPSourceTest.cpp +++ b/third_party/WebKit/Source/core/frame/csp/CSPSourceTest.cpp
@@ -187,11 +187,13 @@ *SecurityOrigin::createFromString("non-standard-scheme://a.com/")); CSPSource source(csp.get(), "", "a.com", 0, "/", CSPSource::NoWildcard, CSPSource::NoWildcard); - // TODO(mkwst, arthursonzogni): This result might be wrong. - // See http://crbug.com/692449 EXPECT_FALSE(source.matches(KURL(base, "http://a.com"))); - // TODO(mkwst, arthursonzogni): This result might be wrong. - // See http://crbug.com/692449 + + // The reason matching fails is because the host is parsed as "" when + // using a non standard scheme even though it should be parsed as "a.com" + // After adding it to the list of standard schemes it now gets parsed + // correctly. This does not matter in practice though because there is + // no way to render/load anything like "non-standard-scheme://a.com" EXPECT_FALSE(source.matches(KURL(base, "non-standard-scheme://a.com"))); } }
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.h b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.h index ae4caa2..a7f28c6 100644 --- a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.h +++ b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.h
@@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifndef CanvasAsyncBlobCreator_h +#define CanvasAsyncBlobCreator_h + #include "bindings/core/v8/ScriptPromiseResolver.h" #include "core/CoreExport.h" #include "core/dom/DOMTypedArray.h" @@ -143,3 +146,5 @@ }; } // namespace blink + +#endif // CanvasAsyncBlobCreator_h
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.cpp index 3ad812c..f50247e 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.cpp +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.cpp
@@ -36,7 +36,6 @@ LayoutSVGResourceContainer::LayoutSVGResourceContainer(SVGElement* node) : LayoutSVGHiddenContainer(node), m_isInLayout(false), - m_id(node->getIdAttribute()), m_invalidationMask(0), m_registered(false), m_isInvalidating(false) {} @@ -74,8 +73,10 @@ detachAllClients(); LayoutSVGHiddenContainer::willBeDestroyed(); - if (m_registered) - svgTreeScopeResourcesFromElement(element()).removeResource(m_id); + if (!m_registered) + return; + svgTreeScopeResourcesFromElement(element()).removeResource( + element()->getIdAttribute()); } void LayoutSVGResourceContainer::styleDidChange(StyleDifference diff, @@ -85,10 +86,12 @@ if (m_registered) return; m_registered = true; - svgTreeScopeResourcesFromElement(element()).updateResource(m_id, this); + svgTreeScopeResourcesFromElement(element()).updateResource( + element()->getIdAttribute(), this); } void LayoutSVGResourceContainer::detachAllClients() { + const AtomicString& id = element()->getIdAttribute(); for (auto* client : m_clients) { // Unlink the resource from the client's SVGResources. (The actual // removal will be signaled after processing all the clients.) @@ -101,22 +104,22 @@ // Add a pending resolution based on the id of the old resource. Element* clientElement = toElement(client->node()); svgTreeScopeResourcesFromElement(clientElement) - .addPendingResource(m_id, *clientElement); + .addPendingResource(id, *clientElement); } removeAllClientsFromCache(); } -void LayoutSVGResourceContainer::idChanged() { +void LayoutSVGResourceContainer::idChanged(const AtomicString& oldId, + const AtomicString& newId) { // Invalidate all our current clients. removeAllClientsFromCache(); // Remove old id, that is guaranteed to be present in cache. SVGTreeScopeResources& treeScopeResources = svgTreeScopeResourcesFromElement(element()); - treeScopeResources.removeResource(m_id); - m_id = element()->getIdAttribute(); - treeScopeResources.updateResource(m_id, this); + treeScopeResources.removeResource(oldId); + treeScopeResources.updateResource(newId, this); } void LayoutSVGResourceContainer::markAllClientsForInvalidation(
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.h index 1884621..f22b7f9 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.h +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.h
@@ -62,7 +62,7 @@ resourceType == RadialGradientResourceType; } - void idChanged(); + void idChanged(const AtomicString& oldId, const AtomicString& newId); void invalidateCacheAndMarkForLayout(SubtreeLayoutScope* = nullptr); @@ -99,7 +99,6 @@ void removeClient(LayoutObject*); void detachAllClients(); - AtomicString m_id; // Track global (markAllClientsForInvalidation) invals to avoid redundant // crawls. unsigned m_invalidationMask : 8;
diff --git a/third_party/WebKit/Source/core/svg/SVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGElement.cpp index 67a9d57..58a7d3fd 100644 --- a/third_party/WebKit/Source/core/svg/SVGElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGElement.cpp
@@ -904,8 +904,10 @@ LayoutObject* object = layoutObject(); // Notify resources about id changes, this is important as we cache // resources by id in SVGDocumentExtensions - if (object && object->isSVGResourceContainer()) - toLayoutSVGResourceContainer(object)->idChanged(); + if (object && object->isSVGResourceContainer()) { + toLayoutSVGResourceContainer(object)->idChanged(params.oldValue, + params.newValue); + } if (isConnected()) buildPendingResourcesIfNeeded(); invalidateInstances();
diff --git a/third_party/WebKit/Source/modules/sensor/Sensor.cpp b/third_party/WebKit/Source/modules/sensor/Sensor.cpp index e930490d..c864dda 100644 --- a/third_party/WebKit/Source/modules/sensor/Sensor.cpp +++ b/third_party/WebKit/Source/modules/sensor/Sensor.cpp
@@ -45,11 +45,6 @@ // Check the given frequency value. if (m_sensorOptions.hasFrequency()) { double frequency = m_sensorOptions.frequency(); - if (frequency <= 0.0) { - exceptionState.throwRangeError("Frequency must be positive."); - return; - } - if (frequency > SensorConfiguration::kMaxAllowedFrequency) { m_sensorOptions.setFrequency(SensorConfiguration::kMaxAllowedFrequency); ConsoleMessage* consoleMessage = ConsoleMessage::create( @@ -151,7 +146,8 @@ auto result = SensorConfiguration::New(); double defaultFrequency = m_sensorProxy->defaultConfig()->frequency; - double maximumFrequency = m_sensorProxy->maximumFrequency(); + double minimumFrequency = m_sensorProxy->frequencyLimits().first; + double maximumFrequency = m_sensorProxy->frequencyLimits().second; double frequency = m_sensorOptions.hasFrequency() ? m_sensorOptions.frequency() @@ -159,6 +155,8 @@ if (frequency > maximumFrequency) frequency = maximumFrequency; + if (frequency < minimumFrequency) + frequency = minimumFrequency; result->frequency = frequency; return result; @@ -248,7 +246,8 @@ m_configuration = createSensorConfig(); DCHECK(m_configuration); DCHECK(m_configuration->frequency > 0 && - m_configuration->frequency <= m_sensorProxy->maximumFrequency()); + m_configuration->frequency <= + SensorConfiguration::kMaxAllowedFrequency); } auto startCallback =
diff --git a/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp b/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp index 6caf643..baa7be2 100644 --- a/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp +++ b/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp
@@ -24,8 +24,7 @@ m_provider(provider), m_clientBinding(this), m_state(SensorProxy::Uninitialized), - m_suspended(false), - m_maximumFrequency(0.0) {} + m_suspended(false) {} SensorProxy::~SensorProxy() {} @@ -211,9 +210,14 @@ handleSensorError(); return; } + m_frequencyLimits.first = params->minimum_frequency; + m_frequencyLimits.second = params->maximum_frequency; - m_maximumFrequency = params->maximum_frequency; - DCHECK(m_maximumFrequency <= SensorConfiguration::kMaxAllowedFrequency); + DCHECK_GT(m_frequencyLimits.first, 0.0); + DCHECK_GE(m_frequencyLimits.second, m_frequencyLimits.first); + constexpr double kMaxAllowedFrequency = + SensorConfiguration::kMaxAllowedFrequency; + DCHECK_GE(kMaxAllowedFrequency, m_frequencyLimits.second); auto errorCallback = WTF::bind(&SensorProxy::handleSensorError, wrapWeakPersistent(this));
diff --git a/third_party/WebKit/Source/modules/sensor/SensorProxy.h b/third_party/WebKit/Source/modules/sensor/SensorProxy.h index 91434ebf..65baab79 100644 --- a/third_party/WebKit/Source/modules/sensor/SensorProxy.h +++ b/third_party/WebKit/Source/modules/sensor/SensorProxy.h
@@ -81,7 +81,9 @@ const device::mojom::blink::SensorConfiguration* defaultConfig() const; - double maximumFrequency() const { return m_maximumFrequency; } + const std::pair<double, double>& frequencyLimits() const { + return m_frequencyLimits; + } Document* document() const; const WTF::Vector<double>& frequenciesUsed() const { @@ -138,7 +140,7 @@ mojo::ScopedSharedBufferMapping m_sharedBuffer; bool m_suspended; device::SensorReading m_reading; - double m_maximumFrequency; + std::pair<double, double> m_frequencyLimits; Member<SensorReadingUpdater> m_readingUpdater; WTF::Vector<double> m_frequenciesUsed;
diff --git a/third_party/WebKit/Source/platform/heap/PageMemory.cpp b/third_party/WebKit/Source/platform/heap/PageMemory.cpp index 967c764c..faa6548 100644 --- a/third_party/WebKit/Source/platform/heap/PageMemory.cpp +++ b/third_party/WebKit/Source/platform/heap/PageMemory.cpp
@@ -72,7 +72,6 @@ } PageMemoryRegion* RegionTree::lookup(Address address) { - MutexLocker locker(m_mutex); RegionTreeNode* current = m_root; while (current) { Address base = current->m_region->base(); @@ -93,7 +92,6 @@ void RegionTree::add(PageMemoryRegion* region) { ASSERT(region); RegionTreeNode* newTree = new RegionTreeNode(region); - MutexLocker locker(m_mutex); newTree->addTo(&m_root); } @@ -108,11 +106,6 @@ } void RegionTree::remove(PageMemoryRegion* region) { - // Deletion of large objects (and thus their regions) can happen - // concurrently on sweeper threads. Removal can also happen during thread - // shutdown, but that case is safe. Regardless, we make all removals - // mutually exclusive. - MutexLocker locker(m_mutex); ASSERT(region); ASSERT(m_root); Address base = region->base();
diff --git a/third_party/WebKit/Source/platform/heap/PageMemory.h b/third_party/WebKit/Source/platform/heap/PageMemory.h index 6e1e87a..a217ea8c 100644 --- a/third_party/WebKit/Source/platform/heap/PageMemory.h +++ b/third_party/WebKit/Source/platform/heap/PageMemory.h
@@ -11,11 +11,6 @@ #include "wtf/Compiler.h" #include "wtf/allocator/Partitions.h" -#if OS(POSIX) -#include <sys/mman.h> -#include <unistd.h> -#endif - namespace blink { class RegionTree; @@ -122,7 +117,6 @@ PageMemoryRegion* lookup(Address); private: - Mutex m_mutex; RegionTreeNode* m_root; }; @@ -174,6 +168,15 @@ WARN_UNUSED_RESULT bool commit() { m_reserved->markPageUsed(writableStart()); + // Check that in-use page isn't also marked as being a non-heap page + // by the current heap's negative cache. That cache is invalidated + // when allocating new pages, but crbug.com/649485 suggests that + // we do get out of sync somehow. + // + // TODO(sof): consider removing check once bug has been diagnosed + // and addressed. + CHECK(!ThreadState::current()->isAddressInHeapDoesNotContainCache( + writableStart())); return m_writable.commit(); }
diff --git a/third_party/WebKit/Source/platform/heap/ThreadState.cpp b/third_party/WebKit/Source/platform/heap/ThreadState.cpp index 9b8d8098..09617fb 100644 --- a/third_party/WebKit/Source/platform/heap/ThreadState.cpp +++ b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
@@ -1086,6 +1086,15 @@ } #endif +bool ThreadState::isAddressInHeapDoesNotContainCache(Address address) { + // If the cache has been marked as invalidated, it's cleared prior + // to performing the next GC. Hence, consider the cache as being + // effectively empty. + if (m_shouldFlushHeapDoesNotContainCache) + return false; + return heap().m_heapDoesNotContainCache->lookup(address); +} + size_t ThreadState::objectPayloadSizeForTesting() { size_t objectPayloadSize = 0; for (int i = 0; i < BlinkGC::NumberOfArenas; ++i)
diff --git a/third_party/WebKit/Source/platform/heap/ThreadState.h b/third_party/WebKit/Source/platform/heap/ThreadState.h index 522977f..70919b6 100644 --- a/third_party/WebKit/Source/platform/heap/ThreadState.h +++ b/third_party/WebKit/Source/platform/heap/ThreadState.h
@@ -379,6 +379,8 @@ m_shouldFlushHeapDoesNotContainCache = true; } + bool isAddressInHeapDoesNotContainCache(Address); + void registerTraceDOMWrappers( v8::Isolate* isolate, void (*traceDOMWrappers)(v8::Isolate*, Visitor*),
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp index fb2bdcf..d62e6a12 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp +++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
@@ -800,6 +800,14 @@ if (!existingResource) return Load; + // If the existing resource is loading and the associated fetcher is not equal + // to |this|, we must not use the resource. Otherwise, CSP violation may + // happen in redirect handling. + if (existingResource->loader() && + existingResource->loader()->fetcher() != this) { + return Reload; + } + // Checks if the resource has an explicit policy about integrity metadata. // // This is necessary because ScriptResource and CSSStyleSheetResource objects
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcherTest.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcherTest.cpp index 6be9d2a9..9e23fdb 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcherTest.cpp +++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcherTest.cpp
@@ -647,13 +647,14 @@ Resource* resource = MockResource::fetch(fetchRequestOriginal, fetcher); ASSERT_TRUE(resource); EXPECT_TRUE(resource->isLinkPreload()); + EXPECT_FALSE(fetcher->isFetching()); fetcher->preloadStarted(resource); // Resource created by parser on the second fetcher FetchRequest fetchRequest2 = FetchRequest(url, FetchInitiatorInfo()); Resource* newResource2 = MockResource::fetch(fetchRequest2, fetcher2); Persistent<MockResourceClient> client2 = new MockResourceClient(newResource2); - EXPECT_EQ(resource, newResource2); + EXPECT_NE(resource, newResource2); EXPECT_FALSE(fetcher2->isFetching()); Platform::current()->getURLLoaderMockFactory()->serveAsynchronousRequests(); }
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.h b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.h index 57895587..94a3c53 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.h +++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.h
@@ -74,6 +74,8 @@ return m_isCacheAwareLoadingActivated; } + ResourceFetcher* fetcher() { return m_fetcher; } + // WebURLLoaderClient // // A succesful load will consist of:
diff --git a/third_party/widevine/cdm/BUILD.gn b/third_party/widevine/cdm/BUILD.gn index 413b1fa2..34ae399f 100644 --- a/third_party/widevine/cdm/BUILD.gn +++ b/third_party/widevine/cdm/BUILD.gn
@@ -42,10 +42,7 @@ widevine_cdm_manifest_file = [ "win/$widevine_arch/manifest.json" ] } else if (is_mac) { widevine_cdm_version_h_file = "mac/$widevine_arch/widevine_cdm_version.h" - widevine_cdm_binary_files = [ - "mac/$widevine_arch/libwidevinecdm.dylib", - "mac/$widevine_arch/libwidevinecdm.dylib.sig", - ] + widevine_cdm_binary_files = [ "mac/$widevine_arch/libwidevinecdm.dylib" ] widevine_cdm_manifest_file = [ "mac/$widevine_arch/manifest.json" ] } else { # Other platforms, use the default one.
diff --git a/third_party/widevine/cdm/widevine.gni b/third_party/widevine/cdm/widevine.gni index a0b3164..b10a92b 100644 --- a/third_party/widevine/cdm/widevine.gni +++ b/third_party/widevine/cdm/widevine.gni
@@ -6,35 +6,3 @@ # Allow widevinecdmadapter to be built in Chromium. enable_widevine = false } - -template("widevine_sign_file") { - # For official builds, generate a signature file for |file| which will - # be used by Widevine. If |signature_file| is not specified, the signature - # file will be in the same directory as |file|. - action(target_name) { - forward_variables_from(invoker, - [ - "file", - "signature_file", - "deps", - ]) - assert(defined(file), "File to be signed must be specified.") - if (!defined(signature_file)) { - signature_file = "$file.sig" - } - - script = "//third_party/widevine/scripts/signature_generator.py" - sources = [ - "$file", - ] - outputs = [ - "$signature_file", - ] - args = [ - "--input_file", - rebase_path("$file", root_build_dir), - "--output_file", - rebase_path("$signature_file", root_build_dir), - ] - } -}
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index b3867068..8aef59a 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -62410,16 +62410,17 @@ </histogram> <histogram name="SessionRestore.AllTabsLoaded" units="ms"> - <owner>jeremy@chromium.org</owner> - <owner>sky@chromium.org</owner> + <owner>chrisha@chromium.org</owner> + <owner>georgesak@chromium.org</owner> <summary> The time from SessionRestore start until all tabs have finished loading. </summary> </histogram> <histogram name="SessionRestore.command_size" units="bytes"> - <owner>jeremy@chromium.org</owner> - <owner>sky@chromium.org</owner> + <obsolete> + Deprecated 2017-02 as not actionable. + </obsolete> <summary> The size of the commands written to disk. See SessionBackend for details. </summary> @@ -62436,8 +62437,8 @@ </histogram> <histogram name="SessionRestore.ForegroundTabFirstLoaded" units="ms"> - <owner>jeremy@chromium.org</owner> - <owner>sky@chromium.org</owner> + <owner>chrisha@chromium.org</owner> + <owner>georgesak@chromium.org</owner> <summary> The time from SessionRestore start until a visible tab has finished loading. </summary> @@ -62470,8 +62471,7 @@ <histogram name="SessionRestore.ForegroundTabFirstPaint3" units="ms"> <owner>chrisha@chromium.org</owner> - <owner>jeremy@chromium.org</owner> - <owner>sky@chromium.org</owner> + <owner>georgesak@chromium.org</owner> <summary> The time from SessionRestore start until a visible tab's first paint. </summary> @@ -62488,14 +62488,16 @@ </histogram> <histogram name="SessionRestore.last_session_file_size" units="KB"> - <owner>jeremy@chromium.org</owner> - <owner>sky@chromium.org</owner> + <obsolete> + Deprecated 2017-02 as not actionable. + </obsolete> <summary>The size, in k, of the last session file on disk.</summary> </histogram> <histogram name="SessionRestore.NavEntryCommittedLongPeriod"> - <owner>jeremy@chromium.org</owner> - <owner>sky@chromium.org</owner> + <obsolete> + Deprecated 2017-02 as not actionable. + </obsolete> <summary> Like NavEntryCommittedPeriod, but specifically to provide a clearer breakdown of samples in the 10 minutes - 8 hours range. @@ -62503,8 +62505,9 @@ </histogram> <histogram name="SessionRestore.NavEntryCommittedPeriod" units="ms"> - <owner>jeremy@chromium.org</owner> - <owner>sky@chromium.org</owner> + <obsolete> + Deprecated 2017-02 as not actionable. + </obsolete> <summary> Milliseconds between subsequent Save() operations due to a nav entry being committed (new tab created + nav initiated). @@ -62512,8 +62515,9 @@ </histogram> <histogram name="SessionRestore.NavigationListPrunedLongPeriod"> - <owner>jeremy@chromium.org</owner> - <owner>sky@chromium.org</owner> + <obsolete> + Deprecated 2017-02 as not actionable. + </obsolete> <summary> Like NavListPrunedPeriod, but specifically to provide a clearer breakdown of samples in the 10 minutes - 8 hours range. @@ -62521,8 +62525,9 @@ </histogram> <histogram name="SessionRestore.NavigationListPrunedPeriod" units="ms"> - <owner>jeremy@chromium.org</owner> - <owner>sky@chromium.org</owner> + <obsolete> + Deprecated 2017-02 as not actionable. + </obsolete> <summary> Milliseconds between subsequent Save() operations due to the navigation list being pruned (typically a change in back/forward stacks). @@ -62530,16 +62535,18 @@ </histogram> <histogram name="SessionRestore.ParallelTabLoads"> - <owner>jeremy@chromium.org</owner> - <owner>sky@chromium.org</owner> + <obsolete> + Deprecated 2017-02 as not actionable. + </obsolete> <summary> The number of tabs that were loaded simultaneously when restoring a session. </summary> </histogram> <histogram name="SessionRestore.read_session_file_time" units="ms"> - <owner>jeremy@chromium.org</owner> - <owner>sky@chromium.org</owner> + <obsolete> + Deprecated 2017-02 as not actionable. + </obsolete> <summary> Amount of time to read and assemble the commands from the last session. </summary> @@ -62565,8 +62572,9 @@ </histogram> <histogram name="SessionRestore.SaveLongPeriod"> - <owner>jeremy@chromium.org</owner> - <owner>sky@chromium.org</owner> + <obsolete> + Deprecated 2017-02 as not actionable. + </obsolete> <summary> Like SavePeriod, but specifically to provide a clearer breakdown of samples in the 10 minutes - 8 hours range. @@ -62574,8 +62582,9 @@ </histogram> <histogram name="SessionRestore.SavePeriod" units="ms"> - <owner>jeremy@chromium.org</owner> - <owner>sky@chromium.org</owner> + <obsolete> + Deprecated 2017-02 as not actionable. + </obsolete> <summary> Amount of time between subsequent SessionService Save() operations (aka updates to session data). @@ -62604,8 +62613,9 @@ </histogram> <histogram name="SessionRestore.TabClosedLongPeriod"> - <owner>jeremy@chromium.org</owner> - <owner>sky@chromium.org</owner> + <obsolete> + Deprecated 2017-02 as not actionable. + </obsolete> <summary> TabClosedPeriod, but specifically to provide a clearer breakdown of samples in the 10 minutes - 8 hours range. @@ -62613,8 +62623,9 @@ </histogram> <histogram name="SessionRestore.TabClosedPeriod" units="ms"> - <owner>jeremy@chromium.org</owner> - <owner>sky@chromium.org</owner> + <obsolete> + Deprecated 2017-02 as not actionable. + </obsolete> <summary> Milliseconds between subsequent Save() operations due to a tab being closed. </summary> @@ -66856,7 +66867,6 @@ </histogram> <histogram name="Startup.ShowAppListColdStart" units="ms"> - <owner>jeremy@chromium.org</owner> <owner>tapted@chromium.org</owner> <summary> Time for a newly created browser process to reach the code that starts @@ -66866,7 +66876,6 @@ </histogram> <histogram name="Startup.ShowAppListWarmStart" units="ms"> - <owner>jeremy@chromium.org</owner> <owner>tapted@chromium.org</owner> <summary> Time for a running browser process to reach the code that starts showing the @@ -69396,7 +69405,6 @@ </histogram> <histogram name="Sync.Startup.TimeDeferred2" units="ms"> - <owner>jeremy@chromium.org</owner> <owner>zea@google.com</owner> <summary> Time spent after ProfileSyncService *creation* but before SyncEngine @@ -85194,6 +85202,7 @@ <int value="35" label="NTPSnippets suggestions"/> <int value="36" label="NTPSnippets thumbnails"/> <int value="37" label="Doodle"/> + <int value="38" label="UKM"/> </enum> <enum name="DecodedImageOrientation" type="int">
diff --git a/ui/gl/gl_context_glx.cc b/ui/gl/gl_context_glx.cc index 8f823ef..145162d 100644 --- a/ui/gl/gl_context_glx.cc +++ b/ui/gl/gl_context_glx.cc
@@ -71,69 +71,68 @@ GLXContext CreateHighestVersionContext(Display* display, GLXFBConfig config, GLXContext share) { - // It is commonly assumed that glXCreateContextAttrib will create a context - // of the highest version possible but it is not specified in the spec and - // is not true on the Mesa drivers. On Mesa, Instead we try to create a - // context per GL version until we succeed, starting from newer version. - // On both Mesa and other drivers we try to create a desktop context and fall - // back to ES context. - // The code could be simpler if the Mesa code path was used for all drivers, - // however the cost of failing a context creation can be high (3 milliseconds - // for the NVIDIA driver). The good thing is that failed context creation only - // takes 0.1 milliseconds on Mesa. + // The only way to get a core profile context of the highest version using + // glXCreateContextAttrib is to try creationg contexts in decreasing version + // numbers. It might look that asking for a core context of version (0, 0) + // works on some driver but it create a _compatibility_ context of the highest + // version instead. The cost of failing a context creation is small (< 0.1 ms) + // on Mesa but is unfortunately a bit expensive on the Nvidia driver (~3ms). - struct ContextCreationInfo { - int profileFlag; - GLVersion version; - }; - - // clang-format off - // For regular drivers we try to create a compatibility, core, then ES - // context. Without requiring any specific version. - const ContextCreationInfo contexts_to_try[] = { - { 0, GLVersion(0, 0) }, - { GLX_CONTEXT_CORE_PROFILE_BIT_ARB, GLVersion(0, 0) }, - { GLX_CONTEXT_ES2_PROFILE_BIT_EXT, GLVersion(0, 0) }, - }; - - // On Mesa we try to create a core context, except for versions below 3.2 - // where it is not applicable. (and fallback to ES as well) - const ContextCreationInfo mesa_contexts_to_try[] = { - { GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { GLVersion(4, 5) } }, - { GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { GLVersion(4, 4) } }, - { GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { GLVersion(4, 3) } }, - { GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { GLVersion(4, 2) } }, - { GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { GLVersion(4, 1) } }, - { GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { GLVersion(4, 0) } }, - { GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { GLVersion(3, 3) } }, - // Do not try to create OpenGL context versions between 3.0 and - // 3.2 because of compatibility problems. crbug.com/659030 - { 0, { GLVersion(2, 0) } }, - { 0, { GLVersion(1, 5) } }, - { 0, { GLVersion(1, 4) } }, - { 0, { GLVersion(1, 3) } }, - { 0, { GLVersion(1, 2) } }, - { 0, { GLVersion(1, 1) } }, - { 0, { GLVersion(1, 0) } }, - { GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { GLVersion(3, 2) } }, - { GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { GLVersion(3, 1) } }, - { GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { GLVersion(3, 0) } }, - { GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { GLVersion(2, 0) } }, - }; - // clang-format on + // Also try to get any Desktop GL context, but if that fails fallback to + // asking for OpenGL ES contexts. std::string client_vendor = glXGetClientString(display, GLX_VENDOR); bool is_mesa = client_vendor.find("Mesa") != std::string::npos; - const ContextCreationInfo* to_try = contexts_to_try; - size_t to_try_length = arraysize(contexts_to_try); - if (is_mesa) { - to_try = mesa_contexts_to_try; - to_try_length = arraysize(mesa_contexts_to_try); + struct ContextCreationInfo { + ContextCreationInfo(int profileFlag, GLVersion version) + : profileFlag(profileFlag), version(version) {} + int profileFlag; + GLVersion version; + }; + + std::vector<ContextCreationInfo> contexts_to_try; + contexts_to_try.emplace_back(GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + GLVersion(4, 5)); + contexts_to_try.emplace_back(GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + GLVersion(4, 4)); + contexts_to_try.emplace_back(GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + GLVersion(4, 3)); + contexts_to_try.emplace_back(GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + GLVersion(4, 2)); + contexts_to_try.emplace_back(GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + GLVersion(4, 1)); + contexts_to_try.emplace_back(GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + GLVersion(4, 0)); + contexts_to_try.emplace_back(GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + GLVersion(3, 3)); + + // On Mesa, do not try to create OpenGL context versions between 3.0 and + // 3.2 because of compatibility problems. See crbug.com/659030 + if (!is_mesa) { + contexts_to_try.emplace_back(0, GLVersion(3, 2)); + contexts_to_try.emplace_back(0, GLVersion(3, 1)); + contexts_to_try.emplace_back(0, GLVersion(3, 0)); } - for (size_t i = 0; i < to_try_length; ++i) { - const ContextCreationInfo& info = to_try[i]; + contexts_to_try.emplace_back(0, GLVersion(2, 1)); + contexts_to_try.emplace_back(0, GLVersion(2, 0)); + contexts_to_try.emplace_back(0, GLVersion(1, 5)); + contexts_to_try.emplace_back(0, GLVersion(1, 4)); + contexts_to_try.emplace_back(0, GLVersion(1, 3)); + contexts_to_try.emplace_back(0, GLVersion(1, 2)); + contexts_to_try.emplace_back(0, GLVersion(1, 1)); + contexts_to_try.emplace_back(0, GLVersion(1, 0)); + contexts_to_try.emplace_back(GLX_CONTEXT_ES2_PROFILE_BIT_EXT, + GLVersion(3, 2)); + contexts_to_try.emplace_back(GLX_CONTEXT_ES2_PROFILE_BIT_EXT, + GLVersion(3, 1)); + contexts_to_try.emplace_back(GLX_CONTEXT_ES2_PROFILE_BIT_EXT, + GLVersion(3, 0)); + contexts_to_try.emplace_back(GLX_CONTEXT_ES2_PROFILE_BIT_EXT, + GLVersion(2, 0)); + + for (const auto& info : contexts_to_try) { if (!GLSurfaceGLX::IsCreateContextES2ProfileSupported() && info.profileFlag == GLX_CONTEXT_ES2_PROFILE_BIT_EXT) { continue;