diff --git a/DEPS b/DEPS index 96267a9..ec1a3f7 100644 --- a/DEPS +++ b/DEPS
@@ -40,7 +40,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'ac44d69a7dba219efc6ead5d76ad364ab79bddab', + 'skia_revision': '87185f7539f4e55fbf2e5eea458b8980c34a8d1d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerDelegate.java index ddee6f6..97dc2ff 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerDelegate.java
@@ -12,6 +12,7 @@ import android.os.AsyncTask; import android.os.Build; import android.support.v4.app.NotificationManagerCompat; +import android.text.TextUtils; import org.chromium.base.ContextUtils; import org.chromium.base.Log; @@ -94,8 +95,9 @@ Class[] args = {String.class, String.class, boolean.class, String.class, String.class, long.class, boolean.class, Uri.class, Uri.class}; Method method = c.getMethod("addCompletedDownload", args); - Uri originalUri = Uri.parse(originalUrl); - Uri refererUri = referer == null ? Uri.EMPTY : Uri.parse(referer); + // OriginalUri has to be null or non-empty. + Uri originalUri = TextUtils.isEmpty(originalUrl) ? null : Uri.parse(originalUrl); + Uri refererUri = TextUtils.isEmpty(referer) ? null : Uri.parse(referer); downloadId = (Long) method.invoke(manager, fileName, description, true, mimeType, path, length, useSystemNotification, originalUri, refererUri); } catch (SecurityException e) {
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index de8d3c9..f24005e 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -6321,12 +6321,6 @@ This is to be used in conjunction with the trace-upload-url flag. WARNING: When enabled, Chrome will record performance data for every navigation and upload it to the URL specified by the trace-upload-url flag. The trace may include personally identifiable information (PII) such as the titles and URLs of websites you visit. </message> - <message name="IDS_FLAGS_ENABLE_NON_VALIDATING_RELOAD_ON_NORMAL_RELOAD_NAME" desc="Name of the flag to enable non-validating reload"> - Enable non-validating reload - </message> - <message name="IDS_FLAGS_ENABLE_NON_VALIDATING_RELOAD_ON_NORMAL_RELOAD_DESCRIPTION" desc="Description of the flag to enable non-validating reload"> - Forces reload UIs trigger non-validating reload (while it usually means regular, cache-validating reload when the flag is disabled). - </message> <message name="IDS_FLAGS_TRACE_UPLOAD_URL" desc="Name of the flag to set the trace upload url"> Trace label for navigation tracing </message>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 53b0a78..d7725b1 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1060,10 +1060,6 @@ {"enable-navigation-tracing", IDS_FLAGS_ENABLE_NAVIGATION_TRACING, IDS_FLAGS_ENABLE_NAVIGATION_TRACING_DESCRIPTION, kOsAll, SINGLE_VALUE_TYPE(switches::kEnableNavigationTracing)}, - {"enable-non-validating-reload-on-normal-reload", - IDS_FLAGS_ENABLE_NON_VALIDATING_RELOAD_ON_NORMAL_RELOAD_NAME, - IDS_FLAGS_ENABLE_NON_VALIDATING_RELOAD_ON_NORMAL_RELOAD_DESCRIPTION, - kOsAll, FEATURE_VALUE_TYPE(features::kNonValidatingReloadOnNormalReload)}, {"trace-upload-url", IDS_FLAGS_TRACE_UPLOAD_URL, IDS_FLAGS_TRACE_UPLOAD_URL_DESCRIPTION, kOsAll, MULTI_VALUE_TYPE(kTraceUploadURL)},
diff --git a/chrome/browser/android/download/download_manager_service.cc b/chrome/browser/android/download/download_manager_service.cc index 02a56b1..01429006 100644 --- a/chrome/browser/android/download/download_manager_service.cc +++ b/chrome/browser/android/download/download_manager_service.cc
@@ -93,7 +93,8 @@ base::TimeDelta time_delta; item->TimeRemaining(&time_delta); - + std::string original_url = item->GetOriginalUrl().SchemeIs(url::kDataScheme) + ? std::string() : item->GetOriginalUrl().spec(); return Java_DownloadInfo_createDownloadInfo( env, ConvertUTF8ToJavaString(env, item->GetGuid()), @@ -109,7 +110,7 @@ item->IsPaused(), has_user_gesture, item->CanResume(), - ConvertUTF8ToJavaString(env, item->GetOriginalUrl().spec()), + ConvertUTF8ToJavaString(env, original_url), ConvertUTF8ToJavaString(env, item->GetReferrerUrl().spec()), time_delta.InMilliseconds()); }
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.html b/chrome/browser/resources/settings/languages_page/languages_page.html index 5e7314a1..31eef10 100644 --- a/chrome/browser/resources/settings/languages_page/languages_page.html +++ b/chrome/browser/resources/settings/languages_page/languages_page.html
@@ -89,9 +89,11 @@ <span class="list-item" hidden="[[isHelpTextHidden_(languages.enabled.*)]]"> <span>$i18n{orderLanguagesInstructions}</span> +<if expr="chromeos"> <a href="$i18n{languagesLearnMoreURL}" target="_blank"> $i18n{learnMore} </a> +</if> </span> <template is="dom-repeat" items="[[languages.enabled]]"> <div class$="list-item [[getLanguageItemClass_(
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index 01f24cd..5843541 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -917,9 +917,13 @@ AddLocalizedStringsBulk(html_source, localized_strings, arraysize(localized_strings)); +#if defined(OS_CHROMEOS) + // Only the Chrome OS help article explains how language order affects website + // language. html_source->AddString( "languagesLearnMoreURL", base::ASCIIToUTF16(chrome::kLanguageSettingsLearnMoreUrl)); +#endif } #if defined(OS_CHROMEOS)
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc index 2b04d80..b703ab75 100644 --- a/chrome/common/url_constants.cc +++ b/chrome/common/url_constants.cc
@@ -619,6 +619,7 @@ // Add hosts here to be included in chrome://chrome-urls (about:about). // These hosts will also be suggested by BuiltinProvider. const char* const kChromeHostURLs[] = { + kChromeUIAboutHost, kChromeUIBluetoothInternalsHost, kChromeUICacheHost, kChromeUIChromeURLsHost, @@ -644,6 +645,7 @@ kChromeUIPredictorsHost, kChromeUIProfilerHost, kChromeUISignInInternalsHost, + kChromeUISiteEngagementHost, kChromeUISuggestionsHost, kChromeUISupervisedUserInternalsHost, kChromeUISyncInternalsHost,
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h index 58e4470..8b623619 100644 --- a/chrome/common/url_constants.h +++ b/chrome/common/url_constants.h
@@ -581,6 +581,7 @@ extern const char kMediaAccessLearnMoreUrl[]; // The URL for the "Learn more" link in the language settings. +// TODO(michaelpg): Compile on Chrome OS only when Options is removed. extern const char kLanguageSettingsLearnMoreUrl[]; #if defined(GOOGLE_CHROME_BUILD) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
diff --git a/chrome/renderer/net/net_error_helper.cc b/chrome/renderer/net/net_error_helper.cc index 42432411..c2d7a37d 100644 --- a/chrome/renderer/net/net_error_helper.cc +++ b/chrome/renderer/net/net_error_helper.cc
@@ -315,7 +315,7 @@ void NetErrorHelper::ReloadPage(bool bypass_cache) { render_frame()->GetWebFrame()->reload( bypass_cache ? blink::WebFrameLoadType::ReloadBypassingCache - : blink::WebFrameLoadType::Reload); + : blink::WebFrameLoadType::ReloadMainResource); } void NetErrorHelper::LoadPageFromCache(const GURL& page_url) {
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 96d224c..60baf186 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -9038.0.0 \ No newline at end of file +9041.0.0 \ No newline at end of file
diff --git a/components/subresource_filter/content/renderer/document_subresource_filter.cc b/components/subresource_filter/content/renderer/document_subresource_filter.cc index f17a1ca..8e326a9e 100644 --- a/components/subresource_filter/content/renderer/document_subresource_filter.cc +++ b/components/subresource_filter/content/renderer/document_subresource_filter.cc
@@ -12,6 +12,7 @@ #include "base/trace_event/trace_event.h" #include "components/subresource_filter/core/common/first_party_origin.h" #include "components/subresource_filter/core/common/memory_mapped_ruleset.h" +#include "components/subresource_filter/core/common/scoped_timers.h" #include "third_party/WebKit/public/platform/WebURL.h" namespace subresource_filter { @@ -87,6 +88,11 @@ ? std::string() : ancestor_document_urls[0].spec()); + SCOPED_UMA_HISTOGRAM_MICRO_TIMER( + "SubresourceFilter.DocumentLoad.Activation.WallDuration"); + SCOPED_UMA_HISTOGRAM_MICRO_THREAD_TIMER( + "SubresourceFilter.DocumentLoad.Activation.CPUDuration"); + DCHECK_NE(activation_state_, ActivationState::DISABLED); DCHECK(ruleset); @@ -124,6 +130,19 @@ TRACE_EVENT1("loader", "DocumentSubresourceFilter::allowLoad", "url", resourceUrl.string().utf8()); + auto wall_duration_exporter = [this](base::TimeDelta delta) { + statistics_.evaluation_total_wall_duration += delta; + UMA_HISTOGRAM_MICRO_TIMES( + "SubresourceFilter.SubresourceLoad.Evaluation.WallDuration", delta); + }; + auto cpu_duration_exporter = [this](base::TimeDelta delta) { + statistics_.evaluation_total_cpu_duration += delta; + UMA_HISTOGRAM_MICRO_TIMES( + "SubresourceFilter.SubresourceLoad.Evaluation.CPUDuration", delta); + }; + SCOPED_TIMER(wall_duration_exporter); + SCOPED_THREAD_TIMER(cpu_duration_exporter); + ++statistics_.num_loads_total; if (filtering_disabled_for_document_)
diff --git a/components/subresource_filter/content/renderer/document_subresource_filter.h b/components/subresource_filter/content/renderer/document_subresource_filter.h index fb72370..3858131 100644 --- a/components/subresource_filter/content/renderer/document_subresource_filter.h +++ b/components/subresource_filter/content/renderer/document_subresource_filter.h
@@ -13,6 +13,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "base/time/time.h" #include "components/subresource_filter/core/common/activation_state.h" #include "components/subresource_filter/core/common/indexed_ruleset.h" #include "third_party/WebKit/public/platform/WebDocumentSubresourceFilter.h" @@ -29,7 +30,6 @@ : public blink::WebDocumentSubresourceFilter, public base::SupportsWeakPtr<DocumentSubresourceFilter> { public: - // TODO(pkalinnikov): Add total evaluation time metrics. struct Statistics { // The number of subresource loads that went through the allowLoad method. size_t num_loads_total = 0; @@ -40,6 +40,10 @@ size_t num_loads_evaluated = 0; size_t num_loads_matching_rules = 0; size_t num_loads_disallowed = 0; + + // Total time spent in allowLoad() calls while evaluating subresource loads. + base::TimeDelta evaluation_total_wall_duration; + base::TimeDelta evaluation_total_cpu_duration; }; // Constructs a new filter that will:
diff --git a/components/subresource_filter/content/renderer/subresource_filter_agent.cc b/components/subresource_filter/content/renderer/subresource_filter_agent.cc index 3eb3a21..6e6c1aa 100644 --- a/components/subresource_filter/content/renderer/subresource_filter_agent.cc +++ b/components/subresource_filter/content/renderer/subresource_filter_agent.cc
@@ -7,10 +7,12 @@ #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/metrics/histogram_macros.h" +#include "base/time/time.h" #include "components/subresource_filter/content/common/subresource_filter_messages.h" #include "components/subresource_filter/content/renderer/document_subresource_filter.h" #include "components/subresource_filter/content/renderer/ruleset_dealer.h" #include "components/subresource_filter/core/common/memory_mapped_ruleset.h" +#include "components/subresource_filter/core/common/scoped_timers.h" #include "content/public/common/browser_side_navigation_policy.h" #include "content/public/renderer/render_frame.h" #include "ipc/ipc_message.h" @@ -93,6 +95,22 @@ UMA_HISTOGRAM_COUNTS_1000( "SubresourceFilter.DocumentLoad.NumSubresourceLoads.Disallowed", statistics.num_loads_disallowed); + + UMA_HISTOGRAM_CUSTOM_MICRO_TIMES( + "SubresourceFilter.DocumentLoad.SubresourceEvaluation." + "TotalWallDuration", + statistics.evaluation_total_wall_duration, + base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(10), + 50); + + // If ThreadTicks is not supported, then no measurements have been collected. + if (base::ThreadTicks::IsSupported()) { + UMA_HISTOGRAM_CUSTOM_MICRO_TIMES( + "SubresourceFilter.DocumentLoad.SubresourceEvaluation.TotalCPUDuration", + statistics.evaluation_total_cpu_duration, + base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(10), + 50); + } } void SubresourceFilterAgent::OnDestruct() {
diff --git a/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc b/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc index 0911fd9c..992053a3 100644 --- a/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc +++ b/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/strings/string_piece.h" #include "base/test/histogram_tester.h" +#include "base/time/time.h" #include "components/subresource_filter/content/common/subresource_filter_messages.h" #include "components/subresource_filter/content/renderer/ruleset_dealer.h" #include "components/subresource_filter/core/common/test_ruleset_creator.h" @@ -83,6 +84,10 @@ "SubresourceFilter.DocumentLoad.NumSubresourceLoads.MatchedRules"; constexpr const char kSubresourcesDisallowed[] = "SubresourceFilter.DocumentLoad.NumSubresourceLoads.Disallowed"; +constexpr const char kEvaluationTotalWallDuration[] = + "SubresourceFilter.DocumentLoad.SubresourceEvaluation.TotalWallDuration"; +constexpr const char kEvaluationTotalCPUDuration[] = + "SubresourceFilter.DocumentLoad.SubresourceEvaluation.TotalCPUDuration"; } // namespace @@ -321,6 +326,9 @@ histogram_tester.ExpectTotalCount(kSubresourcesEvaluated, 0); histogram_tester.ExpectTotalCount(kSubresourcesMatchedRules, 0); histogram_tester.ExpectTotalCount(kSubresourcesDisallowed, 0); + + histogram_tester.ExpectTotalCount(kEvaluationTotalWallDuration, 0); + histogram_tester.ExpectTotalCount(kEvaluationTotalCPUDuration, 0); } TEST_F(SubresourceFilterAgentTest, @@ -338,6 +346,9 @@ histogram_tester.ExpectTotalCount(kSubresourcesEvaluated, 0); histogram_tester.ExpectTotalCount(kSubresourcesMatchedRules, 0); histogram_tester.ExpectTotalCount(kSubresourcesDisallowed, 0); + + histogram_tester.ExpectTotalCount(kEvaluationTotalWallDuration, 0); + histogram_tester.ExpectTotalCount(kEvaluationTotalCPUDuration, 0); } TEST_F(SubresourceFilterAgentTest, Enabled_HistogramSamples) { @@ -376,6 +387,11 @@ ::testing::ElementsAre(base::Bucket(1, 1), base::Bucket(2, 1))); EXPECT_THAT(histogram_tester.GetAllSamples(kSubresourcesDisallowed), ::testing::ElementsAre(base::Bucket(1, 1), base::Bucket(2, 1))); + + histogram_tester.ExpectTotalCount(kEvaluationTotalWallDuration, 2); + const base::HistogramBase::Count total_count = + base::ThreadTicks::IsSupported() ? 2 : 0; + histogram_tester.ExpectTotalCount(kEvaluationTotalCPUDuration, total_count); } TEST_F(SubresourceFilterAgentTest, DryRun_HistogramSamples) { @@ -403,6 +419,11 @@ histogram_tester.ExpectUniqueSample(kSubresourcesEvaluated, 3, 1); histogram_tester.ExpectUniqueSample(kSubresourcesMatchedRules, 2, 1); histogram_tester.ExpectUniqueSample(kSubresourcesDisallowed, 0, 1); + + histogram_tester.ExpectTotalCount(kEvaluationTotalWallDuration, 1); + const base::HistogramBase::Count total_count = + base::ThreadTicks::IsSupported() ? 1 : 0; + histogram_tester.ExpectTotalCount(kEvaluationTotalCPUDuration, total_count); } } // namespace subresource_filter
diff --git a/components/subresource_filter/core/browser/ruleset_service.cc b/components/subresource_filter/core/browser/ruleset_service.cc index 3a0c5fcb..031a1f08 100644 --- a/components/subresource_filter/core/browser/ruleset_service.cc +++ b/components/subresource_filter/core/browser/ruleset_service.cc
@@ -28,6 +28,7 @@ #include "components/subresource_filter/core/common/copying_file_stream.h" #include "components/subresource_filter/core/common/indexed_ruleset.h" #include "components/subresource_filter/core/common/proto/rules.pb.h" +#include "components/subresource_filter/core/common/scoped_timers.h" #include "components/subresource_filter/core/common/unindexed_ruleset.h" #include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h" @@ -344,6 +345,8 @@ bool RulesetService::IndexRuleset(base::File unindexed_ruleset_file, RulesetIndexer* indexer) { SCOPED_UMA_HISTOGRAM_TIMER("SubresourceFilter.IndexRuleset.WallDuration"); + SCOPED_UMA_HISTOGRAM_THREAD_TIMER( + "SubresourceFilter.IndexRuleset.CPUDuration"); int64_t unindexed_ruleset_size = unindexed_ruleset_file.GetLength(); CopyingFileInputStream copying_stream(std::move(unindexed_ruleset_file));
diff --git a/components/subresource_filter/core/common/BUILD.gn b/components/subresource_filter/core/common/BUILD.gn index 1b065d6..7708731c 100644 --- a/components/subresource_filter/core/common/BUILD.gn +++ b/components/subresource_filter/core/common/BUILD.gn
@@ -23,6 +23,7 @@ "memory_mapped_ruleset.cc", "memory_mapped_ruleset.h", "ngram_extractor.h", + "scoped_timers.h", "string_splitter.h", "uint64_hasher.h", "unindexed_ruleset.cc", @@ -69,6 +70,7 @@ "indexed_ruleset_unittest.cc", "knuth_morris_pratt_unittest.cc", "ngram_extractor_unittest.cc", + "scoped_timers_unittest.cc", "string_splitter_unittest.cc", "unindexed_ruleset_unittest.cc", "url_pattern_matching_unittest.cc", @@ -76,6 +78,7 @@ deps = [ ":common", "//base", + "//base/test:test_support", "//testing/gtest", "//third_party/protobuf:protobuf_lite", "//url",
diff --git a/components/subresource_filter/core/common/scoped_timers.h b/components/subresource_filter/core/common/scoped_timers.h new file mode 100644 index 0000000..58a834c2 --- /dev/null +++ b/components/subresource_filter/core/common/scoped_timers.h
@@ -0,0 +1,248 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file provides tools for measuring time intervals and reporting them to +// UMA histograms or via custom functors. It is possible to measure time both +// with base::TimeTicks and base::ThreadTicks. +// WARNING: *UMA_HISTOGRAM_* macros in this file are not thread-safe. +// See also: "base/metrics/histogram_macros*.h". +// +// TODO(pkalinnikov): Consider moving content of this file to "base/metrics/*" +// after some refactoring. Note that most of the code generated by the macros +// below is not thread-safe. + +#ifndef COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_SCOPED_TIMERS_ +#define COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_SCOPED_TIMERS_ + +#include <type_traits> + +#include "base/macros.h" +#include "base/metrics/histogram.h" +#include "base/time/time.h" + +namespace subresource_filter { + +// Creates a scoped object that measures its lifetime using base::TimeTicks, and +// reports the result as base::TimeDelta via provided |export_functor|. The +// functor is copied if passed in by value. +// +// Example: +// void Function() { +// auto export_time = [](base::TimeDelta delta) { +// LOG(INFO) << "Duration: " << delta.InMicroseconds(); +// }; +// SCOPED_TIMER(export_time); +// ... Useful things happen here ... +// } // |export_time| will be triggered here. +// +// This is recommended for when you want to measure the time it takes for a +// method/scope to execute, including, possibly, the time spent by the thread on +// being blocked and/or descheduled. +#define SCOPED_TIMER(export_functor) \ + IMPL_SCOPED_TIMER_EXPANDER(impl::TimeTicksProvider, export_functor, \ + __COUNTER__) + +// Similar to SCOPED_TIMER, but uses base::ThreadTicks for measuring time. +// +// This is recommended for when you want to measure the time it takes for a +// method/scope to do actual work, i.e. excluding the time spent by the thread +// on being blocked and/or descheduled. +#define SCOPED_THREAD_TIMER(export_functor) \ + IMPL_SCOPED_TIMER_EXPANDER(impl::ThreadTicksProvider, export_functor, \ + __COUNTER__) + +// Creates a scoped object that measures its lifetime using base::ThreadTicks, +// and reports the result in milliseconds as a UMA statistic to a histogram with +// the provided |name| which is expected to be a runtime constant. The histogram +// collects times up to 10 seconds in 50 buckets. +// +// Under the hood there is a static base::HistogramBase* pointer initialized +// right before the scoped object. The pointer is used by a specific +// |export_functor| passed in to a SCOPED_THREAD_TIMER (see it above). +// +// Example: +// void Function() { +// SCOPED_UMA_HISTOGRAM_THREAD_TIMER("Component.FunctionTime"); +// ... Useful things happen here ... +// } +// +// WARNING: The generated code is not thread-safe. +#define SCOPED_UMA_HISTOGRAM_THREAD_TIMER(name) \ + IMPL_SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER( \ + name, impl::ThreadTicksProvider, impl::ExportMillisecondsToHistogram, \ + 10 * 1000, __COUNTER__) + +// Similar to SCOPED_UMA_HISTOGRAM_THREAD_TIMER above, but the histogram +// collects times in microseconds, up to 1 second, and using 50 buckets. +// +// WARNING: The generated code is not thread-safe. +#define SCOPED_UMA_HISTOGRAM_MICRO_THREAD_TIMER(name) \ + IMPL_SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER( \ + name, impl::ThreadTicksProvider, impl::ExportMicrosecondsToHistogram, \ + 1000 * 1000, __COUNTER__) + +// Similar to SCOPED_UMA_HISTOGRAM_TIMER in "base/metrics/histogram_macros.h", +// but the histogram stores times in microseconds, up to 1 second, in 50 +// buckets. +// +// WARNING: The generated code is not thread-safe. +#define SCOPED_UMA_HISTOGRAM_MICRO_TIMER(name) \ + IMPL_SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER( \ + name, impl::TimeTicksProvider, impl::ExportMicrosecondsToHistogram, \ + 1000 * 1000, __COUNTER__) + +// Similar to UMA_HISTOGRAM_TIMES in "base/metrics/histogram_macros.h", but +// the histogram stores times in microseconds, up to 1 second, in 50 buckets. +// +// WARNING: The generated code is not thread-safe. +#define UMA_HISTOGRAM_MICRO_TIMES(name, sample) \ + UMA_HISTOGRAM_CUSTOM_MICRO_TIMES(name, sample, \ + base::TimeDelta::FromMicroseconds(1), \ + base::TimeDelta::FromSeconds(1), 50) + +// This can be used when the default ranges are not sufficient. This macro lets +// the metric developer customize the min and max of the sampled range, as well +// as the number of buckets recorded. +#define UMA_HISTOGRAM_CUSTOM_MICRO_TIMES(name, sample, min, max, bucket_count) \ + IMPL_UMA_HISTOGRAM_ADD(name, sample.InMicroseconds(), min.InMicroseconds(), \ + max.InMicroseconds(), bucket_count) + +// ----------------------------------------------------------------------------- +// Below are helpers used by other macros. Shouldn't be used directly. --------- + +// This is necessary to expand __COUNTER__ to an actual value. +#define IMPL_SCOPED_TIMER_EXPANDER(time_provider, export_functor, suffix) \ + IMPL_SCOPED_TIMER_UNIQUE(time_provider, export_functor, suffix) + +// Creates a scoped timer, which uses |time_provider| to measure time, and +// |export_functor| to report it. +#define IMPL_SCOPED_TIMER_UNIQUE(time_provider, export_functor, suffix) \ + impl::ScopedTimer<time_provider, decltype(export_functor)> \ + scoped_timer_##suffix(export_functor); + +// This is necessary to expand __COUNTER__ to an actual value. +#define IMPL_SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER( \ + name, time_provider, histogram_exporter, max_value, suffix) \ + IMPL_SCOPED_UMA_HISTOGRAM_TIMER_UNIQUE( \ + name, time_provider, histogram_exporter, max_value, suffix) + +// Creates a static histogram pointer and a scoped object referring to it +// throught the |histogram_exporter| functor. Both the pointer and the scoped +// object are uniquely-named, using the unique |suffix| passed in. +#define IMPL_SCOPED_UMA_HISTOGRAM_TIMER_UNIQUE( \ + name, time_provider, histogram_exporter, max_value, suffix) \ + IMPL_DEFINE_STATIC_UMA_HISTOGRAM_POINTER(name, 1, max_value, 50, suffix) \ + IMPL_SCOPED_TIMER_UNIQUE(time_provider, \ + (histogram_exporter(histogram_##suffix)), suffix) + +// This is necessary to expand __COUNTER__ to an actual value. +#define IMPL_UMA_HISTOGRAM_MICRO_TIMES_EXPANDER(name, max_value, suffix, \ + sample) \ + IMPL_UMA_HISTOGRAM_MICRO_TIMES_UNIQUE(name, max_value, suffix, sample) + +// Defines a static UMA histogram pointer and writes a |sample| to it. +#define IMPL_UMA_HISTOGRAM_ADD(name, sample, min, max, bucket_count) \ + do { \ + IMPL_DEFINE_STATIC_UMA_HISTOGRAM_POINTER(name, min, max, bucket_count, 0) \ + histogram_0->Add(sample); \ + } while (0) + +// Defines a static pointer to a UMA histogram. +// +// WARNING: Static local variable initialization is deliberately *not* +// thread-safe in Chrome builds. See the "-fno-threadsafe-statics" flag in +// "build/config/compiler/BUILD.gn" and "/Zc:threadSafeInit-" in +// "build/config/win/BUILD.gn" for details. +#define IMPL_DEFINE_STATIC_UMA_HISTOGRAM_POINTER(name, min, max, bucket_count, \ + suffix) \ + static base::HistogramBase* histogram_##suffix = \ + base::Histogram::FactoryGet( \ + name, min, max, bucket_count, \ + base::HistogramBase::kUmaTargetedHistogramFlag); + +namespace impl { + +// ScopedTimer is a multi-purpose scoped timer. It measures time delta from its +// construction till destruction. For example, by putting an instance of this +// class to the beginning of a scope it is possible to measure how long the +// scope is being executed. +// +// The obtained time measurement is reported via ExportFunctor, which takes +// base::TimeDelta as a parameter. +// +// Time is obtained by means of the TimeProvider static interface: +// * static bool IsSupported(); +// - Idempotently returns whether the system supports such type of provider. +// * static void WaitUntilInitialized(); +// - Waits until the provider can be used. +// * static TimeType Now(); +// - Returns the current time of some TimeType, e.g., base::TimeTicks. +// +// Time measurement is exported exactly once, unless TimeProvider::IsSupported() +// is false. In the latter case ExportFunctor is never called. +template <typename TimeProvider, typename ExportFunctor> +class ScopedTimer { + public: + ScopedTimer(ExportFunctor export_functor) : export_functor_(export_functor) { + if (TimeProvider::IsSupported()) { + TimeProvider::WaitUntilInitialized(); + construction_time_ = TimeProvider::Now(); + } + } + + ~ScopedTimer() { + if (TimeProvider::IsSupported()) { + const base::TimeDelta delta = TimeProvider::Now() - construction_time_; + export_functor_(delta); + } + } + + private: + using TimeType = + typename std::remove_reference<decltype(TimeProvider::Now())>::type; + + ExportFunctor export_functor_; + TimeType construction_time_; + + DISALLOW_COPY_AND_ASSIGN(ScopedTimer); +}; + +// TimeProvider implementations ------------------------------------------------ + +class TimeTicksProvider { + public: + static bool IsSupported() { return true; } + static void WaitUntilInitialized() {} + static base::TimeTicks Now() { return base::TimeTicks::Now(); } +}; + +using ThreadTicksProvider = base::ThreadTicks; + +// ExportFunctor implementations ----------------------------------------------- + +template <bool is_microsec_precision> +class ExportTimeDeltaToHistogram { + public: + ExportTimeDeltaToHistogram(base::HistogramBase* histogram) + : histogram_(histogram) {} + + void operator()(base::TimeDelta delta) { + if (is_microsec_precision) + histogram_->Add(delta.InMicroseconds()); + else + histogram_->Add(delta.InMilliseconds()); + } + + private: + base::HistogramBase* histogram_; +}; + +using ExportMillisecondsToHistogram = ExportTimeDeltaToHistogram<false>; +using ExportMicrosecondsToHistogram = ExportTimeDeltaToHistogram<true>; + +} // namespace impl + +} // namespace subresource_filter + +#endif // COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_SCOPED_TIMERS_
diff --git a/components/subresource_filter/core/common/scoped_timers_unittest.cc b/components/subresource_filter/core/common/scoped_timers_unittest.cc new file mode 100644 index 0000000..80cc66c --- /dev/null +++ b/components/subresource_filter/core/common/scoped_timers_unittest.cc
@@ -0,0 +1,121 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/subresource_filter/core/common/scoped_timers.h" + +#include "base/test/histogram_tester.h" +#include "base/time/time.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +class ExportFunctorForTests { + public: + int number_of_calls() const { return number_of_calls_; } + void operator()(base::TimeDelta) { ++number_of_calls_; } + + private: + int number_of_calls_ = 0; +}; + +// Casts an l-value parameter to a reference to it. +template <typename T> +T& reference(T& value) { + return value; +} + +} // namespace + +namespace subresource_filter { + +TEST(ScopedTimersTest, ScopedTimerCallsFunctor) { + ExportFunctorForTests export_functor; + { + // Reference is needed to bypass object copying. + SCOPED_TIMER(reference(export_functor)); + EXPECT_EQ(0, export_functor.number_of_calls()); + } + EXPECT_EQ(1, export_functor.number_of_calls()); +} + +TEST(ScopedTimersTest, ScopedThreadTimerCallsFunctor) { + ExportFunctorForTests export_functor; + { + // Reference is needed to bypass functor copying. + SCOPED_THREAD_TIMER(reference(export_functor)); + EXPECT_EQ(0, export_functor.number_of_calls()); + } + const int expected_number_of_calls = base::ThreadTicks::IsSupported() ? 1 : 0; + EXPECT_EQ(expected_number_of_calls, export_functor.number_of_calls()); +} + +TEST(ScopedTimersTest, ScopedTimersCopyFunctor) { + ExportFunctorForTests export_functor; + { + SCOPED_TIMER(export_functor); + SCOPED_THREAD_TIMER(export_functor); + EXPECT_EQ(0, export_functor.number_of_calls()); + } + EXPECT_EQ(0, export_functor.number_of_calls()); +} + +TEST(ScopedTimersTest, ScopedThreadTimerCallsStoredLambdaFunctor) { + bool export_is_called = false; + auto export_functor = [&export_is_called](base::TimeDelta) { + EXPECT_FALSE(export_is_called); + export_is_called = true; + }; + + { + SCOPED_THREAD_TIMER(export_functor); + EXPECT_FALSE(export_is_called); + } + EXPECT_EQ(base::ThreadTicks::IsSupported(), export_is_called); +} + +TEST(ScopedTimersTest, ScopedTimerCallsStoredLambdaFunctor) { + bool export_is_called = false; + auto export_functor = [&export_is_called](base::TimeDelta) { + export_is_called = true; + }; + + { + SCOPED_TIMER(export_functor); + EXPECT_FALSE(export_is_called); + } + EXPECT_TRUE(export_is_called); +} + +TEST(ScopedTimersTest, ScopedUmaHistogramMacros) { + base::HistogramTester tester; + { + SCOPED_UMA_HISTOGRAM_THREAD_TIMER("ScopedTimers.ThreadTimer"); + SCOPED_UMA_HISTOGRAM_MICRO_THREAD_TIMER("ScopedTimers.MicroThreadTimer"); + SCOPED_UMA_HISTOGRAM_MICRO_TIMER("ScopedTimers.MicroTimer"); + + tester.ExpectTotalCount("ScopedTimers.ThreadTimer", 0); + tester.ExpectTotalCount("ScopedTimers.MicroThreadTimer", 0); + tester.ExpectTotalCount("ScopedTimers.MicroTimer", 0); + } + + const int expected_count = base::ThreadTicks::IsSupported() ? 1 : 0; + tester.ExpectTotalCount("ScopedTimers.ThreadTimer", expected_count); + tester.ExpectTotalCount("ScopedTimers.MicroThreadTimer", expected_count); + + tester.ExpectTotalCount("ScopedTimers.MicroTimer", 1); +} + +TEST(ScopedTimersTest, UmaHistogramMicroTimesFromExportFunctor) { + base::HistogramTester tester; + auto export_functor = [](base::TimeDelta delta) { + UMA_HISTOGRAM_MICRO_TIMES("ScopedTimers.MicroTimes", delta); + }; + { + SCOPED_TIMER(export_functor); + tester.ExpectTotalCount("ScopedTimers.MicroTimes", 0); + } + tester.ExpectTotalCount("ScopedTimers.MicroTimes", 1); +} + +} // namespace subresource_filter
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc index 42d6032..d2ddcae22 100644 --- a/content/browser/frame_host/navigation_controller_impl.cc +++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -265,12 +265,7 @@ } void NavigationControllerImpl::Reload(bool check_for_repost) { - ReloadType type = ReloadType::NORMAL; - if (base::FeatureList::IsEnabled( - features::kNonValidatingReloadOnNormalReload)) { - type = ReloadType::MAIN_RESOURCE; - } - ReloadInternal(check_for_repost, type); + ReloadInternal(check_for_repost, ReloadType::MAIN_RESOURCE); } void NavigationControllerImpl::ReloadToRefreshContent(bool check_for_repost) { ReloadInternal(check_for_repost, ReloadType::MAIN_RESOURCE);
diff --git a/content/browser/frame_host/navigation_controller_impl.h b/content/browser/frame_host/navigation_controller_impl.h index bbba71b..d288764 100644 --- a/content/browser/frame_host/navigation_controller_impl.h +++ b/content/browser/frame_host/navigation_controller_impl.h
@@ -84,6 +84,7 @@ bool IsInitialNavigation() const override; bool IsInitialBlankNavigation() const override; void Reload(bool check_for_repost) override; + // TODO(toyoshim): Merge ReloadToRefreshContent() to Reload(). void ReloadToRefreshContent(bool check_for_repost) override; void ReloadBypassingCache(bool check_for_repost) override; void ReloadOriginalRequestURL(bool check_for_repost) override;
diff --git a/content/browser/frame_host/navigator_impl_unittest.cc b/content/browser/frame_host/navigator_impl_unittest.cc index 5f681a9..a956d53b 100644 --- a/content/browser/frame_host/navigator_impl_unittest.cc +++ b/content/browser/frame_host/navigator_impl_unittest.cc
@@ -834,15 +834,8 @@ // A NavigationRequest should have been generated. NavigationRequest* main_request = node->navigation_request(); ASSERT_TRUE(main_request != NULL); - // TODO(toyoshim): Modify following checks once the feature is enabled. - if (base::FeatureList::IsEnabled( - features::kNonValidatingReloadOnNormalReload)) { - EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD_MAIN_RESOURCE, - main_request->common_params().navigation_type); - } else { - EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD, - main_request->common_params().navigation_type); - } + EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD_MAIN_RESOURCE, + main_request->common_params().navigation_type); main_test_rfh()->PrepareForCommit(); EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
diff --git a/content/browser/loader/reload_cache_control_browsertest.cc b/content/browser/loader/reload_cache_control_browsertest.cc index 98352d5..5affe69 100644 --- a/content/browser/loader/reload_cache_control_browsertest.cc +++ b/content/browser/loader/reload_cache_control_browsertest.cc
@@ -6,9 +6,6 @@ #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/files/file_path.h" -#include "base/test/scoped_feature_list.h" -#include "content/public/common/content_features.h" #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" #include "content/shell/browser/shell.h" @@ -39,12 +36,7 @@ class ReloadCacheControlBrowserTest : public ContentBrowserTest { protected: - ReloadCacheControlBrowserTest() { - // TODO(toyoshim): Tests in this file depend on current reload behavior, - // and should be modified when we enable the new reload behavior. - scoped_feature_list_.InitAndDisableFeature( - features::kNonValidatingReloadOnNormalReload); - } + ReloadCacheControlBrowserTest() {} ~ReloadCacheControlBrowserTest() override = default; void SetUpOnMainThread() override { @@ -77,29 +69,9 @@ request_log_.push_back(log); } - base::test::ScopedFeatureList scoped_feature_list_; - DISALLOW_COPY_AND_ASSIGN(ReloadCacheControlBrowserTest); }; -class ReloadCacheControlWithAnExperimentBrowserTest - : public ReloadCacheControlBrowserTest { - protected: - ReloadCacheControlWithAnExperimentBrowserTest() { - scoped_feature_list_.InitAndEnableFeature( - features::kNonValidatingReloadOnNormalReload); - } - ~ReloadCacheControlWithAnExperimentBrowserTest() override = default; - - void SetUpOnMainThread() override { - SetUpTestServerOnMainThread(); - } - - base::test::ScopedFeatureList scoped_feature_list_; - - DISALLOW_COPY_AND_ASSIGN(ReloadCacheControlWithAnExperimentBrowserTest); -}; - IN_PROC_BROWSER_TEST_F(ReloadCacheControlBrowserTest, NormalReload) { GURL url(embedded_test_server()->GetURL(kReloadTestPath)); @@ -115,7 +87,7 @@ EXPECT_EQ(kReloadTestPath, request_log_[2].relative_url); EXPECT_EQ(kMaxAgeCacheControl, request_log_[2].cache_control); EXPECT_EQ(kReloadImagePath, request_log_[3].relative_url); - EXPECT_EQ(kMaxAgeCacheControl, request_log_[3].cache_control); + EXPECT_EQ(kNoCacheControl, request_log_[3].cache_control); } IN_PROC_BROWSER_TEST_F(ReloadCacheControlBrowserTest, BypassingReload) { @@ -136,25 +108,6 @@ EXPECT_EQ(kNoCacheCacheControl, request_log_[3].cache_control); } -IN_PROC_BROWSER_TEST_F(ReloadCacheControlWithAnExperimentBrowserTest, - ReloadMainResource) { - GURL url(embedded_test_server()->GetURL(kReloadTestPath)); - - EXPECT_TRUE(NavigateToURL(shell(), url)); - ReloadBlockUntilNavigationsComplete(shell(), 1); - - ASSERT_EQ(4UL, request_log_.size()); - EXPECT_EQ(kReloadTestPath, request_log_[0].relative_url); - EXPECT_EQ(kNoCacheControl, request_log_[0].cache_control); - EXPECT_EQ(kReloadImagePath, request_log_[1].relative_url); - EXPECT_EQ(kNoCacheControl, request_log_[1].cache_control); - - EXPECT_EQ(kReloadTestPath, request_log_[2].relative_url); - EXPECT_EQ(kMaxAgeCacheControl, request_log_[2].cache_control); - EXPECT_EQ(kReloadImagePath, request_log_[3].relative_url); - EXPECT_EQ(kNoCacheControl, request_log_[3].cache_control); -} - // TODO(toyoshim): Add another set of reload tests with DevTools open. } // namespace
diff --git a/content/browser/memory/memory_coordinator.cc b/content/browser/memory/memory_coordinator.cc index 4317e5cd..dc9d0a9 100644 --- a/content/browser/memory/memory_coordinator.cc +++ b/content/browser/memory/memory_coordinator.cc
@@ -122,7 +122,8 @@ void MemoryCoordinator::RecordMemoryPressure( base::MemoryPressureMonitor::MemoryPressureLevel level) { - int state = static_cast<int>(GetCurrentMemoryState()); + DCHECK(GetGlobalMemoryState() != base::MemoryState::UNKNOWN); + int state = static_cast<int>(GetGlobalMemoryState()); switch (level) { case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: UMA_HISTOGRAM_ENUMERATION( @@ -139,6 +140,10 @@ } } +base::MemoryState MemoryCoordinator::GetGlobalMemoryState() const { + return base::MemoryState::UNKNOWN; +} + base::MemoryState MemoryCoordinator::GetCurrentMemoryState() const { return base::MemoryState::UNKNOWN; }
diff --git a/content/browser/memory/memory_coordinator.h b/content/browser/memory/memory_coordinator.h index 7d2cbd76..8ed1951 100644 --- a/content/browser/memory/memory_coordinator.h +++ b/content/browser/memory/memory_coordinator.h
@@ -59,7 +59,15 @@ // Called when ChildMemoryCoordinator calls AddChild(). virtual void OnChildAdded(int render_process_id) {} + // Returns the global memory state. + virtual base::MemoryState GetGlobalMemoryState() const; + + // Returns the browser's current memory state. Note that the current state + // could be different from the global memory state as the browser won't be + // suspended. virtual base::MemoryState GetCurrentMemoryState() const; + + // Sets the global memory state for testing. virtual void SetCurrentMemoryStateForTesting(base::MemoryState memory_state); protected:
diff --git a/content/browser/memory/memory_coordinator_impl.cc b/content/browser/memory/memory_coordinator_impl.cc index 66f6a9b4..27b222e 100644 --- a/content/browser/memory/memory_coordinator_impl.cc +++ b/content/browser/memory/memory_coordinator_impl.cc
@@ -188,6 +188,10 @@ SetChildMemoryState(render_process_id, ToMojomMemoryState(current_state_)); } +base::MemoryState MemoryCoordinatorImpl::GetGlobalMemoryState() const { + return current_state_; +} + base::MemoryState MemoryCoordinatorImpl::GetCurrentMemoryState() const { // SUSPENDED state may not make sense to the browser process. Use THROTTLED // instead when the global state is SUSPENDED.
diff --git a/content/browser/memory/memory_coordinator_impl.h b/content/browser/memory/memory_coordinator_impl.h index 7dbe5c6f..5787e251 100644 --- a/content/browser/memory/memory_coordinator_impl.h +++ b/content/browser/memory/memory_coordinator_impl.h
@@ -50,6 +50,7 @@ MemoryMonitor* memory_monitor() { return memory_monitor_.get(); } + base::MemoryState GetGlobalMemoryState() const override; base::MemoryState GetCurrentMemoryState() const override; void SetCurrentMemoryStateForTesting(base::MemoryState memory_state) override;
diff --git a/content/browser/memory/memory_monitor_android.cc b/content/browser/memory/memory_monitor_android.cc index ba73f736..9d144d05 100644 --- a/content/browser/memory/memory_monitor_android.cc +++ b/content/browser/memory/memory_monitor_android.cc
@@ -72,7 +72,7 @@ const base::android::JavaParamRef<jclass>& jcaller, jint level) { DCHECK(level >= 0 && level <= kTrimMemoryLevelMax); - auto state = MemoryCoordinator::GetInstance()->GetCurrentMemoryState(); + auto state = MemoryCoordinator::GetInstance()->GetGlobalMemoryState(); switch (state) { case base::MemoryState::NORMAL: UMA_HISTOGRAM_ENUMERATION("Memory.Coordinator.TrimMemoryLevel.Normal",
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc index e1b1f531..4ed80f9 100644 --- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -594,9 +594,9 @@ run_loop2.Run(); } -// Test that we can generate streams where a mandatory sourceId is specified in +// Test that we can generate streams where a sourceId is specified in // the request. -TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithMandatorySourceId) { +TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithSourceId) { ASSERT_GE(physical_audio_devices_.size(), 1u); ASSERT_GE(physical_video_devices_.size(), 1u); @@ -609,7 +609,7 @@ audio_it->unique_id); ASSERT_FALSE(source_id.empty()); StreamControls controls(true, true); - controls.audio.device_ids.push_back(source_id); + controls.audio.device_id = source_id; SetupFakeUI(true); GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, controls); @@ -624,7 +624,7 @@ video_it->device_id); ASSERT_FALSE(source_id.empty()); StreamControls controls(true, true); - controls.video.device_ids.push_back(source_id); + controls.video.device_id = source_id; SetupFakeUI(true); GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, controls); @@ -632,86 +632,24 @@ } } -// Test that we can generate streams where a optional sourceId is specified in -// the request. -TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithOptionalSourceId) { - ASSERT_GE(physical_audio_devices_.size(), 1u); - ASSERT_GE(physical_video_devices_.size(), 1u); - - media::AudioDeviceNames::const_iterator audio_it = - physical_audio_devices_.begin(); - for (; audio_it != physical_audio_devices_.end(); ++audio_it) { - std::string source_id = content::GetHMACForMediaDeviceID( - browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), - origin_, - audio_it->unique_id); - ASSERT_FALSE(source_id.empty()); - StreamControls controls(true, true); - controls.audio.device_ids.push_back(source_id); - - SetupFakeUI(true); - GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, controls); - EXPECT_EQ(host_->audio_devices_[0].device.id, source_id); - } - - media::VideoCaptureDeviceDescriptors::const_iterator video_it = - physical_video_devices_.begin(); - for (; video_it != physical_video_devices_.end(); ++video_it) { - std::string source_id = content::GetHMACForMediaDeviceID( - browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), origin_, - video_it->device_id); - ASSERT_FALSE(source_id.empty()); - StreamControls controls(true, true); - controls.video.device_ids.push_back(source_id); - - SetupFakeUI(true); - GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, controls); - EXPECT_EQ(host_->video_devices_[0].device.id, source_id); - } -} - -// Test that generating a stream with an invalid mandatory video source id fail. -TEST_F(MediaStreamDispatcherHostTest, - GenerateStreamsWithInvalidMandatoryVideoSourceId) { +// Test that generating a stream with an invalid video source id fail. +TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithInvalidVideoSourceId) { StreamControls controls(true, true); - controls.video.device_ids.push_back("invalid source id"); + controls.video.device_id = "invalid source id"; GenerateStreamAndWaitForFailure(kRenderId, kPageRequestId, controls, MEDIA_DEVICE_NO_HARDWARE); } -// Test that generating a stream with an invalid mandatory audio source id fail. -TEST_F(MediaStreamDispatcherHostTest, - GenerateStreamsWithInvalidMandatoryAudioSourceId) { +// Test that generating a stream with an invalid audio source id fail. +TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithInvalidAudioSourceId) { StreamControls controls(true, true); - controls.audio.device_ids.push_back("invalid source id"); + controls.audio.device_id = "invalid source id"; GenerateStreamAndWaitForFailure(kRenderId, kPageRequestId, controls, MEDIA_DEVICE_NO_HARDWARE); } -// Test that generating a stream with an invalid optional video source id -// succeed. -TEST_F(MediaStreamDispatcherHostTest, - GenerateStreamsWithInvalidOptionalVideoSourceId) { - StreamControls controls(true, true); - controls.video.alternate_device_ids.push_back("invalid source id"); - - SetupFakeUI(true); - GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, controls); -} - -// Test that generating a stream with an invalid optional audio source id -// succeed. -TEST_F(MediaStreamDispatcherHostTest, - GenerateStreamsWithInvalidOptionalAudioSourceId) { - StreamControls controls(true, true); - controls.video.alternate_device_ids.push_back("invalid source id"); - - SetupFakeUI(true); - GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, controls); -} - TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsNoAvailableVideoDevice) { physical_video_devices_.clear(); video_capture_device_factory_->set_number_of_devices(0);
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index 5cdb6233..0da58a4d 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -704,10 +704,10 @@ StreamControls controls; if (IsAudioInputMediaType(type)) { controls.audio.requested = true; - controls.audio.device_ids.push_back(device_id); + controls.audio.device_id = device_id; } else if (IsVideoMediaType(type)) { controls.video.requested = true; - controls.video.device_ids.push_back(device_id); + controls.video.device_id = device_id; } else { NOTREACHED(); } @@ -793,29 +793,15 @@ const TrackControls& controls, const MediaDeviceInfoArray& devices, std::string* device_id) const { - if (!controls.device_ids.empty()) { - if (controls.device_ids.size() > 1) { - LOG(ERROR) << "Only one required device ID is supported"; - return false; - } - const std::string& candidate_id = controls.device_ids[0]; - if (!GetDeviceIDFromHMAC(salt, security_origin, candidate_id, devices, - device_id)) { - LOG(WARNING) << "Invalid mandatory capture ID = " << candidate_id; - return false; - } + if (controls.device_id.empty()) return true; + + if (!GetDeviceIDFromHMAC(salt, security_origin, controls.device_id, devices, + device_id)) { + LOG(WARNING) << "Invalid device ID = " << controls.device_id; + return false; } - // We don't have a required ID. Look at the alternates. - for (const std::string& candidate_id : controls.alternate_device_ids) { - if (GetDeviceIDFromHMAC(salt, security_origin, candidate_id, devices, - device_id)) { - return true; - } else { - LOG(WARNING) << "Invalid optional capture ID = " << candidate_id; - } - } - return true; // If we get here, device_id is empty. + return true; } bool MediaStreamManager::GetRequestedDeviceCaptureId( @@ -1062,10 +1048,10 @@ request->video_type() == MEDIA_TAB_VIDEO_CAPTURE); std::string capture_device_id; - if (!request->controls.audio.device_ids.empty()) { - capture_device_id = request->controls.audio.device_ids[0]; - } else if (!request->controls.video.device_ids.empty()) { - capture_device_id = request->controls.video.device_ids[0]; + if (!request->controls.audio.device_id.empty()) { + capture_device_id = request->controls.audio.device_id; + } else if (!request->controls.video.device_id.empty()) { + capture_device_id = request->controls.video.device_id; } else { return false; } @@ -1117,8 +1103,8 @@ request->controls.video.stream_source; if (video_stream_source == kMediaStreamSourceDesktop && - !request->controls.video.device_ids.empty()) { - video_device_id = request->controls.video.device_ids[0]; + !request->controls.video.device_id.empty()) { + video_device_id = request->controls.video.device_id; } }
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 682f15d8..286c6276 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -247,11 +247,6 @@ if (command_line.HasSwitch(switches::kEnableSlimmingPaintV2)) WebRuntimeFeatures::enableSlimmingPaintV2(true); - if (base::FeatureList::IsEnabled( - features::kNonValidatingReloadOnNormalReload)) { - WebRuntimeFeatures::enableReloadwithoutSubResourceCacheRevalidation(true); - } - if (base::FeatureList::IsEnabled(features::kDocumentWriteEvaluator)) WebRuntimeFeatures::enableDocumentWriteEvaluator(true);
diff --git a/content/common/media/media_stream_messages.h b/content/common/media/media_stream_messages.h index 31a2137..601b2c0 100644 --- a/content/common/media/media_stream_messages.h +++ b/content/common/media/media_stream_messages.h
@@ -29,8 +29,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::TrackControls) IPC_STRUCT_TRAITS_MEMBER(requested) IPC_STRUCT_TRAITS_MEMBER(stream_source) - IPC_STRUCT_TRAITS_MEMBER(device_ids) - IPC_STRUCT_TRAITS_MEMBER(alternate_device_ids) + IPC_STRUCT_TRAITS_MEMBER(device_id) IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(content::StreamControls)
diff --git a/content/common/media/media_stream_options.h b/content/common/media/media_stream_options.h index 2eb56283..55f5687 100644 --- a/content/common/media/media_stream_options.h +++ b/content/common/media/media_stream_options.h
@@ -33,17 +33,13 @@ // Consider replacing with MediaStreamType enum variables. std::string stream_source; // audio.kMediaStreamSource - // Device ID requests. - // The first set represents required devices - either grab one or fail. - // The second set represents optional devices - if we can't get one of - // these, we will grab the default device (if possible). - // The constraint names are "sourceId" and "chromeMediaSourceId". - std::vector<std::string> device_ids; - std::vector<std::string> alternate_device_ids; + // An empty string represents the default device. + // A nonempty string represents a specific device. + std::string device_id; }; // StreamControls describes what is sent to the browser process -// to the renderer process in order to control the opening of a device +// from the renderer process in order to control the opening of a device // pair. This may result in opening one audio and/or one video device. // This has to be a struct with public members in order to allow it to // be sent in the IPC of media_stream_messages.h
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 0933f23..1bea0d7 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -111,11 +111,6 @@ "MemoryCoordinator", base::FEATURE_DISABLED_BY_DEFAULT }; -// Non-validating reload for desktop. -// See https://crbug.com/591245 -const base::Feature kNonValidatingReloadOnNormalReload{ - "NonValidatingReloadOnNormalReload", base::FEATURE_ENABLED_BY_DEFAULT}; - // Kill switch for Web Notification content images. const base::Feature kNotificationContentImage{"NotificationContentImage", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 597d1b09..4230595 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -35,7 +35,6 @@ CONTENT_EXPORT extern const base::Feature kLazyParseCSS; CONTENT_EXPORT extern const base::Feature kMediaDocumentDownloadButton; CONTENT_EXPORT extern const base::Feature kMemoryCoordinator; -CONTENT_EXPORT extern const base::Feature kNonValidatingReloadOnNormalReload; CONTENT_EXPORT extern const base::Feature kNotificationContentImage; CONTENT_EXPORT extern const base::Feature kOptimizeLoadingIPCForSmallResources; CONTENT_EXPORT extern const base::Feature kOriginTrials;
diff --git a/content/renderer/media/user_media_client_impl.cc b/content/renderer/media/user_media_client_impl.cc index 766ca8c7..2381c46 100644 --- a/content/renderer/media/user_media_client_impl.cc +++ b/content/renderer/media/user_media_client_impl.cc
@@ -6,12 +6,13 @@ #include <stddef.h> +#include <algorithm> #include <utility> -#include <vector> #include "base/hash.h" #include "base/location.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -36,78 +37,141 @@ #include "third_party/WebKit/public/platform/WebMediaConstraints.h" #include "third_party/WebKit/public/platform/WebMediaDeviceInfo.h" #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" +#include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" namespace content { namespace { -void CopyVector(const blink::WebVector<blink::WebString>& source, - std::vector<std::string>* destination) { - for (const auto& web_string : source) { - destination->push_back(web_string.utf8()); - } -} - -void CopyFirstString(const blink::WebVector<blink::WebString>& source, +void CopyFirstString(const blink::StringConstraint& constraint, std::string* destination) { - if (!source.isEmpty()) - *destination = source[0].utf8(); + if (!constraint.exact().isEmpty()) + *destination = constraint.exact()[0].utf8(); } -void CopyBlinkRequestToStreamControls(const blink::WebUserMediaRequest& request, - StreamControls* controls) { - if (request.isNull()) { - return; - } - if (!request.audioConstraints().isNull()) { - const blink::WebMediaTrackConstraintSet& audio_basic = - request.audioConstraints().basic(); - CopyFirstString(audio_basic.mediaStreamSource.exact(), - &controls->audio.stream_source); - CopyVector(audio_basic.deviceId.exact(), &(controls->audio.device_ids)); - // Optionals. They may be either in ideal or in advanced.exact. - CopyVector(audio_basic.deviceId.ideal(), - &controls->audio.alternate_device_ids); - for (const auto& constraint : request.audioConstraints().advanced()) { - CopyVector(constraint.deviceId.exact(), - &controls->audio.alternate_device_ids); - CopyVector(constraint.deviceId.ideal(), - &controls->audio.alternate_device_ids); +bool FindDeviceId(const blink::WebVector<blink::WebString> candidates, + const MediaDeviceInfoArray& device_infos, + std::string* device_id) { + for (const auto& candidate : candidates) { + auto it = std::find_if(device_infos.begin(), device_infos.end(), + [&candidate](const MediaDeviceInfo& info) { + return info.device_id == candidate.utf8(); + }); + + if (it != device_infos.end()) { + *device_id = it->device_id; + return true; } - if (audio_basic.hotwordEnabled.hasExact()) { - controls->hotword_enabled = audio_basic.hotwordEnabled.exact(); - } else { - for (const auto& audio_advanced : request.audioConstraints().advanced()) { - if (audio_advanced.hotwordEnabled.hasExact()) { - controls->hotword_enabled = audio_advanced.hotwordEnabled.exact(); - break; - } + } + + return false; +} + +// If a device ID requested as exact basic constraint in |constraints| is found +// in |device_infos|, it is copied to |*device_id|, and the function returns +// false. If such a device is not found in |device_infos|, the function returns +// false and |*device_id| is left unmodified. +// If more than one device ID is requested as an exact basic constraint in +// |constraint|, the function returns false and |*device_id| is left unmodified. +// If no device ID is requested as an exact basic constraint, and at least one +// device ID requested as an ideal basic constraint or as an exact or ideal +// advanced constraint in |constraints| is found in |device_infos|, the first +// such device ID is copied to |*device_id| and the function returns true. +// If no such device ID is found, |*device_id| is left unmodified and the +// function returns true. +// TODO(guidou): Replace with a spec-compliant selection algorithm. See +// http://crbug.com/657733. +bool PickDeviceId(const blink::WebMediaConstraints& constraints, + const MediaDeviceInfoArray& device_infos, + std::string* device_id) { + DCHECK(!constraints.isNull()); + DCHECK(device_id->empty()); + + if (constraints.basic().deviceId.exact().size() > 1) { + LOG(ERROR) << "Only one required device ID is supported"; + return false; + } + + if (constraints.basic().deviceId.exact().size() == 1 && + !FindDeviceId(constraints.basic().deviceId.exact(), device_infos, + device_id)) { + LOG(ERROR) << "Invalid mandatory device ID = " + << constraints.basic().deviceId.exact()[0].utf8(); + return false; + } + + // There is no required device ID. Look at the alternates. + if (FindDeviceId(constraints.basic().deviceId.ideal(), device_infos, + device_id)) { + return true; + } + + for (const auto& advanced : constraints.advanced()) { + if (FindDeviceId(advanced.deviceId.exact(), device_infos, device_id)) { + return true; + } + if (FindDeviceId(advanced.deviceId.ideal(), device_infos, device_id)) { + return true; + } + } + + // No valid alternate device ID found. Select default device. + return true; +} + +bool IsDeviceSource(const std::string& source) { + return source.empty(); +} + +void CopyConstraintsToTrackControls( + const blink::WebMediaConstraints& constraints, + TrackControls* track_controls, + bool* request_devices) { + DCHECK(!constraints.isNull()); + track_controls->requested = true; + CopyFirstString(constraints.basic().mediaStreamSource, + &track_controls->stream_source); + if (IsDeviceSource(track_controls->stream_source)) { + bool request_devices_advanced = false; + for (const auto& advanced : constraints.advanced()) { + if (!advanced.deviceId.isEmpty()) { + request_devices_advanced = true; + break; } } + *request_devices = + request_devices_advanced || !constraints.basic().deviceId.isEmpty(); + } else { + CopyFirstString(constraints.basic().deviceId, &track_controls->device_id); + *request_devices = false; + } +} - if (request.audioConstraints().basic().disableLocalEcho.hasExact()) { - controls->disable_local_echo = - request.audioConstraints().basic().disableLocalEcho.exact(); - } else { - controls->disable_local_echo = - controls->audio.stream_source != kMediaStreamSourceDesktop; +void CopyHotwordAndLocalEchoToStreamControls( + const blink::WebMediaConstraints& audio_constraints, + StreamControls* controls) { + if (audio_constraints.isNull()) + return; + + if (audio_constraints.basic().hotwordEnabled.hasExact()) { + controls->hotword_enabled = + audio_constraints.basic().hotwordEnabled.exact(); + } else { + for (const auto& audio_advanced : audio_constraints.advanced()) { + if (audio_advanced.hotwordEnabled.hasExact()) { + controls->hotword_enabled = audio_advanced.hotwordEnabled.exact(); + break; + } } } - if (!request.videoConstraints().isNull()) { - const blink::WebMediaTrackConstraintSet& video_basic = - request.videoConstraints().basic(); - CopyFirstString(video_basic.mediaStreamSource.exact(), - &(controls->video.stream_source)); - CopyVector(video_basic.deviceId.exact(), &(controls->video.device_ids)); - CopyVector(video_basic.deviceId.ideal(), - &(controls->video.alternate_device_ids)); - for (const auto& constraint : request.videoConstraints().advanced()) { - CopyVector(constraint.deviceId.exact(), - &controls->video.alternate_device_ids); - CopyVector(constraint.deviceId.ideal(), - &controls->video.alternate_device_ids); - } + + if (audio_constraints.basic().disableLocalEcho.hasExact()) { + controls->disable_local_echo = + audio_constraints.basic().disableLocalEcho.exact(); + } else { + controls->disable_local_echo = + controls->audio.stream_source != kMediaStreamSourceDesktop; } } @@ -183,19 +247,34 @@ } int request_id = g_next_request_id++; - StreamControls controls; - url::Origin security_origin; - bool enable_automatic_output_device_selection = false; + std::unique_ptr<StreamControls> controls = base::MakeUnique<StreamControls>(); // |user_media_request| can't be mocked. So in order to test at all we check // if it isNull. + // TODO(guidou): Remove this test-specific code path. if (user_media_request.isNull()) { // We are in a test. - controls.audio.requested = true; - controls.video.requested = true; + controls->audio.requested = true; + controls->video.requested = true; + FinalizeRequestUserMedia( + request_id, user_media_request, std::move(controls), + false /* automatic_output_device_selection */, url::Origin()); } else { + // ownerDocument may be null if we are in a test. + // In that case, it's OK to not check frame(). + DCHECK(user_media_request.ownerDocument().isNull() || + render_frame()->GetWebFrame() == + static_cast<blink::WebFrame*>( + user_media_request.ownerDocument().frame())); + + bool enable_automatic_output_device_selection = false; + bool request_audio_input_devices = false; if (user_media_request.audio()) { - controls.audio.requested = true; + CopyConstraintsToTrackControls(user_media_request.audioConstraints(), + &controls->audio, + &request_audio_input_devices); + CopyHotwordAndLocalEchoToStreamControls( + user_media_request.audioConstraints(), controls.get()); // Check if this input device should be used to select a matching output // device for audio rendering. GetConstraintValueAsBoolean( @@ -203,52 +282,88 @@ &blink::WebMediaTrackConstraintSet::renderToAssociatedSink, &enable_automatic_output_device_selection); } + bool request_video_input_devices = false; if (user_media_request.video()) { - controls.video.requested = true; + CopyConstraintsToTrackControls(user_media_request.videoConstraints(), + &controls->video, + &request_video_input_devices); } - CopyBlinkRequestToStreamControls(user_media_request, &controls); - security_origin = user_media_request.getSecurityOrigin(); - // ownerDocument may be null if we are in a test. - // In that case, it's OK to not check frame(). - DCHECK(user_media_request.ownerDocument().isNull() || - render_frame()->GetWebFrame() == - static_cast<blink::WebFrame*>( - user_media_request.ownerDocument().frame())); + + url::Origin security_origin = user_media_request.getSecurityOrigin(); + if (request_audio_input_devices || request_video_input_devices) { + GetMediaDevicesDispatcher()->EnumerateDevices( + request_audio_input_devices, request_video_input_devices, + false /* request_audio_output_devices */, security_origin, + base::Bind(&UserMediaClientImpl::SelectUserMediaDevice, + weak_factory_.GetWeakPtr(), request_id, user_media_request, + base::Passed(&controls), + enable_automatic_output_device_selection, + security_origin)); + } else { + FinalizeRequestUserMedia( + request_id, user_media_request, std::move(controls), + enable_automatic_output_device_selection, security_origin); + } + } +} + +void UserMediaClientImpl::SelectUserMediaDevice( + int request_id, + const blink::WebUserMediaRequest& user_media_request, + std::unique_ptr<StreamControls> controls, + bool enable_automatic_output_device_selection, + const url::Origin& security_origin, + const EnumerationResult& device_enumeration) { + DCHECK(CalledOnValidThread()); + + if (controls->audio.requested && + IsDeviceSource(controls->audio.stream_source)) { + if (!PickDeviceId(user_media_request.audioConstraints(), + device_enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT], + &controls->audio.device_id)) { + GetUserMediaRequestFailed(user_media_request, MEDIA_DEVICE_NO_HARDWARE, + ""); + return; + } } - DVLOG(1) << "UserMediaClientImpl::requestUserMedia(" << request_id << ", [ " - << "audio=" << (controls.audio.requested) - << " select associated sink: " - << enable_automatic_output_device_selection - << ", video=" << (controls.video.requested) << " ], " - << security_origin << ")"; - - std::string audio_device_id; - if (!user_media_request.isNull() && user_media_request.audio()) { - GetConstraintValueAsString(user_media_request.audioConstraints(), - &blink::WebMediaTrackConstraintSet::deviceId, - &audio_device_id); + if (controls->video.requested && + IsDeviceSource(controls->video.stream_source)) { + if (!PickDeviceId(user_media_request.videoConstraints(), + device_enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT], + &controls->video.device_id)) { + GetUserMediaRequestFailed(user_media_request, MEDIA_DEVICE_NO_HARDWARE, + ""); + return; + } } - std::string video_device_id; - if (!user_media_request.isNull() && user_media_request.video()) { - GetConstraintValueAsString(user_media_request.videoConstraints(), - &blink::WebMediaTrackConstraintSet::deviceId, - &video_device_id); - } + FinalizeRequestUserMedia(request_id, user_media_request, std::move(controls), + enable_automatic_output_device_selection, + security_origin); +} - WebRtcLogMessage(base::StringPrintf( - "MSI::requestUserMedia. request_id=%d" - ", audio source id=%s" - ", video source id=%s", - request_id, audio_device_id.c_str(), video_device_id.c_str())); +void UserMediaClientImpl::FinalizeRequestUserMedia( + int request_id, + const blink::WebUserMediaRequest& user_media_request, + std::unique_ptr<StreamControls> controls, + bool enable_automatic_output_device_selection, + const url::Origin& security_origin) { + DCHECK(CalledOnValidThread()); + + WebRtcLogMessage( + base::StringPrintf("MSI::requestUserMedia. request_id=%d" + ", audio source id=%s" + ", video source id=%s", + request_id, controls->audio.device_id.c_str(), + controls->video.device_id.c_str())); user_media_requests_.push_back( new UserMediaRequestInfo(request_id, user_media_request, enable_automatic_output_device_selection)); media_stream_dispatcher_->GenerateStream( - request_id, weak_factory_.GetWeakPtr(), controls, security_origin); + request_id, weak_factory_.GetWeakPtr(), *controls, security_origin); } void UserMediaClientImpl::cancelUserMediaRequest(
diff --git a/content/renderer/media/user_media_client_impl.h b/content/renderer/media/user_media_client_impl.h index e9202d6..2492ccc 100644 --- a/content/renderer/media/user_media_client_impl.h +++ b/content/renderer/media/user_media_client_impl.h
@@ -242,6 +242,20 @@ const ::mojom::MediaDevicesDispatcherHostPtr& GetMediaDevicesDispatcher(); + void SelectUserMediaDevice( + int request_id, + const blink::WebUserMediaRequest& user_media_request, + std::unique_ptr<StreamControls> controls, + bool enable_automatic_output_device_selection, + const url::Origin& security_origin, + const EnumerationResult& device_enumeration); + void FinalizeRequestUserMedia( + int request_id, + const blink::WebUserMediaRequest& user_media_request, + std::unique_ptr<StreamControls> controls, + bool enable_automatic_output_device_selection, + const url::Origin& security_origin); + // Callback invoked by MediaDevicesEventDispatcher when a device-change // notification arrives. void DevicesChanged(MediaDeviceType device_type,
diff --git a/content/renderer/media/user_media_client_impl_unittest.cc b/content/renderer/media/user_media_client_impl_unittest.cc index c0de733a..437f3c2c 100644 --- a/content/renderer/media/user_media_client_impl_unittest.cc +++ b/content/renderer/media/user_media_client_impl_unittest.cc
@@ -110,6 +110,7 @@ void RequestUserMedia(const blink::WebUserMediaRequest& user_media_request) { state_ = REQUEST_NOT_COMPLETE; requestUserMedia(user_media_request); + base::RunLoop().RunUntilIdle(); } void RequestUserMedia() {
diff --git a/ios/chrome/BUILD.gn b/ios/chrome/BUILD.gn index 1c9fef6..5044c7b 100644 --- a/ios/chrome/BUILD.gn +++ b/ios/chrome/BUILD.gn
@@ -48,7 +48,6 @@ "//ios/chrome/browser/update_client:unit_tests", "//ios/chrome/browser/voice:unit_tests", "//ios/chrome/browser/web_resource:unit_tests", - "//ios/chrome/browser/webp_transcode:unit_tests", "//ios/chrome/common:unit_tests", "//ios/chrome/test:unit_tests", ]
diff --git a/ios/chrome/browser/net/BUILD.gn b/ios/chrome/browser/net/BUILD.gn index 4919747..b548450 100644 --- a/ios/chrome/browser/net/BUILD.gn +++ b/ios/chrome/browser/net/BUILD.gn
@@ -44,9 +44,9 @@ "//ios/chrome/browser", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/browsing_data", - "//ios/chrome/browser/webp_transcode", "//ios/net", "//ios/web", + "//ios/web/public/image_fetcher", "//net", "//net:extras", "//url", @@ -74,7 +74,6 @@ testonly = true sources = [ "cookie_util_unittest.mm", - "image_fetcher_unittest.mm", "metrics_network_client_unittest.mm", "retryable_url_fetcher_unittest.mm", ]
diff --git a/ios/chrome/browser/net/image_fetcher.mm b/ios/chrome/browser/net/image_fetcher.mm index de591c0..4ad0f02 100644 --- a/ios/chrome/browser/net/image_fetcher.mm +++ b/ios/chrome/browser/net/image_fetcher.mm
@@ -11,7 +11,7 @@ #include "base/location.h" #include "base/mac/scoped_nsobject.h" #include "base/task_runner.h" -#include "ios/chrome/browser/webp_transcode/webp_decoder.h" +#include "ios/web/public/image_fetcher/webp_decoder.h" #include "ios/web/public/web_thread.h" #include "net/base/load_flags.h" #include "net/http/http_response_headers.h"
diff --git a/ios/chrome/browser/net/image_fetcher_unittest.mm b/ios/chrome/browser/net/image_fetcher_unittest.mm deleted file mode 100644 index de2d2c9..0000000 --- a/ios/chrome/browser/net/image_fetcher_unittest.mm +++ /dev/null
@@ -1,203 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/net/image_fetcher.h" - -#import <UIKit/UIKit.h> - -#include "base/ios/ios_util.h" -#include "base/mac/scoped_block.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/memory/ref_counted.h" -#include "base/run_loop.h" -#include "base/threading/thread.h" -#include "base/threading/thread_task_runner_handle.h" -#include "build/build_config.h" -#include "net/http/http_response_headers.h" -#include "net/url_request/test_url_fetcher_factory.h" -#include "net/url_request/url_request_test_util.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/platform_test.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { - -static unsigned char kJPGImage[] = { - 255,216,255,224,0,16,74,70,73,70,0,1,1,1,0,72,0,72,0,0,255,254,0,19,67, - 114,101,97,116,101,100,32,119,105,116,104,32,71,73,77,80,255,219,0,67, - 0,5,3,4,4,4,3,5,4,4,4,5,5,5,6,7,12,8,7,7,7,7,15,11,11,9,12,17,15,18,18, - 17,15,17,17,19,22,28,23,19,20,26,21,17,17,24,33,24,26,29,29,31,31,31, - 19,23,34,36,34,30,36,28,30,31,30,255,219,0,67,1,5,5,5,7,6,7,14,8,8,14, - 30,20,17,20,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, - 30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, - 30,30,30,30,30,30,30,30,255,192,0,17,8,0,1,0,1,3,1,34,0,2,17,1,3,17,1, - 255,196,0,21,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,255,196,0,20,16,1, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,196,0,20,1,1,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,255,196,0,20,17,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,218, - 0,12,3,1,0,2,17,3,17,0,63,0,178,192,7,255,217 -}; - -static unsigned char kPNGImage[] = { - 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,1,0,0,0,1,1,0,0,0, - 0,55,110,249,36,0,0,0,2,98,75,71,68,0,1,221,138,19,164,0,0,0,9,112,72, - 89,115,0,0,11,18,0,0,11,18,1,210,221,126,252,0,0,0,9,118,112,65,103,0, - 0,0,1,0,0,0,1,0,199,149,95,237,0,0,0,10,73,68,65,84,8,215,99,104,0,0, - 0,130,0,129,221,67,106,244,0,0,0,25,116,69,88,116,99,111,109,109,101, - 110,116,0,67,114,101,97,116,101,100,32,119,105,116,104,32,71,73,77,80, - 231,175,64,203,0,0,0,37,116,69,88,116,100,97,116,101,58,99,114,101,97, - 116,101,0,50,48,49,49,45,48,54,45,50,50,84,49,54,58,49,54,58,52,54,43, - 48,50,58,48,48,31,248,231,223,0,0,0,37,116,69,88,116,100,97,116,101,58, - 109,111,100,105,102,121,0,50,48,49,49,45,48,54,45,50,50,84,49,54,58,49, - 54,58,52,54,43,48,50,58,48,48,110,165,95,99,0,0,0,17,116,69,88,116,106, - 112,101,103,58,99,111,108,111,114,115,112,97,99,101,0,50,44,117,85,159, - 0,0,0,32,116,69,88,116,106,112,101,103,58,115,97,109,112,108,105,110, - 103,45,102,97,99,116,111,114,0,50,120,50,44,49,120,49,44,49,120,49,73, - 250,166,180,0,0,0,0,73,69,78,68,174,66,96,130 -}; - -static unsigned char kWEBPImage[] = { - 82,73,70,70,74,0,0,0,87,69,66,80,86,80,56,88,10,0,0,0,16,0,0,0,0,0,0,0,0,0, - 65,76,80,72,12,0,0,0,1,7,16,17,253,15,68,68,255,3,0,0,86,80,56,32,24,0,0,0, - 48,1,0,157,1,42,1,0,1,0,3,0,52,37,164,0,3,112,0,254,251,253,80,0 -}; - -static const char kTestUrl[] = "http://www.img.com"; - -static const char kWEBPHeaderResponse[] = - "HTTP/1.1 200 OK\0Content-type: image/webp\0\0"; - -} // namespace - -class ImageFetcherTest : public PlatformTest { - protected: - ImageFetcherTest() - : worker_thread_("TestThread"), - callback_([^(const GURL& original_url, - int http_response_code, - NSData * data) { - result_ = [UIImage imageWithData:data]; - called_ = true; - } copy]) { - worker_thread_.Start(); - - image_fetcher_ = - base::MakeUnique<ImageFetcher>(worker_thread_.task_runner()); - image_fetcher_->SetRequestContextGetter( - new net::TestURLRequestContextGetter( - base::ThreadTaskRunnerHandle::Get())); - } - - net::TestURLFetcher* SetupFetcher() { - image_fetcher_->StartDownload(GURL(kTestUrl), callback_); - EXPECT_EQ(nil, result_); - EXPECT_EQ(false, called_); - net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0); - DCHECK(fetcher); - DCHECK(fetcher->delegate()); - return fetcher; - } - - // Message loop for the main test thread. - base::MessageLoop loop_; - - // Worker thread used for ImageFetcher's asynchronous work. - base::Thread worker_thread_; - - base::mac::ScopedBlock<ImageFetchedCallback> callback_; - net::TestURLFetcherFactory factory_; - std::unique_ptr<ImageFetcher> image_fetcher_; - UIImage* result_ = nil; - bool called_ = false; - - private: - DISALLOW_COPY_AND_ASSIGN(ImageFetcherTest); -}; - -TEST_F(ImageFetcherTest, TestError) { - net::TestURLFetcher* fetcher = SetupFetcher(); - fetcher->set_response_code(404); - fetcher->delegate()->OnURLFetchComplete(fetcher); - EXPECT_EQ(nil, result_); - EXPECT_TRUE(called_); -} - -TEST_F(ImageFetcherTest, TestJpg) { - net::TestURLFetcher* fetcher = SetupFetcher(); - fetcher->set_response_code(200); - fetcher->SetResponseString(std::string((char*)kJPGImage, sizeof(kJPGImage))); - fetcher->delegate()->OnURLFetchComplete(fetcher); - EXPECT_NE(nil, result_); - EXPECT_TRUE(called_); -} - -TEST_F(ImageFetcherTest, TestPng) { - net::TestURLFetcher* fetcher = SetupFetcher(); - fetcher->set_response_code(200); - fetcher->SetResponseString(std::string((char*)kPNGImage, sizeof(kPNGImage))); - fetcher->delegate()->OnURLFetchComplete(fetcher); - EXPECT_NE(nil, result_); - EXPECT_TRUE(called_); -} - -TEST_F(ImageFetcherTest, TestGoodWebP) { -// TODO(droger): This test fails on iOS 9 x64 devices. http://crbug.com/523235 -#if defined(OS_IOS) && defined(ARCH_CPU_ARM64) && !TARGET_IPHONE_SIMULATOR - if (base::ios::IsRunningOnIOS9OrLater()) - return; -#endif - net::TestURLFetcher* fetcher = SetupFetcher(); - fetcher->set_response_code(200); - fetcher->SetResponseString( - std::string((char*)kWEBPImage, sizeof(kWEBPImage))); - scoped_refptr<net::HttpResponseHeaders> headers(new net::HttpResponseHeaders( - std::string(kWEBPHeaderResponse, arraysize(kWEBPHeaderResponse)))); - fetcher->set_response_headers(headers); - fetcher->delegate()->OnURLFetchComplete(fetcher); - worker_thread_.FlushForTesting(); - base::RunLoop().RunUntilIdle(); - EXPECT_NE(nil, result_); - EXPECT_TRUE(called_); -} - -TEST_F(ImageFetcherTest, TestBadWebP) { - net::TestURLFetcher* fetcher = SetupFetcher(); - fetcher->set_response_code(200); - fetcher->SetResponseString("This is not a valid WebP image"); - scoped_refptr<net::HttpResponseHeaders> headers(new net::HttpResponseHeaders( - std::string(kWEBPHeaderResponse, arraysize(kWEBPHeaderResponse)))); - fetcher->set_response_headers(headers); - fetcher->delegate()->OnURLFetchComplete(fetcher); - worker_thread_.FlushForTesting(); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(nil, result_); - EXPECT_TRUE(called_); -} - -TEST_F(ImageFetcherTest, DeleteDuringWebPDecoding) { - net::TestURLFetcher* fetcher = SetupFetcher(); - fetcher->set_response_code(200); - fetcher->SetResponseString( - std::string((char*)kWEBPImage, sizeof(kWEBPImage))); - scoped_refptr<net::HttpResponseHeaders> headers(new net::HttpResponseHeaders( - std::string(kWEBPHeaderResponse, arraysize(kWEBPHeaderResponse)))); - fetcher->set_response_headers(headers); - fetcher->delegate()->OnURLFetchComplete(fetcher); - // Delete the image fetcher, and check that the callback is not called. - image_fetcher_.reset(); - worker_thread_.FlushForTesting(); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(nil, result_); - EXPECT_FALSE(called_); -} - -TEST_F(ImageFetcherTest, TestCallbacksNotCalledDuringDeletion) { - image_fetcher_->StartDownload(GURL(kTestUrl), callback_); - image_fetcher_.reset(); - EXPECT_FALSE(called_); -} -
diff --git a/ios/chrome/browser/providers/BUILD.gn b/ios/chrome/browser/providers/BUILD.gn index 1db5454..2a6e7c7c 100644 --- a/ios/chrome/browser/providers/BUILD.gn +++ b/ios/chrome/browser/providers/BUILD.gn
@@ -10,6 +10,8 @@ "chromium_browser_provider.mm", "chromium_logo_controller.h", "chromium_logo_controller.mm", + "chromium_spotlight_provider.h", + "chromium_spotlight_provider.mm", "chromium_voice_search_provider.h", "chromium_voice_search_provider.mm", ] @@ -21,6 +23,7 @@ "//ios/public/provider/chrome/browser", "//ios/public/provider/chrome/browser/distribution", "//ios/public/provider/chrome/browser/signin", + "//ios/public/provider/chrome/browser/spotlight", "//ios/public/provider/chrome/browser/ui", "//ios/public/provider/chrome/browser/user_feedback", "//ios/public/provider/chrome/browser/voice",
diff --git a/ios/chrome/browser/providers/chromium_browser_provider.h b/ios/chrome/browser/providers/chromium_browser_provider.h index 5a237e6..cc5c31b1 100644 --- a/ios/chrome/browser/providers/chromium_browser_provider.h +++ b/ios/chrome/browser/providers/chromium_browser_provider.h
@@ -29,6 +29,7 @@ UserFeedbackProvider* GetUserFeedbackProvider() const override; AppDistributionProvider* GetAppDistributionProvider() const override; BrandedImageProvider* GetBrandedImageProvider() const override; + SpotlightProvider* GetSpotlightProvider() const override; private: std::unique_ptr<AppDistributionProvider> app_distribution_provider_; @@ -38,6 +39,7 @@ std::unique_ptr<ios::ChromeIdentityService> chrome_identity_service_; std::unique_ptr<UserFeedbackProvider> user_feedback_provider_; std::unique_ptr<VoiceSearchProvider> voice_search_provider_; + std::unique_ptr<SpotlightProvider> spotlight_provider_; }; #endif // IOS_CHROME_BROWSER_PROVIDERS_CHROMIUM_BROWSER_PROVIDER_H_
diff --git a/ios/chrome/browser/providers/chromium_browser_provider.mm b/ios/chrome/browser/providers/chromium_browser_provider.mm index 1cd9d9f..3d5ed08 100644 --- a/ios/chrome/browser/providers/chromium_browser_provider.mm +++ b/ios/chrome/browser/providers/chromium_browser_provider.mm
@@ -7,6 +7,7 @@ #include "base/memory/ptr_util.h" #import "ios/chrome/browser/providers/chromium_logo_controller.h" #import "ios/chrome/browser/providers/chromium_voice_search_provider.h" +#import "ios/chrome/browser/providers/chromium_spotlight_provider.h" #import "ios/chrome/browser/providers/images/chromium_branded_image_provider.h" #include "ios/chrome/browser/providers/signin/chromium_signin_resources_provider.h" #include "ios/chrome/browser/providers/ui/chromium_styled_text_field.h" @@ -26,7 +27,8 @@ signin_resources_provider_( base::MakeUnique<ChromiumSigninResourcesProvider>()), user_feedback_provider_(base::MakeUnique<UserFeedbackProvider>()), - voice_search_provider_(base::MakeUnique<ChromiumVoiceSearchProvider>()) {} + voice_search_provider_(base::MakeUnique<ChromiumVoiceSearchProvider>()), + spotlight_provider_(base::MakeUnique<ChromiumSpotlightProvider>()) {} ChromiumBrowserProvider::~ChromiumBrowserProvider() {} @@ -84,3 +86,7 @@ BrandedImageProvider* ChromiumBrowserProvider::GetBrandedImageProvider() const { return branded_image_provider_.get(); } + +SpotlightProvider* ChromiumBrowserProvider::GetSpotlightProvider() const { + return spotlight_provider_.get(); +}
diff --git a/ios/chrome/browser/providers/chromium_spotlight_provider.h b/ios/chrome/browser/providers/chromium_spotlight_provider.h new file mode 100644 index 0000000..c0484b8 --- /dev/null +++ b/ios/chrome/browser/providers/chromium_spotlight_provider.h
@@ -0,0 +1,22 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_PROVIDERS_CHROMIUM_SPOTLIGHT_PROVIDER_H_ +#define IOS_CHROME_BROWSER_PROVIDERS_CHROMIUM_SPOTLIGHT_PROVIDER_H_ + +#import <Foundation/Foundation.h> + +#import "ios/public/provider/chrome/browser/spotlight/spotlight_provider.h" + +class ChromiumSpotlightProvider : public SpotlightProvider { + public: + bool IsSpotlightEnabled() override; + NSString* GetBookmarkDomain() override; + NSString* GetTopSitesDomain() override; + NSString* GetActionsDomain() override; + NSString* GetCustomAttributeItemID() override; + NSArray* GetAdditionalKeywords() override; +}; + +#endif // IOS_CHROME_BROWSER_PROVIDERS_CHROMIUM_SPOTLIGHT_PROVIDER_H_
diff --git a/ios/chrome/browser/providers/chromium_spotlight_provider.mm b/ios/chrome/browser/providers/chromium_spotlight_provider.mm new file mode 100644 index 0000000..8fa6cf4 --- /dev/null +++ b/ios/chrome/browser/providers/chromium_spotlight_provider.mm
@@ -0,0 +1,29 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/providers/chromium_spotlight_provider.h" + +bool ChromiumSpotlightProvider::IsSpotlightEnabled() { + return true; +} + +NSString* ChromiumSpotlightProvider::GetBookmarkDomain() { + return @"org.chromium.bookmarks"; +} + +NSString* ChromiumSpotlightProvider::GetTopSitesDomain() { + return @"org.chromium.topsites"; +} + +NSString* ChromiumSpotlightProvider::GetActionsDomain() { + return @"org.chromium.actions"; +} + +NSString* ChromiumSpotlightProvider::GetCustomAttributeItemID() { + return @"OrgChromiumItemID"; +} + +NSArray* ChromiumSpotlightProvider::GetAdditionalKeywords() { + return @[ @"chromium" ]; +}
diff --git a/ios/chrome/browser/suggestions/BUILD.gn b/ios/chrome/browser/suggestions/BUILD.gn index da48938..216bf04 100644 --- a/ios/chrome/browser/suggestions/BUILD.gn +++ b/ios/chrome/browser/suggestions/BUILD.gn
@@ -20,11 +20,10 @@ "//components/signin/core/browser", "//components/suggestions", "//ios/chrome/browser/browser_state", - "//ios/chrome/browser/net", "//ios/chrome/browser/signin", "//ios/chrome/browser/sync", - "//ios/chrome/browser/webp_transcode", "//ios/web", + "//ios/web/public/image_fetcher", "//net", "//skia", "//ui/gfx",
diff --git a/ios/chrome/browser/suggestions/image_fetcher_impl.h b/ios/chrome/browser/suggestions/image_fetcher_impl.h index a6902d5..dfa1ae5 100644 --- a/ios/chrome/browser/suggestions/image_fetcher_impl.h +++ b/ios/chrome/browser/suggestions/image_fetcher_impl.h
@@ -13,7 +13,6 @@ #include "components/image_fetcher/image_fetcher.h" class GURL; -class ImageFetcher; namespace base { class SequencedWorkerPool; @@ -31,6 +30,10 @@ class URLRequestContextGetter; } +namespace web { +class ImageDataFetcher; +} + namespace suggestions { // A class used to fetch server images asynchronously. @@ -52,7 +55,7 @@ override; private: - std::unique_ptr<::ImageFetcher> imageFetcher_; + std::unique_ptr<web::ImageDataFetcher> image_fetcher_; image_fetcher::ImageFetcherDelegate* delegate_;
diff --git a/ios/chrome/browser/suggestions/image_fetcher_impl.mm b/ios/chrome/browser/suggestions/image_fetcher_impl.mm index 70d93428..9920987f 100644 --- a/ios/chrome/browser/suggestions/image_fetcher_impl.mm +++ b/ios/chrome/browser/suggestions/image_fetcher_impl.mm
@@ -6,9 +6,10 @@ #include <UIKit/UIKit.h> +#include "base/memory/ptr_util.h" #include "base/threading/sequenced_worker_pool.h" #include "components/image_fetcher/image_fetcher_delegate.h" -#include "ios/chrome/browser/net/image_fetcher.h" +#import "ios/web/public/image_fetcher/image_data_fetcher.h" #include "net/url_request/url_request_context_getter.h" #include "skia/ext/skia_utils_ios.h" #include "ui/gfx/image/image.h" @@ -17,9 +18,9 @@ ImageFetcherImpl::ImageFetcherImpl( net::URLRequestContextGetter* url_request_context, - base::SequencedWorkerPool* blocking_pool) { - imageFetcher_.reset(new ::ImageFetcher(blocking_pool)); - imageFetcher_->SetRequestContextGetter(url_request_context); + base::SequencedWorkerPool* blocking_pool) + : image_fetcher_(base::MakeUnique<web::ImageDataFetcher>(blocking_pool)) { + image_fetcher_->SetRequestContextGetter(url_request_context); } ImageFetcherImpl::~ImageFetcherImpl() { @@ -52,27 +53,29 @@ } // Copy string reference so it's retained. const std::string fetch_id(id); - ImageFetchedCallback fetcher_callback = + // If image_fetcher_ is destroyed the request will be cancelled and this block + // will never be called. A reference to delegate_ can be kept. + web::ImageFetchedCallback fetcher_callback = ^(const GURL& original_url, int response_code, NSData* data) { - if (data) { - // Most likely always returns 1x images. - UIImage* ui_image = [UIImage imageWithData:data scale:1]; - if (ui_image) { - gfx::Image gfx_image(ui_image); - callback.Run(fetch_id, gfx_image); - if (delegate_) { - delegate_->OnImageFetched(fetch_id, gfx_image); + if (data) { + // Most likely always returns 1x images. + UIImage* ui_image = [UIImage imageWithData:data scale:1]; + if (ui_image) { + gfx::Image gfx_image(ui_image); + callback.Run(fetch_id, gfx_image); + if (delegate_) { + delegate_->OnImageFetched(fetch_id, gfx_image); + } + return; } - return; } - } - gfx::Image empty_image; - callback.Run(fetch_id, empty_image); - if (delegate_) { - delegate_->OnImageFetched(fetch_id, empty_image); - } - }; - imageFetcher_->StartDownload(image_url, fetcher_callback); + gfx::Image empty_image; + callback.Run(fetch_id, empty_image); + if (delegate_) { + delegate_->OnImageFetched(fetch_id, empty_image); + } + }; + image_fetcher_->StartDownload(image_url, fetcher_callback); } } // namespace suggestions
diff --git a/ios/chrome/browser/suggestions/ios_image_decoder_impl.mm b/ios/chrome/browser/suggestions/ios_image_decoder_impl.mm index 52fc5507..e3525d13 100644 --- a/ios/chrome/browser/suggestions/ios_image_decoder_impl.mm +++ b/ios/chrome/browser/suggestions/ios_image_decoder_impl.mm
@@ -11,7 +11,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/memory/weak_ptr.h" -#include "ios/chrome/browser/webp_transcode/webp_decoder.h" +#import "ios/web/public/image_fetcher/webp_decoder.h" #include "ios/web/public/web_thread.h" #include "ui/gfx/image/image.h"
diff --git a/ios/chrome/browser/webp_transcode/README b/ios/chrome/browser/webp_transcode/README deleted file mode 100644 index 4484825..0000000 --- a/ios/chrome/browser/webp_transcode/README +++ /dev/null
@@ -1,2 +0,0 @@ -webp_transcode is used to convert WebP images to other formats supported by the -iOS web views.
diff --git a/ios/public/provider/chrome/browser/BUILD.gn b/ios/public/provider/chrome/browser/BUILD.gn index 72e0c31..9de14fb 100644 --- a/ios/public/provider/chrome/browser/BUILD.gn +++ b/ios/public/provider/chrome/browser/BUILD.gn
@@ -38,6 +38,7 @@ "//ios/public/provider/chrome/browser/omaha:test_support", "//ios/public/provider/chrome/browser/sessions:test_support", "//ios/public/provider/chrome/browser/signin:test_support", + "//ios/public/provider/chrome/browser/spotlight:test_support", "//ios/public/provider/chrome/browser/ui", "//ios/public/provider/chrome/browser/ui:test_support", "//ios/public/provider/chrome/browser/user_feedback:test_support",
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.h b/ios/public/provider/chrome/browser/chrome_browser_provider.h index eb577ab..92db0be 100644 --- a/ios/public/provider/chrome/browser/chrome_browser_provider.h +++ b/ios/public/provider/chrome/browser/chrome_browser_provider.h
@@ -25,6 +25,7 @@ class OmahaServiceProvider; class PrefRegistrySimple; class PrefService; +class SpotlightProvider; class UserFeedbackProvider; class VoiceSearchProvider; @@ -192,6 +193,9 @@ // Logs if any modals created by this provider are still presented. It does // not dismiss them. virtual void LogIfModalViewsArePresented() const; + + // Returns an instance of the spotlight provider. + virtual SpotlightProvider* GetSpotlightProvider() const; }; } // namespace ios
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.mm b/ios/public/provider/chrome/browser/chrome_browser_provider.mm index dc5fb2e..95d9aec 100644 --- a/ios/public/provider/chrome/browser/chrome_browser_provider.mm +++ b/ios/public/provider/chrome/browser/chrome_browser_provider.mm
@@ -146,6 +146,10 @@ return nullptr; } +SpotlightProvider* ChromeBrowserProvider::GetSpotlightProvider() const { + return nullptr; +} + BrandedImageProvider* ChromeBrowserProvider::GetBrandedImageProvider() const { return nullptr; }
diff --git a/ios/public/provider/chrome/browser/spotlight/BUILD.gn b/ios/public/provider/chrome/browser/spotlight/BUILD.gn new file mode 100644 index 0000000..816bf722 --- /dev/null +++ b/ios/public/provider/chrome/browser/spotlight/BUILD.gn
@@ -0,0 +1,25 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("spotlight") { + sources = [ + "spotlight_provider.h", + "spotlight_provider.mm", + ] + deps = [ + "//base", + ] + libs = [ "Foundation.framework" ] +} + +source_set("test_support") { + testonly = true + sources = [ + "test_spotlight_provider.h", + "test_spotlight_provider.mm", + ] + deps = [ + ":spotlight", + ] +}
diff --git a/ios/public/provider/chrome/browser/spotlight/spotlight_provider.h b/ios/public/provider/chrome/browser/spotlight/spotlight_provider.h new file mode 100644 index 0000000..9e9c5f20 --- /dev/null +++ b/ios/public/provider/chrome/browser/spotlight/spotlight_provider.h
@@ -0,0 +1,39 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SPOTLIGHT_SPOTLIGHT_PROVIDER_H +#define IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SPOTLIGHT_SPOTLIGHT_PROVIDER_H + +#import <Foundation/Foundation.h> + +#import "base/macros.h" + +class SpotlightProvider { + public: + SpotlightProvider() {} + virtual ~SpotlightProvider() {} + + // Returns if the provider provides valid values on all other methods. + virtual bool IsSpotlightEnabled(); + + // Returns the spotlight domain for bookmarks items. + virtual NSString* GetBookmarkDomain(); + + // Returns the spotlight domain for top sites items. + virtual NSString* GetTopSitesDomain(); + + // Returns the spotlight domain for action items. + virtual NSString* GetActionsDomain(); + + // Returns the id for the custom item containing item ID in Spotlight index. + virtual NSString* GetCustomAttributeItemID(); + + // Returns additional keywords that are added to all Spotlight items. + virtual NSArray* GetAdditionalKeywords(); + + private: + DISALLOW_COPY_AND_ASSIGN(SpotlightProvider); +}; + +#endif // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SPOTLIGHT_SPOTLIGHT_PROVIDER_H
diff --git a/ios/public/provider/chrome/browser/spotlight/spotlight_provider.mm b/ios/public/provider/chrome/browser/spotlight/spotlight_provider.mm new file mode 100644 index 0000000..2a9c2da --- /dev/null +++ b/ios/public/provider/chrome/browser/spotlight/spotlight_provider.mm
@@ -0,0 +1,29 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/public/provider/chrome/browser/spotlight/spotlight_provider.h" + +bool SpotlightProvider::IsSpotlightEnabled() { + return false; +} + +NSString* SpotlightProvider::GetBookmarkDomain() { + return nil; +} + +NSString* SpotlightProvider::GetTopSitesDomain() { + return nil; +} + +NSString* SpotlightProvider::GetActionsDomain() { + return nil; +} + +NSString* SpotlightProvider::GetCustomAttributeItemID() { + return nil; +} + +NSArray* SpotlightProvider::GetAdditionalKeywords() { + return nil; +}
diff --git a/ios/public/provider/chrome/browser/spotlight/test_spotlight_provider.h b/ios/public/provider/chrome/browser/spotlight/test_spotlight_provider.h new file mode 100644 index 0000000..11eff13d --- /dev/null +++ b/ios/public/provider/chrome/browser/spotlight/test_spotlight_provider.h
@@ -0,0 +1,22 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SPOTLIGHT_TEST_SPOTLIGHT_PROVIDER_H +#define IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SPOTLIGHT_TEST_SPOTLIGHT_PROVIDER_H + +#import <Foundation/Foundation.h> + +#import "ios/public/provider/chrome/browser/spotlight/spotlight_provider.h" + +class TestSpotlightProvider : public SpotlightProvider { + public: + bool IsSpotlightEnabled() override; + NSString* GetBookmarkDomain() override; + NSString* GetTopSitesDomain() override; + NSString* GetActionsDomain() override; + NSString* GetCustomAttributeItemID() override; + NSArray* GetAdditionalKeywords() override; +}; + +#endif // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SPOTLIGHT_TEST_SPOTLIGHT_PROVIDER_H
diff --git a/ios/public/provider/chrome/browser/spotlight/test_spotlight_provider.mm b/ios/public/provider/chrome/browser/spotlight/test_spotlight_provider.mm new file mode 100644 index 0000000..4dcdac2d --- /dev/null +++ b/ios/public/provider/chrome/browser/spotlight/test_spotlight_provider.mm
@@ -0,0 +1,29 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/public/provider/chrome/browser/spotlight/test_spotlight_provider.h" + +bool TestSpotlightProvider::IsSpotlightEnabled() { + return true; +} + +NSString* TestSpotlightProvider::GetBookmarkDomain() { + return @"org.chromium.bookmarks"; +} + +NSString* TestSpotlightProvider::GetTopSitesDomain() { + return @"org.chromium.topsites"; +} + +NSString* TestSpotlightProvider::GetActionsDomain() { + return @"org.chromium.actions"; +} + +NSString* TestSpotlightProvider::GetCustomAttributeItemID() { + return @"OrgChromiumItemID"; +} + +NSArray* TestSpotlightProvider::GetAdditionalKeywords() { + return @[ @"chromium" ]; +}
diff --git a/ios/public/provider/chrome/browser/test_chrome_browser_provider.h b/ios/public/provider/chrome/browser/test_chrome_browser_provider.h index 62de8bf..22ddbea7 100644 --- a/ios/public/provider/chrome/browser/test_chrome_browser_provider.h +++ b/ios/public/provider/chrome/browser/test_chrome_browser_provider.h
@@ -36,6 +36,7 @@ AppDistributionProvider* GetAppDistributionProvider() const override; OmahaServiceProvider* GetOmahaServiceProvider() const override; UserFeedbackProvider* GetUserFeedbackProvider() const override; + SpotlightProvider* GetSpotlightProvider() const override; std::unique_ptr<sync_sessions::SyncedWindowDelegatesGetter> CreateSyncedWindowDelegatesGetter( ios::ChromeBrowserState* browser_state) override; @@ -51,6 +52,7 @@ std::unique_ptr<SigninResourcesProvider> signin_resources_provider_; std::unique_ptr<VoiceSearchProvider> voice_search_provider_; std::unique_ptr<UserFeedbackProvider> user_feedback_provider_; + std::unique_ptr<SpotlightProvider> spotlight_provider_; DISALLOW_COPY_AND_ASSIGN(TestChromeBrowserProvider); };
diff --git a/ios/public/provider/chrome/browser/test_chrome_browser_provider.mm b/ios/public/provider/chrome/browser/test_chrome_browser_provider.mm index e097404..be379676 100644 --- a/ios/public/provider/chrome/browser/test_chrome_browser_provider.mm +++ b/ios/public/provider/chrome/browser/test_chrome_browser_provider.mm
@@ -16,6 +16,7 @@ #include "ios/public/provider/chrome/browser/sessions/test_synced_window_delegates_getter.h" #include "ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h" #include "ios/public/provider/chrome/browser/signin/test_signin_resources_provider.h" +#import "ios/public/provider/chrome/browser/spotlight/test_spotlight_provider.h" #import "ios/public/provider/chrome/browser/ui/test_infobar_view.h" #import "ios/public/provider/chrome/browser/ui/test_styled_text_field.h" #import "ios/public/provider/chrome/browser/user_feedback/test_user_feedback_provider.h" @@ -34,7 +35,8 @@ signin_resources_provider_( base::MakeUnique<TestSigninResourcesProvider>()), voice_search_provider_(base::MakeUnique<TestVoiceSearchProvider>()), - user_feedback_provider_(base::MakeUnique<TestUserFeedbackProvider>()) {} + user_feedback_provider_(base::MakeUnique<TestUserFeedbackProvider>()), + spotlight_provider_(base::MakeUnique<TestSpotlightProvider>()) {} TestChromeBrowserProvider::~TestChromeBrowserProvider() {} @@ -96,6 +98,10 @@ return user_feedback_provider_.get(); } +SpotlightProvider* TestChromeBrowserProvider::GetSpotlightProvider() const { + return spotlight_provider_.get(); +} + std::unique_ptr<sync_sessions::SyncedWindowDelegatesGetter> TestChromeBrowserProvider::CreateSyncedWindowDelegatesGetter( ios::ChromeBrowserState* browser_state) {
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn index 8c6aa55..6a6ba6fe 100644 --- a/ios/web/BUILD.gn +++ b/ios/web/BUILD.gn
@@ -363,6 +363,7 @@ "//ios/testing:ios_test_support", "//ios/testing:ocmock_support", "//ios/third_party/gcdwebserver", + "//ios/web/public/image_fetcher", "//ios/web/test:mojo_bindings", "//net:test_support", "//testing/gmock", @@ -380,6 +381,8 @@ "public/test/http_server_util.mm", "public/test/js_test_util.h", "public/test/js_test_util.mm", + "public/test/mock_image_data_fetcher.h", + "public/test/mock_image_data_fetcher.mm", "public/test/native_controller_test_util.h", "public/test/native_controller_test_util.mm", "public/test/navigation_test_util.h", @@ -478,6 +481,7 @@ "//base/test:test_support", "//ios/net", "//ios/testing:ocmock_support", + "//ios/web/public/image_fetcher:unit_tests", "//ios/web/test:mojo_bindings", "//net:test_support", "//services/service_manager/public/cpp",
diff --git a/ios/chrome/browser/webp_transcode/BUILD.gn b/ios/web/public/image_fetcher/BUILD.gn similarity index 62% rename from ios/chrome/browser/webp_transcode/BUILD.gn rename to ios/web/public/image_fetcher/BUILD.gn index f52fbfc9..7c93ce1d 100644 --- a/ios/chrome/browser/webp_transcode/BUILD.gn +++ b/ios/web/public/image_fetcher/BUILD.gn
@@ -2,14 +2,17 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("webp_transcode") { +source_set("image_fetcher") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ + "image_data_fetcher.h", + "image_data_fetcher.mm", "webp_decoder.h", "webp_decoder.mm", ] deps = [ "//base", + "//net", "//third_party/libwebp:libwebp_dec", ] } @@ -18,12 +21,15 @@ configs += [ "//build/config/compiler:enable_arc" ] testonly = true sources = [ + "image_data_fetcher_unittest.mm", "webp_decoder_unittest.mm", ] deps = [ - ":webp_transcode", + ":image_fetcher", ":webp_transcode_unit_tests_bundle_data", "//base", + "//net", + "//net:test_support", "//testing/gmock", "//testing/gtest", ] @@ -34,12 +40,12 @@ visibility = [ ":unit_tests" ] testonly = true sources = [ - "//ios/chrome/test/data/webp_transcode/test.jpg", - "//ios/chrome/test/data/webp_transcode/test.webp", - "//ios/chrome/test/data/webp_transcode/test_alpha.png", - "//ios/chrome/test/data/webp_transcode/test_alpha.webp", - "//ios/chrome/test/data/webp_transcode/test_small.tiff", - "//ios/chrome/test/data/webp_transcode/test_small.webp", + "//ios/web/test/data/webp_transcode/test.jpg", + "//ios/web/test/data/webp_transcode/test.webp", + "//ios/web/test/data/webp_transcode/test_alpha.png", + "//ios/web/test/data/webp_transcode/test_alpha.webp", + "//ios/web/test/data/webp_transcode/test_small.tiff", + "//ios/web/test/data/webp_transcode/test_small.webp", ] outputs = [ "{{bundle_resources_dir}}/{{source_root_relative_dir}}/" +
diff --git a/ios/chrome/browser/webp_transcode/DEPS b/ios/web/public/image_fetcher/DEPS similarity index 100% rename from ios/chrome/browser/webp_transcode/DEPS rename to ios/web/public/image_fetcher/DEPS
diff --git a/ios/chrome/browser/webp_transcode/OWNERS b/ios/web/public/image_fetcher/OWNERS similarity index 100% rename from ios/chrome/browser/webp_transcode/OWNERS rename to ios/web/public/image_fetcher/OWNERS
diff --git a/ios/web/public/image_fetcher/image_data_fetcher.h b/ios/web/public/image_fetcher/image_data_fetcher.h new file mode 100644 index 0000000..797a2d3e9 --- /dev/null +++ b/ios/web/public/image_fetcher/image_data_fetcher.h
@@ -0,0 +1,96 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_WEB_PUBLIC_IMAGE_FETCHER_IMAGE_DATA_FETCHER_H_ +#define IOS_WEB_PUBLIC_IMAGE_FETCHER_IMAGE_DATA_FETCHER_H_ + +#include <map> + +#include "base/mac/scoped_block.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "net/url_request/url_fetcher_delegate.h" +#include "net/url_request/url_request.h" + +class GURL; +@class NSData; + +namespace base { +class TaskRunner; +} + +namespace net { +class URLRequestContextGetter; +} + +namespace web { + +// Callback that informs of the download of an image encoded in |data|, +// downloaded from |url|, and with the http status |http_response_code|. If the +// url is a data URL, |http_response_code| is always 200. +using ImageFetchedCallback = void (^)(const GURL& url, + int http_response_code, + NSData* data); + +// Utility class that will retrieve an image from an URL. The image is returned +// as NSData which can be used with +[UIImage imageWithData:]. This class +// usually returns the raw bytes retrieved from the network without any +// processing, with the exception of WebP encoded images. Those are decoded and +// then reencoded in a format suitable for UIImage. +// An instance of this class can download a number of images at the same time. +class ImageDataFetcher : public net::URLFetcherDelegate { + public: + // The TaskRunner is used to eventually decode the image. + explicit ImageDataFetcher(const scoped_refptr<base::TaskRunner>& task_runner); + ~ImageDataFetcher() override; + + // Start downloading the image at the given |url|. The |callback| will be + // called with the downloaded image, or nil if any error happened. The + // |referrer| and |referrer_policy| will be passed on to the underlying + // URLFetcher. + // This method assumes the request context getter has been set. + // (virtual for testing) + virtual void StartDownload(const GURL& url, + ImageFetchedCallback callback, + const std::string& referrer, + net::URLRequest::ReferrerPolicy referrer_policy); + + // Helper method to call StartDownload without a referrer. + // (virtual for testing) + virtual void StartDownload(const GURL& url, ImageFetchedCallback callback); + + // A valid request context getter is required before starting the download. + // (virtual for testing) + virtual void SetRequestContextGetter( + const scoped_refptr<net::URLRequestContextGetter>& + request_context_getter); + + // net::URLFetcherDelegate: + void OnURLFetchComplete(const net::URLFetcher* source) override; + + private: + // Runs the callback with the given arguments. + void RunCallback(const base::mac::ScopedBlock<ImageFetchedCallback>& callback, + const GURL& url, + const int http_response_code, + NSData* data); + + // Tracks open download requests. The key is the URLFetcher object doing the + // fetch; the value is the callback to use when the download request + // completes. When a download request completes, the URLFetcher must be + // deleted and the callback called and released. + std::map<const net::URLFetcher*, ImageFetchedCallback> downloads_in_progress_; + scoped_refptr<net::URLRequestContextGetter> request_context_getter_; + + // The task runner used to decode images if necessary. + const scoped_refptr<base::TaskRunner> task_runner_; + + // The WeakPtrFactory is used to cancel callbacks if ImageDataFetcher is + // destroyed during WebP decoding. + base::WeakPtrFactory<ImageDataFetcher> weak_factory_; +}; + +#endif // IOS_WEB_PUBLIC_IMAGE_FETCHER_IMAGE_DATA_FETCHER_H_ + +} // namespace web
diff --git a/ios/web/public/image_fetcher/image_data_fetcher.mm b/ios/web/public/image_fetcher/image_data_fetcher.mm new file mode 100644 index 0000000..cc7167db --- /dev/null +++ b/ios/web/public/image_fetcher/image_data_fetcher.mm
@@ -0,0 +1,179 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/web/public/image_fetcher/image_data_fetcher.h" + +#import <Foundation/Foundation.h> +#include <stddef.h> + +#include "base/bind.h" +#include "base/location.h" +#include "base/mac/scoped_nsobject.h" +#include "base/task_runner.h" +#include "base/task_runner_util.h" +#include "ios/web/public/image_fetcher/webp_decoder.h" +#include "net/base/load_flags.h" +#include "net/http/http_response_headers.h" +#include "net/url_request/url_fetcher.h" +#include "net/url_request/url_request_context_getter.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { + +class WebpDecoderDelegate : public webp_transcode::WebpDecoder::Delegate { + public: + NSData* data() const { return decoded_image_; } + + // WebpDecoder::Delegate methods + void OnFinishedDecoding(bool success) override { + if (!success) + decoded_image_.reset(); + } + void SetImageFeatures( + size_t total_size, + webp_transcode::WebpDecoder::DecodedImageFormat format) override { + decoded_image_.reset([[NSMutableData alloc] initWithCapacity:total_size]); + } + void OnDataDecoded(NSData* data) override { + DCHECK(decoded_image_); + [decoded_image_ appendData:data]; + } + + private: + ~WebpDecoderDelegate() override {} + base::scoped_nsobject<NSMutableData> decoded_image_; +}; + +// Content-type header for WebP images. +static const char kWEBPMimeType[] = "image/webp"; + +// Returns a NSData object containing the decoded image. +// Returns nil in case of failure. +base::scoped_nsobject<NSData> DecodeWebpImage( + const base::scoped_nsobject<NSData>& webp_image) { + scoped_refptr<WebpDecoderDelegate> delegate(new WebpDecoderDelegate); + scoped_refptr<webp_transcode::WebpDecoder> decoder( + new webp_transcode::WebpDecoder(delegate.get())); + decoder->OnDataReceived(webp_image); + DLOG_IF(ERROR, !delegate->data()) << "WebP image decoding failed."; + return base::scoped_nsobject<NSData>(delegate->data()); +} + +} // namespace + +namespace web { + +ImageDataFetcher::ImageDataFetcher( + const scoped_refptr<base::TaskRunner>& task_runner) + : request_context_getter_(nullptr), + task_runner_(task_runner), + weak_factory_(this) { + DCHECK(task_runner_.get()); +} + +ImageDataFetcher::~ImageDataFetcher() { + // Delete all the entries in the |downloads_in_progress_| map. This will in + // turn cancel all of the requests. + for (const auto& pair : downloads_in_progress_) { + delete pair.first; + } +} + +void ImageDataFetcher::StartDownload( + const GURL& url, + ImageFetchedCallback callback, + const std::string& referrer, + net::URLRequest::ReferrerPolicy referrer_policy) { + DCHECK(request_context_getter_.get()); + net::URLFetcher* fetcher = + net::URLFetcher::Create(url, net::URLFetcher::GET, this).release(); + downloads_in_progress_[fetcher] = [callback copy]; + fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | + net::LOAD_DO_NOT_SAVE_COOKIES | + net::LOAD_DO_NOT_SEND_AUTH_DATA); + fetcher->SetRequestContext(request_context_getter_.get()); + fetcher->SetReferrer(referrer); + fetcher->SetReferrerPolicy(referrer_policy); + fetcher->Start(); +} + +void ImageDataFetcher::StartDownload(const GURL& url, + ImageFetchedCallback callback) { + ImageDataFetcher::StartDownload(url, callback, std::string(), + net::URLRequest::NEVER_CLEAR_REFERRER); +} + +// Delegate callback that is called when URLFetcher completes. If the image +// was fetched successfully, creates a new NSData and returns it to the +// callback, otherwise returns nil to the callback. +void ImageDataFetcher::OnURLFetchComplete(const net::URLFetcher* fetcher) { + if (downloads_in_progress_.find(fetcher) == downloads_in_progress_.end()) { + LOG(ERROR) << "Received callback for unknown URLFetcher " << fetcher; + return; + } + + // Ensures that |fetcher| will be deleted in the event of early return. + std::unique_ptr<const net::URLFetcher> fetcher_deleter(fetcher); + + // Retrieves the callback and ensures that it will be deleted in the event + // of early return. + base::mac::ScopedBlock<ImageFetchedCallback> callback( + downloads_in_progress_[fetcher]); + + // Remove |fetcher| from the map. + downloads_in_progress_.erase(fetcher); + + // Make sure the request was successful. For "data" requests, the response + // code has no meaning, because there is no actual server (data is encoded + // directly in the URL). In that case, set the response code to 200 (OK). + const GURL& original_url = fetcher->GetOriginalURL(); + const int http_response_code = + original_url.SchemeIs("data") ? 200 : fetcher->GetResponseCode(); + if (http_response_code != 200) { + (callback.get())(original_url, http_response_code, nil); + return; + } + + std::string response; + if (!fetcher->GetResponseAsString(&response)) { + (callback.get())(original_url, http_response_code, nil); + return; + } + + // Create a NSData from the returned data and notify the callback. + base::scoped_nsobject<NSData> data([[NSData alloc] + initWithBytes:reinterpret_cast<const unsigned char*>(response.data()) + length:response.size()]); + + if (fetcher->GetResponseHeaders()) { + std::string mime_type; + fetcher->GetResponseHeaders()->GetMimeType(&mime_type); + if (mime_type == kWEBPMimeType) { + base::PostTaskAndReplyWithResult( + task_runner_.get(), FROM_HERE, base::Bind(&DecodeWebpImage, data), + base::Bind(&ImageDataFetcher::RunCallback, weak_factory_.GetWeakPtr(), + callback, original_url, http_response_code)); + return; + } + } + (callback.get())(original_url, http_response_code, data); +} + +void ImageDataFetcher::RunCallback( + const base::mac::ScopedBlock<ImageFetchedCallback>& callback, + const GURL& url, + int http_response_code, + NSData* data) { + (callback.get())(url, http_response_code, data); +} + +void ImageDataFetcher::SetRequestContextGetter( + const scoped_refptr<net::URLRequestContextGetter>& request_context_getter) { + request_context_getter_ = request_context_getter; +} + +} // namespace web
diff --git a/ios/web/public/image_fetcher/image_data_fetcher_unittest.mm b/ios/web/public/image_fetcher/image_data_fetcher_unittest.mm new file mode 100644 index 0000000..06412ec --- /dev/null +++ b/ios/web/public/image_fetcher/image_data_fetcher_unittest.mm
@@ -0,0 +1,217 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/web/public/image_fetcher/image_data_fetcher.h" + +#import <UIKit/UIKit.h> + +#include "base/ios/ios_util.h" +#include "base/mac/scoped_block.h" +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/memory/ref_counted.h" +#include "base/run_loop.h" +#include "base/threading/thread.h" +#include "base/threading/thread_task_runner_handle.h" +#include "build/build_config.h" +#include "net/http/http_response_headers.h" +#include "net/url_request/test_url_fetcher_factory.h" +#include "net/url_request/url_request_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +namespace { + +static unsigned char kJPGImage[] = { + 255, 216, 255, 224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 1, 0, + 72, 0, 72, 0, 0, 255, 254, 0, 19, 67, 114, 101, 97, 116, 101, + 100, 32, 119, 105, 116, 104, 32, 71, 73, 77, 80, 255, 219, 0, 67, + 0, 5, 3, 4, 4, 4, 3, 5, 4, 4, 4, 5, 5, 5, 6, + 7, 12, 8, 7, 7, 7, 7, 15, 11, 11, 9, 12, 17, 15, 18, + 18, 17, 15, 17, 17, 19, 22, 28, 23, 19, 20, 26, 21, 17, 17, + 24, 33, 24, 26, 29, 29, 31, 31, 31, 19, 23, 34, 36, 34, 30, + 36, 28, 30, 31, 30, 255, 219, 0, 67, 1, 5, 5, 5, 7, 6, + 7, 14, 8, 8, 14, 30, 20, 17, 20, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 255, + 192, 0, 17, 8, 0, 1, 0, 1, 3, 1, 34, 0, 2, 17, 1, + 3, 17, 1, 255, 196, 0, 21, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 255, 196, 0, 20, + 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 255, 196, 0, 20, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 196, 0, 20, 17, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 255, 218, 0, 12, 3, 1, 0, 2, 17, 3, 17, 0, 63, + 0, 178, 192, 7, 255, 217}; + +static unsigned char kPNGImage[] = { + 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, + 82, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 55, + 110, 249, 36, 0, 0, 0, 2, 98, 75, 71, 68, 0, 1, 221, 138, + 19, 164, 0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 11, 18, 0, + 0, 11, 18, 1, 210, 221, 126, 252, 0, 0, 0, 9, 118, 112, 65, + 103, 0, 0, 0, 1, 0, 0, 0, 1, 0, 199, 149, 95, 237, 0, + 0, 0, 10, 73, 68, 65, 84, 8, 215, 99, 104, 0, 0, 0, 130, + 0, 129, 221, 67, 106, 244, 0, 0, 0, 25, 116, 69, 88, 116, 99, + 111, 109, 109, 101, 110, 116, 0, 67, 114, 101, 97, 116, 101, 100, 32, + 119, 105, 116, 104, 32, 71, 73, 77, 80, 231, 175, 64, 203, 0, 0, + 0, 37, 116, 69, 88, 116, 100, 97, 116, 101, 58, 99, 114, 101, 97, + 116, 101, 0, 50, 48, 49, 49, 45, 48, 54, 45, 50, 50, 84, 49, + 54, 58, 49, 54, 58, 52, 54, 43, 48, 50, 58, 48, 48, 31, 248, + 231, 223, 0, 0, 0, 37, 116, 69, 88, 116, 100, 97, 116, 101, 58, + 109, 111, 100, 105, 102, 121, 0, 50, 48, 49, 49, 45, 48, 54, 45, + 50, 50, 84, 49, 54, 58, 49, 54, 58, 52, 54, 43, 48, 50, 58, + 48, 48, 110, 165, 95, 99, 0, 0, 0, 17, 116, 69, 88, 116, 106, + 112, 101, 103, 58, 99, 111, 108, 111, 114, 115, 112, 97, 99, 101, 0, + 50, 44, 117, 85, 159, 0, 0, 0, 32, 116, 69, 88, 116, 106, 112, + 101, 103, 58, 115, 97, 109, 112, 108, 105, 110, 103, 45, 102, 97, 99, + 116, 111, 114, 0, 50, 120, 50, 44, 49, 120, 49, 44, 49, 120, 49, + 73, 250, 166, 180, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, + 130}; + +static unsigned char kWEBPImage[] = { + 82, 73, 70, 70, 74, 0, 0, 0, 87, 69, 66, 80, 86, 80, 56, 88, 10, + 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 76, 80, 72, + 12, 0, 0, 0, 1, 7, 16, 17, 253, 15, 68, 68, 255, 3, 0, 0, 86, + 80, 56, 32, 24, 0, 0, 0, 48, 1, 0, 157, 1, 42, 1, 0, 1, 0, + 3, 0, 52, 37, 164, 0, 3, 112, 0, 254, 251, 253, 80, 0}; + +static const char kTestUrl[] = "http://www.img.com"; + +static const char kWEBPHeaderResponse[] = + "HTTP/1.1 200 OK\0Content-type: image/webp\0\0"; + +} // namespace + +namespace web { + +class ImageDataFetcherTest : public PlatformTest { + protected: + ImageDataFetcherTest() + : worker_thread_("TestThread"), + callback_( + [^(const GURL& original_url, int http_response_code, NSData* data) { + result_ = [UIImage imageWithData:data]; + called_ = true; + } copy]) { + worker_thread_.Start(); + + image_fetcher_ = + base::MakeUnique<ImageDataFetcher>(worker_thread_.task_runner()); + image_fetcher_->SetRequestContextGetter( + new net::TestURLRequestContextGetter( + base::ThreadTaskRunnerHandle::Get())); + } + + net::TestURLFetcher* SetupFetcher() { + image_fetcher_->StartDownload(GURL(kTestUrl), callback_); + EXPECT_EQ(nil, result_); + EXPECT_EQ(false, called_); + net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0); + DCHECK(fetcher); + DCHECK(fetcher->delegate()); + return fetcher; + } + + // Message loop for the main test thread. + base::MessageLoop loop_; + + // Worker thread used for ImageFetcher's asynchronous work. + base::Thread worker_thread_; + + base::mac::ScopedBlock<ImageFetchedCallback> callback_; + net::TestURLFetcherFactory factory_; + std::unique_ptr<ImageDataFetcher> image_fetcher_; + UIImage* result_ = nil; + bool called_ = false; + + private: + DISALLOW_COPY_AND_ASSIGN(ImageDataFetcherTest); +}; + +TEST_F(ImageDataFetcherTest, TestError) { + net::TestURLFetcher* fetcher = SetupFetcher(); + fetcher->set_response_code(404); + fetcher->delegate()->OnURLFetchComplete(fetcher); + EXPECT_EQ(nil, result_); + EXPECT_TRUE(called_); +} + +TEST_F(ImageDataFetcherTest, TestJpg) { + net::TestURLFetcher* fetcher = SetupFetcher(); + fetcher->set_response_code(200); + fetcher->SetResponseString(std::string((char*)kJPGImage, sizeof(kJPGImage))); + fetcher->delegate()->OnURLFetchComplete(fetcher); + EXPECT_NE(nil, result_); + EXPECT_TRUE(called_); +} + +TEST_F(ImageDataFetcherTest, TestPng) { + net::TestURLFetcher* fetcher = SetupFetcher(); + fetcher->set_response_code(200); + fetcher->SetResponseString(std::string((char*)kPNGImage, sizeof(kPNGImage))); + fetcher->delegate()->OnURLFetchComplete(fetcher); + EXPECT_NE(nil, result_); + EXPECT_TRUE(called_); +} + +TEST_F(ImageDataFetcherTest, TestGoodWebP) { +// TODO(droger): This test fails on iOS 9 x64 devices. http://crbug.com/523235 +#if defined(OS_IOS) && defined(ARCH_CPU_ARM64) && !TARGET_IPHONE_SIMULATOR + if (base::ios::IsRunningOnIOS9OrLater()) + return; +#endif + net::TestURLFetcher* fetcher = SetupFetcher(); + fetcher->set_response_code(200); + fetcher->SetResponseString( + std::string((char*)kWEBPImage, sizeof(kWEBPImage))); + scoped_refptr<net::HttpResponseHeaders> headers(new net::HttpResponseHeaders( + std::string(kWEBPHeaderResponse, arraysize(kWEBPHeaderResponse)))); + fetcher->set_response_headers(headers); + fetcher->delegate()->OnURLFetchComplete(fetcher); + worker_thread_.FlushForTesting(); + base::RunLoop().RunUntilIdle(); + EXPECT_NE(nil, result_); + EXPECT_TRUE(called_); +} + +TEST_F(ImageDataFetcherTest, TestBadWebP) { + net::TestURLFetcher* fetcher = SetupFetcher(); + fetcher->set_response_code(200); + fetcher->SetResponseString("This is not a valid WebP image"); + scoped_refptr<net::HttpResponseHeaders> headers(new net::HttpResponseHeaders( + std::string(kWEBPHeaderResponse, arraysize(kWEBPHeaderResponse)))); + fetcher->set_response_headers(headers); + fetcher->delegate()->OnURLFetchComplete(fetcher); + worker_thread_.FlushForTesting(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(nil, result_); + EXPECT_TRUE(called_); +} + +TEST_F(ImageDataFetcherTest, DeleteDuringWebPDecoding) { + net::TestURLFetcher* fetcher = SetupFetcher(); + fetcher->set_response_code(200); + fetcher->SetResponseString( + std::string((char*)kWEBPImage, sizeof(kWEBPImage))); + scoped_refptr<net::HttpResponseHeaders> headers(new net::HttpResponseHeaders( + std::string(kWEBPHeaderResponse, arraysize(kWEBPHeaderResponse)))); + fetcher->set_response_headers(headers); + fetcher->delegate()->OnURLFetchComplete(fetcher); + // Delete the image fetcher, and check that the callback is not called. + image_fetcher_.reset(); + worker_thread_.FlushForTesting(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(nil, result_); + EXPECT_FALSE(called_); +} + +TEST_F(ImageDataFetcherTest, TestCallbacksNotCalledDuringDeletion) { + image_fetcher_->StartDownload(GURL(kTestUrl), callback_); + image_fetcher_.reset(); + EXPECT_FALSE(called_); +} + +} // namespace web
diff --git a/ios/chrome/browser/webp_transcode/webp_decoder.h b/ios/web/public/image_fetcher/webp_decoder.h similarity index 92% rename from ios/chrome/browser/webp_transcode/webp_decoder.h rename to ios/web/public/image_fetcher/webp_decoder.h index e2f5714..1ab4d6c5 100644 --- a/ios/chrome/browser/webp_transcode/webp_decoder.h +++ b/ios/web/public/image_fetcher/webp_decoder.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_WEBP_TRANSCODE_WEBP_DECODER_H_ -#define IOS_CHROME_BROWSER_WEBP_TRANSCODE_WEBP_DECODER_H_ +#ifndef IOS_WEB_PUBLIC_IMAGE_FETCHER_WEBP_DECODER_H_ +#define IOS_WEB_PUBLIC_IMAGE_FETCHER_WEBP_DECODER_H_ #import <Foundation/Foundation.h> #include <stddef.h> @@ -75,4 +75,4 @@ } // namespace webp_transcode -#endif // IOS_CHROME_BROWSER_WEBP_TRANSCODE_WEBP_DECODER_H_ +#endif // IOS_WEB_PUBLIC_IMAGE_FETCHER_WEBP_DECODER_H_
diff --git a/ios/chrome/browser/webp_transcode/webp_decoder.mm b/ios/web/public/image_fetcher/webp_decoder.mm similarity index 79% rename from ios/chrome/browser/webp_transcode/webp_decoder.mm rename to ios/web/public/image_fetcher/webp_decoder.mm index 16f2b4a7..935deee 100644 --- a/ios/chrome/browser/webp_transcode/webp_decoder.mm +++ b/ios/web/public/image_fetcher/webp_decoder.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ios/chrome/browser/webp_transcode/webp_decoder.h" +#include "ios/web/public/image_fetcher/webp_decoder.h" #import <Foundation/Foundation.h> #include <stdint.h> @@ -45,34 +45,34 @@ const uint8_t num_ifd_entries = has_alpha ? kNumIfdEntries : kNumIfdEntries - 1; uint8_t tiff_header[kHeaderSize] = { - 0x49, 0x49, 0x2a, 0x00, // little endian signature - 8, 0, 0, 0, // offset to the unique IFD that follows - // IFD (offset = 8). Entries must be written in increasing tag order. - num_ifd_entries, 0, // Number of entries in the IFD (12 bytes each). - 0x00, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 10: Width (TBD) - 0x01, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 22: Height (TBD) - 0x02, 0x01, 3, 0, bytes_per_px, 0, 0, 0, // 34: BitsPerSample: 8888 - kExtraDataOffset + 0, 0, 0, 0, - 0x03, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 46: Compression: none - 0x06, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 58: Photometric: RGB - 0x11, 0x01, 4, 0, 1, 0, 0, 0, // 70: Strips offset: - kHeaderSize, 0, 0, 0, // data follows header - 0x12, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 82: Orientation: topleft - 0x15, 0x01, 3, 0, 1, 0, 0, 0, // 94: SamplesPerPixels - bytes_per_px, 0, 0, 0, - 0x16, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 106: Rows per strip (TBD) - 0x17, 0x01, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 118: StripByteCount (TBD) - 0x1a, 0x01, 5, 0, 1, 0, 0, 0, // 130: X-resolution - kExtraDataOffset + 8, 0, 0, 0, - 0x1b, 0x01, 5, 0, 1, 0, 0, 0, // 142: Y-resolution - kExtraDataOffset + 8, 0, 0, 0, - 0x1c, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 154: PlanarConfiguration - 0x28, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 166: ResolutionUnit (inch) - 0x52, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 178: ExtraSamples: rgbA - 0, 0, 0, 0, // 190: IFD terminator - // kExtraDataOffset: - 8, 0, 8, 0, 8, 0, 8, 0, // BitsPerSample - 72, 0, 0, 0, 1, 0, 0, 0 // 72 pixels/inch, for X/Y-resolution + 0x49, 0x49, 0x2a, 0x00, // little endian signature + 8, 0, 0, 0, // offset to the unique IFD that follows + // IFD (offset = 8). Entries must be written in increasing tag order. + num_ifd_entries, 0, // Number of entries in the IFD (12 bytes each). + 0x00, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 10: Width (TBD) + 0x01, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 22: Height (TBD) + 0x02, 0x01, 3, 0, bytes_per_px, 0, 0, 0, // 34: BitsPerSample: 8888 + kExtraDataOffset + 0, 0, 0, 0, 0x03, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, + 0, // 46: Compression: none + 0x06, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 58: Photometric: RGB + 0x11, 0x01, 4, 0, 1, 0, 0, 0, // 70: Strips offset: + kHeaderSize, 0, 0, 0, // data follows header + 0x12, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 82: Orientation: topleft + 0x15, 0x01, 3, 0, 1, 0, 0, 0, // 94: SamplesPerPixels + bytes_per_px, 0, 0, 0, 0x16, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, + 0, // 106: Rows per strip (TBD) + 0x17, 0x01, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 118: StripByteCount (TBD) + 0x1a, 0x01, 5, 0, 1, 0, 0, 0, // 130: X-resolution + kExtraDataOffset + 8, 0, 0, 0, 0x1b, 0x01, 5, 0, 1, 0, 0, + 0, // 142: Y-resolution + kExtraDataOffset + 8, 0, 0, 0, 0x1c, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, + 0, // 154: PlanarConfiguration + 0x28, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 166: ResolutionUnit (inch) + 0x52, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 178: ExtraSamples: rgbA + 0, 0, 0, 0, // 190: IFD terminator + // kExtraDataOffset: + 8, 0, 8, 0, 8, 0, 8, 0, // BitsPerSample + 72, 0, 0, 0, 1, 0, 0, 0 // 72 pixels/inch, for X/Y-resolution }; // Fill placeholders in IFD:
diff --git a/ios/chrome/browser/webp_transcode/webp_decoder_unittest.mm b/ios/web/public/image_fetcher/webp_decoder_unittest.mm similarity index 98% rename from ios/chrome/browser/webp_transcode/webp_decoder_unittest.mm rename to ios/web/public/image_fetcher/webp_decoder_unittest.mm index e7b67f7..9efbe75 100644 --- a/ios/chrome/browser/webp_transcode/webp_decoder_unittest.mm +++ b/ios/web/public/image_fetcher/webp_decoder_unittest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ios/chrome/browser/webp_transcode/webp_decoder.h" +#include "ios/web/public/image_fetcher/webp_decoder.h" #import <CoreGraphics/CoreGraphics.h> #import <Foundation/Foundation.h> @@ -59,8 +59,8 @@ NSData* LoadImage(const base::FilePath& filename) { base::FilePath path; PathService::Get(base::DIR_SOURCE_ROOT, &path); - path = path.AppendASCII("ios/chrome/test/data/webp_transcode") - .Append(filename); + path = + path.AppendASCII("ios/web/test/data/webp_transcode").Append(filename); return [NSData dataWithContentsOfFile:base::SysUTF8ToNSString(path.value())]; }
diff --git a/ios/web/public/test/mock_image_data_fetcher.h b/ios/web/public/test/mock_image_data_fetcher.h new file mode 100644 index 0000000..196b68f2 --- /dev/null +++ b/ios/web/public/test/mock_image_data_fetcher.h
@@ -0,0 +1,36 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_WEB_PUBLIC_IMAGE_FETCHER_MOCK_IMAGE_DATA_FETCHER_H_ +#define IOS_WEB_PUBLIC_IMAGE_FETCHER_MOCK_IMAGE_DATA_FETCHER_H_ + +#import "ios/web/public/image_fetcher/image_data_fetcher.h" + +#include "testing/gmock/include/gmock/gmock.h" + +namespace web { + +// Mocks the ImageDataFetcher utility class, which can be used to asynchronously +// retrieve an image from an URL. +class MockImageDataFetcher : public ImageDataFetcher { + public: + explicit MockImageDataFetcher( + const scoped_refptr<base::TaskRunner>& task_runner); + ~MockImageDataFetcher() override; + + MOCK_METHOD4(StartDownload, + void(const GURL& url, + ImageFetchedCallback callback, + const std::string& referrer, + net::URLRequest::ReferrerPolicy referrer_policy)); + MOCK_METHOD2(StartDownload, + void(const GURL& url, ImageFetchedCallback callback)); + MOCK_METHOD1(SetRequestContextGetter, + void(const scoped_refptr<net::URLRequestContextGetter>& + request_context_getter)); +}; + +} // namespace web + +#endif // IOS_WEB_PUBLIC_IMAGE_FETCHER_MOCK_IMAGE_DATA_FETCHER_H_
diff --git a/ios/web/public/test/mock_image_data_fetcher.mm b/ios/web/public/test/mock_image_data_fetcher.mm new file mode 100644 index 0000000..fbdfd57 --- /dev/null +++ b/ios/web/public/test/mock_image_data_fetcher.mm
@@ -0,0 +1,15 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/web/public/test/mock_image_data_fetcher.h" + +namespace web { + +MockImageDataFetcher::MockImageDataFetcher( + const scoped_refptr<base::TaskRunner>& task_runner) + : ImageDataFetcher(task_runner) {} + +MockImageDataFetcher::~MockImageDataFetcher() {} + +} // namespace web
diff --git a/ios/chrome/test/data/webp_transcode/OWNERS b/ios/web/test/data/webp_transcode/OWNERS similarity index 100% rename from ios/chrome/test/data/webp_transcode/OWNERS rename to ios/web/test/data/webp_transcode/OWNERS
diff --git a/ios/chrome/test/data/webp_transcode/test.jpg b/ios/web/test/data/webp_transcode/test.jpg similarity index 100% rename from ios/chrome/test/data/webp_transcode/test.jpg rename to ios/web/test/data/webp_transcode/test.jpg Binary files differ
diff --git a/ios/chrome/test/data/webp_transcode/test.webp b/ios/web/test/data/webp_transcode/test.webp similarity index 100% rename from ios/chrome/test/data/webp_transcode/test.webp rename to ios/web/test/data/webp_transcode/test.webp Binary files differ
diff --git a/ios/chrome/test/data/webp_transcode/test_alpha.png b/ios/web/test/data/webp_transcode/test_alpha.png similarity index 100% rename from ios/chrome/test/data/webp_transcode/test_alpha.png rename to ios/web/test/data/webp_transcode/test_alpha.png Binary files differ
diff --git a/ios/chrome/test/data/webp_transcode/test_alpha.webp b/ios/web/test/data/webp_transcode/test_alpha.webp similarity index 100% rename from ios/chrome/test/data/webp_transcode/test_alpha.webp rename to ios/web/test/data/webp_transcode/test_alpha.webp Binary files differ
diff --git a/ios/chrome/test/data/webp_transcode/test_small.tiff b/ios/web/test/data/webp_transcode/test_small.tiff similarity index 100% rename from ios/chrome/test/data/webp_transcode/test_small.tiff rename to ios/web/test/data/webp_transcode/test_small.tiff Binary files differ
diff --git a/ios/chrome/test/data/webp_transcode/test_small.webp b/ios/web/test/data/webp_transcode/test_small.webp similarity index 100% rename from ios/chrome/test/data/webp_transcode/test_small.webp rename to ios/web/test/data/webp_transcode/test_small.webp Binary files differ
diff --git a/net/log/trace_net_log_observer.cc b/net/log/trace_net_log_observer.cc index 4c7b7dc..bae83a5a 100644 --- a/net/log/trace_net_log_observer.cc +++ b/net/log/trace_net_log_observer.cc
@@ -90,6 +90,10 @@ DCHECK(!net_log_to_watch_); DCHECK(!net_log()); net_log_to_watch_ = netlog; + // Tracing can start before the observer is even created, for instance for + // startup tracing. + if (base::trace_event::TraceLog::GetInstance()->IsEnabled()) + OnTraceLogEnabled(); base::trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this); }
diff --git a/net/log/trace_net_log_observer_unittest.cc b/net/log/trace_net_log_observer_unittest.cc index 60c54ee0..2cd4f01 100644 --- a/net/log/trace_net_log_observer_unittest.cc +++ b/net/log/trace_net_log_observer_unittest.cc
@@ -319,6 +319,31 @@ TestNetLogEntry::List entries; net_log()->GetEntries(&entries); EXPECT_EQ(3u, entries.size()); + EXPECT_EQ(1u, trace_events()->GetSize()); +} + +TEST_F(TraceNetLogObserverTest, + CreateObserverAfterTracingStartsDisabledCategory) { + set_trace_net_log_observer(nullptr); + + std::string disabled_netlog_category = + std::string("-") + kNetLogTracingCategory; + TraceLog::GetInstance()->SetEnabled( + base::trace_event::TraceConfig(disabled_netlog_category, ""), + TraceLog::RECORDING_MODE); + + set_trace_net_log_observer(new TraceNetLogObserver()); + trace_net_log_observer()->WatchForTraceStart(net_log()); + net_log()->AddGlobalEntry(NetLogEventType::CANCELLED); + trace_net_log_observer()->StopWatchForTraceStart(); + net_log()->AddGlobalEntry(NetLogEventType::REQUEST_ALIVE); + net_log()->AddGlobalEntry(NetLogEventType::URL_REQUEST_START_JOB); + + EndTraceAndFlush(); + + TestNetLogEntry::List entries; + net_log()->GetEntries(&entries); + EXPECT_EQ(3u, entries.size()); EXPECT_EQ(0u, trace_events()->GetSize()); }
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 06a773a..cc4bd23 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1183,24 +1183,6 @@ ] } ], - "NonValidatingReloadOnNormalReload": [ - { - "platforms": [ - "android", - "linux", - "mac", - "win" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "NonValidatingReloadOnNormalReload" - ] - } - ] - } - ], "OfferUploadCreditCards": [ { "platforms": [
diff --git a/third_party/WebKit/Source/bindings/IDLExtendedAttributes.md b/third_party/WebKit/Source/bindings/IDLExtendedAttributes.md index aa42702..ee8567e 100644 --- a/third_party/WebKit/Source/bindings/IDLExtendedAttributes.md +++ b/third_party/WebKit/Source/bindings/IDLExtendedAttributes.md
@@ -550,21 +550,18 @@ Summary: `[CallWith]` indicates that the bindings code calls the Blink implementation with additional information. -Each value changes the signature of the Blink methods by adding an additional parameter to the head of the parameter list, such as `&state` for `[CallWith=ScriptState]`. - -Multiple values can be specified e.g. `[CallWith=ScriptState|ScriptArguments]`. The order of the values in the IDL file doesn't matter: the generated parameter list is always in a fixed order (specifically `&state`, `scriptContext`, `scriptArguments.release()`, if present, corresponding to `ScriptState`, `ScriptExecutionContext`, `ScriptArguments`, respectively). +Each value changes the signature of the Blink methods by adding an additional parameter to the head of the parameter list, such as `ScriptState*` for `[CallWith=ScriptState]`. There are also three rarely used values: `CurrentWindow`, `EnteredWindow`, `ThisValue`. `[SetterCallWith]` applies to attributes, and only affects the signature of the setter; this is only used in Location.idl, with `CurrentWindow&EnteredWindow`. -Syntax: -`CallWith=ScriptState|ScriptExecutionContext|ScriptArguments|CurrentWindow|EnteredWindow|ThisValue` - #### [CallWith=ScriptState] _(m, a*)_ -`[CallWith=ScriptState]` is used in a number of places for methods. -`[CallWith=ScriptState]` _can_ be used for attributes, but is not used in real IDL files. +`[CallWith=ScriptState]` is used in a number of places for methods. +ScriptState holds all information about script execution. +You can retrieve Frame, ExcecutionContext, v8::Context, v8::Isolate etc +from ScriptState. IDL example: @@ -582,7 +579,18 @@ String Example::func(ScriptState* state, bool a, bool b); ``` -#### [CallWith=ExecutionContext] _(m,a)_ +Be careful when you use `[CallWith=ScriptState]`. +You should not store the passed-in ScriptState on a DOM object (using RefPtr<ScriptState>). +This is because if the stored ScriptState is used by some method called by a different +world (note that the DOM object is shared among multiple worlds), it leaks the ScriptState +to the world. ScriptState must be carefully maintained in a way that doesn't leak +to another world. + +#### [CallWith=ExecutionContext] _(m,a)_ _deprecated_ + +`[CallWith=ExecutionContext]` is a less convenient version of `[CallWith=ScriptState]` +because you can just retrieve ExecutionContext from ScriptState. +Use `[CallWith=ScriptState]` instead. IDL example: @@ -600,24 +608,6 @@ String Example::func(ExecutionContext* context, bool a, bool b); ``` -You can retrieve the document and frame from a `ExecutionContext*`. - -#### [CallWith=ScriptArguments] _(m)_ - -IDL example: - -```webidl -interface Example { - [CallWith=ScriptState] DOMString func(boolean a, boolean b); -}; -``` - -C++ Blink function signature: - -```c++ -String Example::func(ScriptArguments* arguments, bool a, bool b); -``` - _(rare CallWith values)_ #### [CallWith=CurrentWindow&EnteredWindow] _(m, a)_ @@ -655,7 +645,7 @@ ```webidl [ Constructor(float x, float y, DOMString str), - ConstructorCallWith=Document|ExecutionContext, + ConstructorCallWith=ExecutionContext, ] interface XXX { ... @@ -669,13 +659,18 @@ *** ```c++ -PassRefPtr<XXX> XXX::create(ScriptExecutionContext* context, ScriptState* state, float x, float y, String str) +PassRefPtr<XXX> XXX::create(ExecutionContext* context, float x, float y, String str) { ...; } ``` -You can retrieve document or frame from ScriptExecutionContext. +Be careful when you use `[ConstructorCallWith=ScriptState]`. +You should not store the passed-in ScriptState on a DOM object (using RefPtr<ScriptState>). +This is because if the stored ScriptState is used by some method called by a different +world (note that the DOM object is shared among multiple worlds), it leaks the ScriptState +to the world. ScriptState must be carefully maintained in a way that doesn't leak +to another world. ### [Custom] _(i, m, s, a, f)_ @@ -827,7 +822,7 @@ } ``` -#### [Custom=LegacyCallAsFunction] _(i) _deprecated__ +#### [Custom=LegacyCallAsFunction] _(i) _deprecated_ Summary: `[Custom=LegacyCallAsFunction]` allows you to write custom bindings for call(...) of a given interface. @@ -1384,7 +1379,7 @@ } // Called by generated binding code if no value cached or isAttributeDirty() returns true -ScriptValue Object::attribute(ScriptExecutionContext* context) +ScriptValue Object::attribute(ExecutionContext* context) { m_attributeDirty = false; return convertDataToScriptValue(m_data);
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index ed97200c..fca88932 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -5738,11 +5738,6 @@ m_taskRunner->postTask(location, std::move(task), taskNameForInstrumentation); } -void Document::postInspectorTask(const WebTraceLocation& location, - std::unique_ptr<ExecutionContextTask> task) { - m_taskRunner->postInspectorTask(location, std::move(task)); -} - void Document::tasksWereSuspended() { scriptRunner()->suspend();
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h index 907fb50..38cbd58e 100644 --- a/third_party/WebKit/Source/core/dom/Document.h +++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -996,8 +996,6 @@ std::unique_ptr<ExecutionContextTask>, const String& taskNameForInstrumentation = emptyString()) override; // Executes the task on context's thread asynchronously. - void postInspectorTask(const WebTraceLocation&, - std::unique_ptr<ExecutionContextTask>); void tasksWereSuspended() final; void tasksWereResumed() final;
diff --git a/third_party/WebKit/Source/core/dom/MainThreadTaskRunner.cpp b/third_party/WebKit/Source/core/dom/MainThreadTaskRunner.cpp index e8e1ac08..91ec2dc 100644 --- a/third_party/WebKit/Source/core/dom/MainThreadTaskRunner.cpp +++ b/third_party/WebKit/Source/core/dom/MainThreadTaskRunner.cpp
@@ -44,17 +44,6 @@ MainThreadTaskRunner::~MainThreadTaskRunner() {} -void MainThreadTaskRunner::postTaskInternal( - const WebTraceLocation& location, - std::unique_ptr<ExecutionContextTask> task, - bool isInspectorTask, - bool instrumenting) { - Platform::current()->mainThread()->getWebTaskRunner()->postTask( - location, - crossThreadBind(&MainThreadTaskRunner::perform, m_weakPtr, - passed(std::move(task)), isInspectorTask, instrumenting)); -} - void MainThreadTaskRunner::postTask(const WebTraceLocation& location, std::unique_ptr<ExecutionContextTask> task, const String& taskNameForInstrumentation) { @@ -62,17 +51,12 @@ InspectorInstrumentation::asyncTaskScheduled( m_context, taskNameForInstrumentation, task.get()); const bool instrumenting = !taskNameForInstrumentation.isEmpty(); - postTaskInternal(location, std::move(task), false, instrumenting); -} - -void MainThreadTaskRunner::postInspectorTask( - const WebTraceLocation& location, - std::unique_ptr<ExecutionContextTask> task) { - postTaskInternal(location, std::move(task), true, false); + Platform::current()->mainThread()->getWebTaskRunner()->postTask( + location, crossThreadBind(&MainThreadTaskRunner::perform, m_weakPtr, + passed(std::move(task)), instrumenting)); } void MainThreadTaskRunner::perform(std::unique_ptr<ExecutionContextTask> task, - bool isInspectorTask, bool instrumenting) { // If the owner m_context is about to be swept then it // is no longer safe to access. @@ -80,7 +64,7 @@ return; InspectorInstrumentation::AsyncTask asyncTask(m_context, task.get(), - !isInspectorTask); + instrumenting); task->performTask(m_context); }
diff --git a/third_party/WebKit/Source/core/dom/MainThreadTaskRunner.h b/third_party/WebKit/Source/core/dom/MainThreadTaskRunner.h index 8be7056..5b8a2f6 100644 --- a/third_party/WebKit/Source/core/dom/MainThreadTaskRunner.h +++ b/third_party/WebKit/Source/core/dom/MainThreadTaskRunner.h
@@ -58,20 +58,12 @@ std::unique_ptr<ExecutionContextTask>, const String& taskNameForInstrumentation = emptyString()); - void postInspectorTask(const WebTraceLocation&, - std::unique_ptr<ExecutionContextTask>); void perform(std::unique_ptr<ExecutionContextTask>, - bool isInspectorTask, bool instrumenting); private: explicit MainThreadTaskRunner(ExecutionContext*); - void postTaskInternal(const WebTraceLocation&, - std::unique_ptr<ExecutionContextTask>, - bool isInspectorTask, - bool instrumenting); - // Untraced back reference to the owner Document; // this object has identical lifetime to it. UntracedMember<ExecutionContext> m_context;
diff --git a/third_party/WebKit/Source/core/events/PromiseRejectionEvent.cpp b/third_party/WebKit/Source/core/events/PromiseRejectionEvent.cpp index d923902..7653df1f 100644 --- a/third_party/WebKit/Source/core/events/PromiseRejectionEvent.cpp +++ b/third_party/WebKit/Source/core/events/PromiseRejectionEvent.cpp
@@ -13,7 +13,7 @@ const AtomicString& type, const PromiseRejectionEventInit& initializer) : Event(type, initializer), - m_scriptState(state), + m_world(state->world()), m_promise(this), m_reason(this) { ThreadState::current()->registerPreFinalizer(this); @@ -33,28 +33,23 @@ // (and touch the ScopedPersistents) after Oilpan starts lazy sweeping. m_promise.clear(); m_reason.clear(); - m_scriptState.clear(); + m_world.clear(); } -ScriptPromise PromiseRejectionEvent::promise(ScriptState* state) const { +ScriptPromise PromiseRejectionEvent::promise(ScriptState* scriptState) const { // Return null when the promise is accessed by a different world than the // world that created the promise. - if (!m_scriptState || !m_scriptState->contextIsValid() || - m_scriptState->world().worldId() != state->world().worldId()) + if (!canBeDispatchedInWorld(scriptState->world())) return ScriptPromise(); - return ScriptPromise(m_scriptState.get(), - m_promise.newLocal(m_scriptState->isolate())); + return ScriptPromise(scriptState, m_promise.newLocal(scriptState->isolate())); } -ScriptValue PromiseRejectionEvent::reason(ScriptState* state) const { +ScriptValue PromiseRejectionEvent::reason(ScriptState* scriptState) const { // Return null when the value is accessed by a different world than the world // that created the value. - if (m_reason.isEmpty() || !m_scriptState || - !m_scriptState->contextIsValid() || - m_scriptState->world().worldId() != state->world().worldId()) - return ScriptValue(state, v8::Undefined(state->isolate())); - return ScriptValue(m_scriptState.get(), - m_reason.newLocal(m_scriptState->isolate())); + if (m_reason.isEmpty() || !canBeDispatchedInWorld(scriptState->world())) + return ScriptValue(scriptState, v8::Undefined(scriptState->isolate())); + return ScriptValue(scriptState, m_reason.newLocal(scriptState->isolate())); } void PromiseRejectionEvent::setWrapperReference( @@ -76,8 +71,7 @@ bool PromiseRejectionEvent::canBeDispatchedInWorld( const DOMWrapperWorld& world) const { - return m_scriptState && m_scriptState->contextIsValid() && - m_scriptState->world().worldId() == world.worldId(); + return m_world && m_world->worldId() == world.worldId(); } DEFINE_TRACE(PromiseRejectionEvent) {
diff --git a/third_party/WebKit/Source/core/events/PromiseRejectionEvent.h b/third_party/WebKit/Source/core/events/PromiseRejectionEvent.h index 48833ee..0ea862c 100644 --- a/third_party/WebKit/Source/core/events/PromiseRejectionEvent.h +++ b/third_party/WebKit/Source/core/events/PromiseRejectionEvent.h
@@ -50,7 +50,7 @@ ~PromiseRejectionEvent() override; void dispose(); - RefPtr<ScriptState> m_scriptState; + RefPtr<DOMWrapperWorld> m_world; TraceWrapperV8Reference<v8::Value> m_promise; TraceWrapperV8Reference<v8::Value> m_reason; };
diff --git a/third_party/WebKit/Source/core/fetch/BUILD.gn b/third_party/WebKit/Source/core/fetch/BUILD.gn index 44f33a0..87979fa 100644 --- a/third_party/WebKit/Source/core/fetch/BUILD.gn +++ b/third_party/WebKit/Source/core/fetch/BUILD.gn
@@ -42,8 +42,6 @@ "ResourceLoaderOptions.h", "ResourceLoadingLog.h", "SubstituteData.h", - "TextResource.cpp", - "TextResource.h", "UniqueIdentifier.cpp", "UniqueIdentifier.h", ]
diff --git a/third_party/WebKit/Source/core/fetch/DEPS b/third_party/WebKit/Source/core/fetch/DEPS index 84251e0f..f2a592e7 100644 --- a/third_party/WebKit/Source/core/fetch/DEPS +++ b/third_party/WebKit/Source/core/fetch/DEPS
@@ -6,6 +6,5 @@ # core/fetch/ shouldn't depend on anything else in core/, # but has not been fully isolated yet. # Do not add to this list. - "!core/html/parser/TextResourceDecoder.h", "!core/svg/graphics/SVGImage.h", ]
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp index 38f3f95d..cb7b2ccc 100644 --- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp +++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
@@ -1272,14 +1272,6 @@ encodedDataLength); } -void ResourceFetcher::acceptDataFromThreadedReceiver(unsigned long identifier, - const char* data, - int dataLength, - int encodedDataLength) { - context().dispatchDidReceiveData(identifier, data, dataLength, - encodedDataLength); -} - void ResourceFetcher::moveResourceLoaderToNonBlocking(ResourceLoader* loader) { DCHECK(loader); // TODO(yoav): Convert CHECK to DCHECK if no crash reports come in.
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.h b/third_party/WebKit/Source/core/fetch/ResourceFetcher.h index 10991d5..4f67343 100644 --- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.h +++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.h
@@ -137,11 +137,6 @@ bool defersLoading() const; bool isControlledByServiceWorker() const; - void acceptDataFromThreadedReceiver(unsigned long identifier, - const char* data, - int dataLength, - int encodedDataLength); - enum ResourceLoadStartType { ResourceLoadingFromNetwork, ResourceLoadingFromCache
diff --git a/third_party/WebKit/Source/core/frame/csp/CSPSource.h b/third_party/WebKit/Source/core/frame/csp/CSPSource.h index b599e78..3a4739cf 100644 --- a/third_party/WebKit/Source/core/frame/csp/CSPSource.h +++ b/third_party/WebKit/Source/core/frame/csp/CSPSource.h
@@ -57,6 +57,7 @@ GetIntersectCSPSourcesSchemes); FRIEND_TEST_ALL_PREFIXES(CSPDirectiveListTest, GetSourceVector); FRIEND_TEST_ALL_PREFIXES(CSPDirectiveListTest, OperativeDirectiveGivenType); + FRIEND_TEST_ALL_PREFIXES(SourceListDirectiveTest, SubsumesWithSelf); bool schemeMatches(const String&) const; bool hostMatches(const String&) const;
diff --git a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.h b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.h index ad42feb..3336811 100644 --- a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.h +++ b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.h
@@ -341,6 +341,8 @@ bool shouldSendCSPHeader(Resource::Type) const; + CSPSource* getSelfSource() const { return m_selfSource; } + static bool shouldBypassMainWorld(const ExecutionContext*); static bool isNonceableElement(const Element*);
diff --git a/third_party/WebKit/Source/core/frame/csp/SourceListDirective.cpp b/third_party/WebKit/Source/core/frame/csp/SourceListDirective.cpp index ef1173e..223967d 100644 --- a/third_party/WebKit/Source/core/frame/csp/SourceListDirective.cpp +++ b/third_party/WebKit/Source/core/frame/csp/SourceListDirective.cpp
@@ -585,12 +585,17 @@ if (!m_list.size() || !other.size()) return !m_list.size(); - HeapVector<Member<CSPSource>> normalizedA = other[0]->m_list; - for (size_t i = 1; i < other.size(); i++) { - normalizedA = other[i]->getIntersectCSPSources(normalizedA); - } + HeapVector<Member<CSPSource>> normalizedA = m_list; + if (m_allowSelf && other[0]->m_policy->getSelfSource()) + normalizedA.append(other[0]->m_policy->getSelfSource()); - return CSPSource::firstSubsumesSecond(m_list, normalizedA); + HeapVector<Member<CSPSource>> normalizedB = other[0]->m_list; + if (other[0]->m_allowSelf && other[0]->m_policy->getSelfSource()) + normalizedB.append(other[0]->m_policy->getSelfSource()); + for (size_t i = 1; i < other.size(); i++) + normalizedB = other[i]->getIntersectCSPSources(normalizedB); + + return CSPSource::firstSubsumesSecond(normalizedA, normalizedB); } HashMap<String, CSPSource*> SourceListDirective::getIntersectSchemesOnly( @@ -630,7 +635,10 @@ } } - for (const auto& sourceA : m_list) { + HeapVector<Member<CSPSource>> thisVector = m_list; + if (m_allowSelf) + thisVector.append(m_policy->getSelfSource()); + for (const auto& sourceA : thisVector) { if (schemesMap.contains(sourceA->getScheme())) continue;
diff --git a/third_party/WebKit/Source/core/frame/csp/SourceListDirectiveTest.cpp b/third_party/WebKit/Source/core/frame/csp/SourceListDirectiveTest.cpp index fabecda3..acfecf8 100644 --- a/third_party/WebKit/Source/core/frame/csp/SourceListDirectiveTest.cpp +++ b/third_party/WebKit/Source/core/frame/csp/SourceListDirectiveTest.cpp
@@ -37,6 +37,16 @@ csp->bindToExecutionContext(document.get()); } + ContentSecurityPolicy* SetUpWithOrigin(const String& origin) { + KURL url(ParsedURLString, origin); + RefPtr<SecurityOrigin> secureOrigin(SecurityOrigin::create(url)); + Document* document = Document::create(); + document->setSecurityOrigin(secureOrigin); + ContentSecurityPolicy* csp = ContentSecurityPolicy::create(); + csp->bindToExecutionContext(document); + return csp; + } + bool equalSources(const Source& a, const Source& b) { return a.scheme == b.scheme && a.host == b.host && a.port == b.port && a.path == b.path && a.hostWildcard == b.hostWildcard && @@ -437,4 +447,121 @@ } } +TEST_F(SourceListDirectiveTest, SubsumesWithSelf) { + SourceListDirective A("script-src", + "http://example1.com/foo/ http://*.example2.com/bar/ " + "http://*.example3.com:*/bar/ 'self'", + csp.get()); + + struct TestCase { + std::vector<const char*> sourcesB; + const char* originB; + bool expected; + } cases[] = { + // "https://example.test/" is a secure origin for both A and B. + {{"'self'"}, "https://example.test/", true}, + {{"'self' 'self' 'self'"}, "https://example.test/", true}, + {{"'self'", "'self'", "'self'"}, "https://example.test/", true}, + {{"'self'", "'self'", "https://*.example.test/"}, + "https://example.test/", + true}, + {{"'self'", "'self'", "https://*.example.test/bar/"}, + "https://example.test/", + true}, + {{"'self' https://another.test/bar", "'self' http://*.example.test/bar", + "https://*.example.test/bar/"}, + "https://example.test/", + true}, + {{"http://example1.com/foo/ 'self'"}, "https://example.test/", true}, + {{"http://example1.com/foo/ https://example.test/"}, + "https://example.test/", + true}, + {{"http://example1.com/foo/ http://*.example2.com/bar/"}, + "https://example.test/", + true}, + {{"http://example1.com/foo/ http://*.example2.com/bar/ " + "http://*.example3.com:*/bar/ https://example.test/"}, + "https://example.test/", + true}, + {{"http://example1.com/foo/ http://*.example2.com/bar/ " + "http://*.example3.com:*/bar/ 'self'"}, + "https://example.test/", + true}, + {{"'self'", "'self'", "https://example.test/"}, + "https://example.test/", + true}, + {{"'self'", "https://example.test/folder/"}, + "https://example.test/", + true}, + {{"'self'", "http://example.test/folder/"}, + "https://example.test/", + true}, + {{"'self' https://example.com/", "https://example.com/"}, + "https://example.test/", + false}, + {{"http://example1.com/foo/ http://*.example2.com/bar/", + "http://example1.com/foo/ http://*.example2.com/bar/ 'self'"}, + "https://example.test/", + true}, + {{"http://*.example1.com/foo/", "http://*.example1.com/foo/ 'self'"}, + "https://example.test/", + false}, + {{"https://*.example.test/", "https://*.example.test/ 'self'"}, + "https://example.test/", + false}, + {{"http://example.test/"}, "https://example.test/", false}, + {{"https://example.test/"}, "https://example.test/", true}, + // Origins of A and B do not match. + {{"https://example.test/"}, "https://other-origin.test/", false}, + {{"'self'"}, "https://other-origin.test/", true}, + {{"http://example1.com/foo/ http://*.example2.com/bar/ " + "http://*.example3.com:*/bar/ 'self'"}, + "https://other-origin.test/", + true}, + {{"http://example1.com/foo/ http://*.example2.com/bar/ " + "http://*.example3.com:*/bar/ https://other-origin.test/"}, + "https://other-origin.test/", + true}, + {{"http://example1.com/foo/ 'self'"}, "https://other-origin.test/", true}, + {{"'self'", "https://example.test/"}, "https://other-origin.test/", true}, + {{"'self' https://example.test/", "https://example.test/"}, + "https://other-origin.test/", + false}, + {{"https://example.test/", "http://example.test/"}, + "https://other-origin.test/", + false}, + {{"'self'", "http://other-origin.test/"}, + "https://other-origin.test/", + true}, + {{"'self'", "https://non-example.test/"}, + "https://other-origin.test/", + true}, + // B's origin matches one of sources in the source list of A. + {{"'self'", "http://*.example1.com/foo/"}, "http://example1.com/", true}, + {{"http://*.example2.com/bar/", "'self'"}, + "http://example2.com/bar/", + true}, + {{"'self' http://*.example1.com/foo/", "http://*.example1.com/foo/"}, + "http://example1.com/", + false}, + {{"http://*.example2.com/bar/ http://example1.com/", + "'self' http://example1.com/"}, + "http://example2.com/bar/", + false}, + }; + + for (const auto& test : cases) { + ContentSecurityPolicy* cspB = SetUpWithOrigin(String(test.originB)); + + HeapVector<Member<SourceListDirective>> vectorB; + for (const auto& sources : test.sourcesB) { + SourceListDirective* member = + new SourceListDirective("script-src", sources, cspB); + vectorB.append(member); + } + + EXPECT_EQ(test.expected, A.subsumes(vectorB)); + } +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp index 4eff1b4c..f5cad31 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
@@ -397,6 +397,10 @@ void HTMLDocumentParser::validateSpeculations( std::unique_ptr<TokenizedChunk> chunk) { ASSERT(chunk); + // TODO(kouhei): We should simplify codepath here by disallowing + // validateSpeculations + // while isWaitingForScripts, and m_lastChunkBeforeScript can simply be + // pushed to m_speculations. if (isWaitingForScripts()) { // We're waiting on a network script, just save the chunk, we'll get a // second validateSpeculations call after the script completes. This call @@ -1056,14 +1060,18 @@ ASSERT(!isWaitingForScripts()); if (m_haveBackgroundParser) { - validateSpeculations(std::move(m_lastChunkBeforeScript)); - ASSERT(!m_lastChunkBeforeScript); - pumpPendingSpeculations(); + if (m_lastChunkBeforeScript) { + validateSpeculations(std::move(m_lastChunkBeforeScript)); + DCHECK(!m_lastChunkBeforeScript); + pumpPendingSpeculations(); + } return; } m_insertionPreloadScanner.reset(); - pumpTokenizerIfPossible(); + if (m_tokenizer) { + pumpTokenizerIfPossible(); + } endIfDelayed(); } @@ -1092,14 +1100,11 @@ } void HTMLDocumentParser::executeScriptsWaitingForResources() { + DCHECK(document()->isScriptExecutionReady()); + // Document only calls this when the Document owns the DocumentParser so this // will not be called in the DocumentFragment case. - ASSERT(m_scriptRunner); - // Ignore calls unless we have a script blocking the parser waiting on a - // stylesheet load. Otherwise we are currently parsing and this is a - // re-entrant call from encountering a </ style> tag. - if (!m_scriptRunner->hasScriptsWaitingForResources()) - return; + DCHECK(m_scriptRunner); m_scriptRunner->executeScriptsWaitingForResources(); if (!isWaitingForScripts()) resumeParsingAfterScriptExecution();
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp b/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp index 1f130d3c..899dd1d 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp
@@ -154,8 +154,7 @@ : m_reentryPermit(reentryPermit), m_document(document), m_host(host), - m_parserBlockingScript(PendingScript::create(nullptr, nullptr)), - m_hasScriptsWaitingForResources(false) { + m_parserBlockingScript(PendingScript::create(nullptr, nullptr)) { ASSERT(m_host); ThreadState::current()->registerPreFinalizer(this); } @@ -181,18 +180,17 @@ // detached. } -bool HTMLScriptRunner::isPendingScriptReady(const PendingScript* script) { - m_hasScriptsWaitingForResources = !m_document->isScriptExecutionReady(); - if (m_hasScriptsWaitingForResources) +bool HTMLScriptRunner::isPendingScriptReady() { + if (!m_document->isScriptExecutionReady()) return false; - return script->isReady(); + return m_parserBlockingScript->isReady(); } void HTMLScriptRunner::executeParsingBlockingScript() { - ASSERT(m_document); - ASSERT(!isExecutingScript()); - ASSERT(m_document->isScriptExecutionReady()); - ASSERT(isPendingScriptReady(m_parserBlockingScript.get())); + DCHECK(m_document); + DCHECK(!isExecutingScript()); + DCHECK(m_document->isScriptExecutionReady()); + DCHECK(isPendingScriptReady()); InsertionPointRecord insertionPointRecord(m_host->inputStream()); executePendingScriptAndDispatchEvent(m_parserBlockingScript.get(), @@ -215,10 +213,9 @@ if (!isExecutingScript()) { Microtask::performCheckpoint(V8PerIsolateData::mainThreadIsolate()); if (pendingScriptType == ScriptStreamer::ParsingBlocking) { - m_hasScriptsWaitingForResources = !m_document->isScriptExecutionReady(); // The parser cannot be unblocked as a microtask requested another // resource - if (m_hasScriptsWaitingForResources) + if (!m_document->isScriptExecutionReady()) return; } } @@ -373,8 +370,7 @@ } void HTMLScriptRunner::executeParsingBlockingScripts() { - while (hasParserBlockingScript() && - isPendingScriptReady(m_parserBlockingScript.get())) + while (hasParserBlockingScript() && isPendingScriptReady()) executeParsingBlockingScript(); } @@ -390,9 +386,6 @@ void HTMLScriptRunner::executeScriptsWaitingForResources() { TRACE_EVENT0("blink", "HTMLScriptRunner::executeScriptsWaitingForResources"); ASSERT(m_document); - // Callers should check hasScriptsWaitingForResources() before calling - // to prevent parser or script re-entry during </style> parsing. - ASSERT(hasScriptsWaitingForResources()); ASSERT(!isExecutingScript()); ASSERT(m_document->isScriptExecutionReady()); executeParsingBlockingScripts();
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.h b/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.h index 2c251c8f..938c9ee 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.h +++ b/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.h
@@ -64,9 +64,6 @@ const TextPosition& scriptStartPosition); void executeScriptsWaitingForLoad(Resource*); - bool hasScriptsWaitingForResources() const { - return m_hasScriptsWaitingForResources; - } void executeScriptsWaitingForResources(); bool executeScriptsWaitingForParsing(); @@ -95,7 +92,7 @@ void runScript(Element*, const TextPosition& scriptStartPosition); - bool isPendingScriptReady(const PendingScript*); + bool isPendingScriptReady(); void stopWatchingResourceForLoad(Resource*); @@ -107,12 +104,6 @@ Member<PendingScript> m_parserBlockingScript; // http://www.whatwg.org/specs/web-apps/current-work/#list-of-scripts-that-will-execute-when-the-document-has-finished-parsing HeapDeque<Member<PendingScript>> m_scriptsToExecuteAfterParsing; - - // We only want stylesheet loads to trigger script execution if script - // execution is currently stopped due to stylesheet loads, otherwise we'd - // cause nested script execution when parsing <style> tags since </style> - // tags can cause Document to call executeScriptsWaitingForResources. - bool m_hasScriptsWaitingForResources; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.cpp index edf1862..024c9cd 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.cpp
@@ -74,6 +74,7 @@ } void HTMLViewSourceParser::finish() { + flush(); if (!m_input.haveSeenEndOfFile()) m_input.markEndOfFile();
diff --git a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp index 861a88d..a91810f 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
@@ -447,13 +447,9 @@ optionalScriptToEvaluateOnLoad.fromMaybe(""); m_v8Session->setSkipAllPauses(true); m_reloading = true; - FrameLoadType reloadType = FrameLoadTypeReload; - if (optionalBypassCache.fromMaybe(false)) - reloadType = FrameLoadTypeReloadBypassingCache; - else if (RuntimeEnabledFeatures:: - reloadwithoutSubResourceCacheRevalidationEnabled()) - reloadType = FrameLoadTypeReloadMainResource; - m_inspectedFrames->root()->reload(reloadType, + m_inspectedFrames->root()->reload(optionalBypassCache.fromMaybe(false) + ? FrameLoadTypeReloadBypassingCache + : FrameLoadTypeReloadMainResource, ClientRedirectPolicy::NotClientRedirect); return Response::OK(); }
diff --git a/third_party/WebKit/Source/core/loader/BUILD.gn b/third_party/WebKit/Source/core/loader/BUILD.gn index e388b3b..33c258a 100644 --- a/third_party/WebKit/Source/core/loader/BUILD.gn +++ b/third_party/WebKit/Source/core/loader/BUILD.gn
@@ -72,6 +72,8 @@ "resource/ScriptResource.h", "resource/StyleSheetResource.h", "resource/StyleSheetResourceClient.h", + "resource/TextResource.cpp", + "resource/TextResource.h", "resource/XSLStyleSheetResource.cpp", "resource/XSLStyleSheetResource.h", ]
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.h b/third_party/WebKit/Source/core/loader/DocumentLoader.h index 21af6601..fd1ebf4 100644 --- a/third_party/WebKit/Source/core/loader/DocumentLoader.h +++ b/third_party/WebKit/Source/core/loader/DocumentLoader.h
@@ -139,9 +139,6 @@ void startLoadingMainResource(); - void acceptDataFromThreadedReceiver(const char* data, - int dataLength, - int encodedDataLength); DocumentLoadTiming& timing() { return m_documentLoadTiming; } const DocumentLoadTiming& timing() const { return m_documentLoadTiming; }
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp index 59426dd81..29d7a9eb 100644 --- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp +++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -121,10 +121,6 @@ } static bool needsHistoryItemRestore(FrameLoadType type) { - if (!RuntimeEnabledFeatures:: - reloadwithoutSubResourceCacheRevalidationEnabled() && - type == FrameLoadTypeReloadMainResource) - return false; // TODO(toyoshim): Shall we return true for FrameLoadTypeInitialHistoryLoad // too? return type == FrameLoadTypeBackForward || isReloadLoadType(type);
diff --git a/third_party/WebKit/Source/core/loader/resource/DocumentResource.h b/third_party/WebKit/Source/core/loader/resource/DocumentResource.h index 0340f0b..5019a12 100644 --- a/third_party/WebKit/Source/core/loader/resource/DocumentResource.h +++ b/third_party/WebKit/Source/core/loader/resource/DocumentResource.h
@@ -25,8 +25,8 @@ #include "core/fetch/Resource.h" #include "core/fetch/ResourceClient.h" -#include "core/fetch/TextResource.h" #include "core/html/parser/TextResourceDecoder.h" +#include "core/loader/resource/TextResource.h" #include "platform/heap/Handle.h" #include <memory>
diff --git a/third_party/WebKit/Source/core/loader/resource/ScriptResource.h b/third_party/WebKit/Source/core/loader/resource/ScriptResource.h index b0dced7..ebf3d3a6 100644 --- a/third_party/WebKit/Source/core/loader/resource/ScriptResource.h +++ b/third_party/WebKit/Source/core/loader/resource/ScriptResource.h
@@ -29,7 +29,7 @@ #include "core/CoreExport.h" #include "core/fetch/IntegrityMetadata.h" #include "core/fetch/ResourceClient.h" -#include "core/fetch/TextResource.h" +#include "core/loader/resource/TextResource.h" namespace blink {
diff --git a/third_party/WebKit/Source/core/loader/resource/StyleSheetResource.h b/third_party/WebKit/Source/core/loader/resource/StyleSheetResource.h index 4ffa8f226..5953a52 100644 --- a/third_party/WebKit/Source/core/loader/resource/StyleSheetResource.h +++ b/third_party/WebKit/Source/core/loader/resource/StyleSheetResource.h
@@ -32,7 +32,7 @@ #define StyleSheetResource_h #include "core/CoreExport.h" -#include "core/fetch/TextResource.h" +#include "core/loader/resource/TextResource.h" namespace blink {
diff --git a/third_party/WebKit/Source/core/fetch/TextResource.cpp b/third_party/WebKit/Source/core/loader/resource/TextResource.cpp similarity index 96% rename from third_party/WebKit/Source/core/fetch/TextResource.cpp rename to third_party/WebKit/Source/core/loader/resource/TextResource.cpp index bcfbfc8c..f734340 100644 --- a/third_party/WebKit/Source/core/fetch/TextResource.cpp +++ b/third_party/WebKit/Source/core/loader/resource/TextResource.cpp
@@ -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 "core/fetch/TextResource.h" +#include "core/loader/resource/TextResource.h" #include "core/html/parser/TextResourceDecoder.h" #include "platform/SharedBuffer.h"
diff --git a/third_party/WebKit/Source/core/fetch/TextResource.h b/third_party/WebKit/Source/core/loader/resource/TextResource.h similarity index 100% rename from third_party/WebKit/Source/core/fetch/TextResource.h rename to third_party/WebKit/Source/core/loader/resource/TextResource.h
diff --git a/third_party/WebKit/Source/core/testing/Internals.idl b/third_party/WebKit/Source/core/testing/Internals.idl index 711e5e4..2c4bf04 100644 --- a/third_party/WebKit/Source/core/testing/Internals.idl +++ b/third_party/WebKit/Source/core/testing/Internals.idl
@@ -26,7 +26,6 @@ [ DoNotCheckConstants, - ConstructorCallWith=ScriptState, ] interface Internals { DOMString address(Node node);
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.cpp b/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.cpp index 615bb9a..bc60b0f 100644 --- a/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.cpp +++ b/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.cpp
@@ -140,16 +140,15 @@ void InProcessWorkerObjectProxy::postMessageToPageInspector( const String& message) { - ExecutionContext* context = getExecutionContext(); - if (context->isDocument()) { - // TODO(hiroshige): consider using getParentFrameTaskRunners() here - // too. - toDocument(context)->postInspectorTask( - BLINK_FROM_HERE, - createCrossThreadTask( - &InProcessWorkerMessagingProxy::postMessageToPageInspector, - m_messagingProxyWeakPtr, message)); - } + DCHECK(getExecutionContext()->isDocument()); + // The TaskType of Inspector tasks need to be Unthrottled because they need to + // run even on a suspended page. + getParentFrameTaskRunners() + ->get(TaskType::Unthrottled) + ->postTask(BLINK_FROM_HERE, + crossThreadBind( + &InProcessWorkerMessagingProxy::postMessageToPageInspector, + m_messagingProxyWeakPtr, message)); } ParentFrameTaskRunners*
diff --git a/third_party/WebKit/Source/core/workers/ParentFrameTaskRunners.cpp b/third_party/WebKit/Source/core/workers/ParentFrameTaskRunners.cpp index f6bfe61..f3099795 100644 --- a/third_party/WebKit/Source/core/workers/ParentFrameTaskRunners.cpp +++ b/third_party/WebKit/Source/core/workers/ParentFrameTaskRunners.cpp
@@ -20,7 +20,7 @@ // For now we only support very limited task types. for (auto type : {TaskType::Internal, TaskType::Networking, TaskType::PostedMessage, - TaskType::CanvasBlobSerialization}) { + TaskType::CanvasBlobSerialization, TaskType::Unthrottled}) { m_taskRunners.add(type, TaskRunnerHelper::get(type, frame)); } }
diff --git a/third_party/WebKit/Source/core/workers/ThreadedWorkletObjectProxy.cpp b/third_party/WebKit/Source/core/workers/ThreadedWorkletObjectProxy.cpp index 33a8c62..37f2e08f 100644 --- a/third_party/WebKit/Source/core/workers/ThreadedWorkletObjectProxy.cpp +++ b/third_party/WebKit/Source/core/workers/ThreadedWorkletObjectProxy.cpp
@@ -10,6 +10,7 @@ #include "core/dom/ExecutionContext.h" #include "core/dom/ExecutionContextTask.h" #include "core/inspector/ConsoleMessage.h" +#include "core/workers/ParentFrameTaskRunners.h" #include "core/workers/ThreadedWorkletMessagingProxy.h" #include "wtf/Functional.h" #include "wtf/PtrUtil.h" @@ -44,14 +45,14 @@ void ThreadedWorkletObjectProxy::postMessageToPageInspector( const String& message) { DCHECK(getExecutionContext()->isDocument()); - // TODO(nhiroki): Replace this with getParentFrameTaskRunners(). - // (https://crbug.com/667310) - toDocument(getExecutionContext()) - ->postInspectorTask( - BLINK_FROM_HERE, - createCrossThreadTask( - &ThreadedWorkletMessagingProxy::postMessageToPageInspector, - m_messagingProxyWeakPtr, message)); + // The TaskType of Inspector tasks need to be Unthrottled because they need to + // run even on a suspended page. + getParentFrameTaskRunners() + ->get(TaskType::Unthrottled) + ->postTask(BLINK_FROM_HERE, + crossThreadBind( + &ThreadedWorkletMessagingProxy::postMessageToPageInspector, + m_messagingProxyWeakPtr, message)); } ParentFrameTaskRunners*
diff --git a/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.cpp b/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.cpp index 6e77abc4..9cd65c6 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.cpp +++ b/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.cpp
@@ -71,7 +71,6 @@ WaitUntilObserver* waitUntilObserver, bool navigationPreloadSent) : ExtendableEvent(type, initializer, waitUntilObserver), - m_scriptState(scriptState), m_observer(respondWithObserver), m_preloadResponseProperty(new PreloadResponseProperty( scriptState->getExecutionContext(), @@ -110,17 +109,17 @@ } void FetchEvent::onNavigationPreloadResponse( + ScriptState* scriptState, std::unique_ptr<WebServiceWorkerResponse> response, std::unique_ptr<WebDataConsumerHandle> dataConsumeHandle) { - if (!m_scriptState->contextIsValid()) + if (!scriptState->contextIsValid()) return; DCHECK(m_preloadResponseProperty); - ScriptState::Scope scope(m_scriptState.get()); - FetchResponseData* responseData = - FetchResponseData::createWithBuffer(new BodyStreamBuffer( - m_scriptState.get(), new BytesConsumerForDataConsumerHandle( - m_scriptState->getExecutionContext(), - std::move(dataConsumeHandle)))); + ScriptState::Scope scope(scriptState); + FetchResponseData* responseData = FetchResponseData::createWithBuffer( + new BodyStreamBuffer(scriptState, new BytesConsumerForDataConsumerHandle( + scriptState->getExecutionContext(), + std::move(dataConsumeHandle)))); responseData->setURL(response->url()); responseData->setStatus(response->status()); responseData->setStatusMessage(response->statusText()); @@ -130,12 +129,13 @@ FetchResponseData* taintedResponse = responseData->createBasicFilteredResponse(); m_preloadResponseProperty->resolve( - Response::create(m_scriptState->getExecutionContext(), taintedResponse)); + Response::create(scriptState->getExecutionContext(), taintedResponse)); } void FetchEvent::onNavigationPreloadError( + ScriptState* scriptState, std::unique_ptr<WebServiceWorkerError> error) { - if (!m_scriptState->contextIsValid()) + if (!scriptState->contextIsValid()) return; DCHECK(m_preloadResponseProperty); m_preloadResponseProperty->reject(
diff --git a/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.h b/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.h index e7a5e13..cf6f254 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.h +++ b/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.h
@@ -54,9 +54,11 @@ void respondWith(ScriptState*, ScriptPromise, ExceptionState&); ScriptPromise preloadResponse(ScriptState*); - void onNavigationPreloadResponse(std::unique_ptr<WebServiceWorkerResponse>, + void onNavigationPreloadResponse(ScriptState*, + std::unique_ptr<WebServiceWorkerResponse>, std::unique_ptr<WebDataConsumerHandle>); - void onNavigationPreloadError(std::unique_ptr<WebServiceWorkerError>); + void onNavigationPreloadError(ScriptState*, + std::unique_ptr<WebServiceWorkerError>); const AtomicString& interfaceName() const override; @@ -71,7 +73,6 @@ bool navigationPreloadSent); private: - RefPtr<ScriptState> m_scriptState; Member<RespondWithObserver> m_observer; Member<Request> m_request; Member<PreloadResponseProperty> m_preloadResponseProperty;
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in index 6ec91c97..1716f622 100644 --- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in +++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
@@ -193,7 +193,6 @@ PushMessaging status=stable QuotaPromise status=experimental ReducedReferrerGranularity -ReloadwithoutSubResourceCacheRevalidation RemotePlayback status=stable RenderingPipelineThrottling status=stable RenderingPipelineThrottlingLoadingIframes status=stable @@ -212,7 +211,7 @@ Sensor status=experimental ServiceWorkerNavigationPreload SetRootScroller status=experimental -ShadowPiercingDescendantCombinator status=test +ShadowPiercingDescendantCombinator status=experimental ShapeDetection status=experimental SharedArrayBuffer SharedWorker status=stable @@ -272,4 +271,4 @@ ParseHTMLOnMainThread status=test SendBeaconThrowForBlobWithNonSimpleType status=experimental PerformanceNavigationTiming2 status=test -BackgroundVideoTrackOptimization status=stable \ No newline at end of file +BackgroundVideoTrackOptimization status=stable
diff --git a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp index 7f6f81b..50364d3 100644 --- a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp +++ b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp
@@ -199,8 +199,9 @@ std::unique_ptr<WebDataConsumerHandle> dataConsumeHandle) { FetchEvent* fetchEvent = m_pendingPreloadFetchEvents.take(fetchEventID); DCHECK(fetchEvent); - fetchEvent->onNavigationPreloadResponse(std::move(response), - std::move(dataConsumeHandle)); + fetchEvent->onNavigationPreloadResponse( + workerGlobalScope()->scriptController()->getScriptState(), + std::move(response), std::move(dataConsumeHandle)); } void ServiceWorkerGlobalScopeProxy::onNavigationPreloadError( @@ -208,7 +209,9 @@ std::unique_ptr<WebServiceWorkerError> error) { FetchEvent* fetchEvent = m_pendingPreloadFetchEvents.take(fetchEventID); DCHECK(fetchEvent); - fetchEvent->onNavigationPreloadError(std::move(error)); + fetchEvent->onNavigationPreloadError( + workerGlobalScope()->scriptController()->getScriptState(), + std::move(error)); } void ServiceWorkerGlobalScopeProxy::dispatchForeignFetchEvent( @@ -353,10 +356,14 @@ void ServiceWorkerGlobalScopeProxy::postMessageToPageInspector( const String& message) { DCHECK(m_embeddedWorker); - document().postInspectorTask( - BLINK_FROM_HERE, - createCrossThreadTask(&WebEmbeddedWorkerImpl::postMessageToPageInspector, - crossThreadUnretained(m_embeddedWorker), message)); + // The TaskType of Inspector tasks need to be Unthrottled because they need to + // run even on a suspended page. + getParentFrameTaskRunners() + ->get(TaskType::Unthrottled) + ->postTask( + BLINK_FROM_HERE, + crossThreadBind(&WebEmbeddedWorkerImpl::postMessageToPageInspector, + crossThreadUnretained(m_embeddedWorker), message)); } ParentFrameTaskRunners*
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp index e0108fad..7c317d7 100644 --- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp +++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -853,8 +853,7 @@ // TODO(clamy): Remove this function once RenderFrame calls load for all // requests. DCHECK(frame()); - DCHECK(loadType == WebFrameLoadType::Reload || - loadType == WebFrameLoadType::ReloadBypassingCache); + DCHECK(isReloadLoadType(static_cast<FrameLoadType>(loadType))); WebURLRequest request = requestForReload(loadType, overrideUrl); if (request.isNull()) return;
diff --git a/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp b/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp index 5e44f8a..5d947a1 100644 --- a/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp +++ b/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp
@@ -282,12 +282,6 @@ RuntimeEnabledFeatures::setReducedReferrerGranularityEnabled(enable); } -void WebRuntimeFeatures::enableReloadwithoutSubResourceCacheRevalidation( - bool enable) { - RuntimeEnabledFeatures::setReloadwithoutSubResourceCacheRevalidationEnabled( - enable); -} - void WebRuntimeFeatures::enablePushMessaging(bool enable) { RuntimeEnabledFeatures::setPushMessagingEnabled(enable); }
diff --git a/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp b/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp index 0167d8c..f1984dd 100644 --- a/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp +++ b/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp
@@ -238,11 +238,15 @@ } void WebSharedWorkerImpl::postMessageToPageInspector(const String& message) { - m_mainFrame->frame()->document()->postInspectorTask( - BLINK_FROM_HERE, - createCrossThreadTask( - &WebSharedWorkerImpl::postMessageToPageInspectorOnMainThread, - crossThreadUnretained(this), message)); + // The TaskType of Inspector tasks need to be Unthrottled because they need to + // run even on a suspended page. + getParentFrameTaskRunners() + ->get(TaskType::Unthrottled) + ->postTask( + BLINK_FROM_HERE, + crossThreadBind( + &WebSharedWorkerImpl::postMessageToPageInspectorOnMainThread, + crossThreadUnretained(this), message)); } void WebSharedWorkerImpl::postMessageToPageInspectorOnMainThread(
diff --git a/third_party/WebKit/public/web/WebRuntimeFeatures.h b/third_party/WebKit/public/web/WebRuntimeFeatures.h index 1865a63..fe4b0e0 100644 --- a/third_party/WebKit/public/web/WebRuntimeFeatures.h +++ b/third_party/WebKit/public/web/WebRuntimeFeatures.h
@@ -105,8 +105,6 @@ BLINK_EXPORT static void enablePresentationAPI(bool); BLINK_EXPORT static void enablePushMessaging(bool); BLINK_EXPORT static void enableReducedReferrerGranularity(bool); - BLINK_EXPORT static void enableReloadwithoutSubResourceCacheRevalidation( - bool); BLINK_EXPORT static void enableRenderingPipelineThrottling(bool); BLINK_EXPORT static void enableRemotePlaybackAPI(bool); BLINK_EXPORT static void enableRootLayerScrolling(bool);
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 5d8f1ea6..589b88cf 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -4148,7 +4148,7 @@ <summary>Image codec inferred during decode.</summary> </histogram> -<histogram name="Blink.Fetch.RequestResourceTime" units="us"> +<histogram name="Blink.Fetch.RequestResourceTime" units="microseconds"> <owner>csharrison@chromium.org</owner> <summary> The total microseconds spent in ResourceFetcher::requestResource. @@ -48379,7 +48379,7 @@ </summary> </histogram> -<histogram name="PreloadScanner.ExternalCSS.ScanTime" units="us"> +<histogram name="PreloadScanner.ExternalCSS.ScanTime" units="microseconds"> <owner>csharrison@chromium.org</owner> <summary> Microseconds it took to scan the first chunk of external CSS for preloads. @@ -63632,18 +63632,36 @@ </summary> </histogram> -<histogram name="Style.AuthorStyleSheet.ParseTime" units="us"> +<histogram name="Style.AuthorStyleSheet.ParseTime" units="microseconds"> <owner>csharrison@chromium.org</owner> <summary> Microseconds spent in StyleSheetContents::parseAuthorStyleSheet. </summary> </histogram> -<histogram name="Style.UpdateTime" units="us"> +<histogram name="Style.UpdateTime" units="microseconds"> <owner>csharrison@chromium.org</owner> <summary>Microseconds spent in Document::updateStyle.</summary> </histogram> +<histogram name="SubresourceFilter.DocumentLoad.Activation.CPUDuration" + units="microseconds"> + <owner>pkalinnikov@chromium.org</owner> + <summary> + Records how much thread CPU time it takes to decide whether subresource + filtering should be activated for a main frame or subframe. + </summary> +</histogram> + +<histogram name="SubresourceFilter.DocumentLoad.Activation.WallDuration" + units="microseconds"> + <owner>pkalinnikov@chromium.org</owner> + <summary> + Records how long it takes to decide whether subresource filtering should be + activated for a main frame or subframe. + </summary> +</histogram> + <histogram name="SubresourceFilter.DocumentLoad.ActivationState" enum="SubresourceFilterActivationState"> <owner>engedy@chromium.org</owner> @@ -63707,6 +63725,39 @@ </summary> </histogram> +<histogram + name="SubresourceFilter.DocumentLoad.SubresourceEvaluation.TotalCPUDuration" + units="microseconds"> + <owner>pkalinnikov@chromium.org</owner> + <summary> + Whenever a document load is finished in a main frame or subframe with + subresource filtering activated, records the total thread CPU time spent on + processing subresource requests in allowLoad. + </summary> +</histogram> + +<histogram + name="SubresourceFilter.DocumentLoad.SubresourceEvaluation.TotalWallDuration" + units="microseconds"> + <owner>pkalinnikov@chromium.org</owner> + <summary> + Whenever a document load is finished in a main frame or subframe with + subresource filtering activated, records the total real time spent on + processing subresource requests in allowLoad, including the time spent on + waiting or being descheduled. + </summary> +</histogram> + +<histogram name="SubresourceFilter.IndexRuleset.CPUDuration" units="ms"> + <owner>pkalinnikov@chromium.org</owner> + <summary> + The total CPU time it took to parse and index all rules. Does not include + time when the indexing thread was not doing actual work, e.g. waiting for + I/O or being descheduled. Recorded every time the RulesetService kicks off a + ruleset indexing process. + </summary> +</histogram> + <histogram name="SubresourceFilter.IndexRuleset.NumUnsupportedRules" units="rules"> <owner>engedy@chromium.org</owner> @@ -63761,6 +63812,26 @@ </summary> </histogram> +<histogram name="SubresourceFilter.SubresourceLoad.Evaluation.CPUDuration" + units="microseconds"> + <owner>pkalinnikov@chromium.org</owner> + <summary> + Whenever a subresource of a document is evaluated against the ruleset, + records the thread CPU time spent on calculating whether it should be + allowed to load. + </summary> +</histogram> + +<histogram name="SubresourceFilter.SubresourceLoad.Evaluation.WallDuration" + units="microseconds"> + <owner>pkalinnikov@chromium.org</owner> + <summary> + Whenever a subresource of a document is evaluated against the ruleset, + records how much time was spent on calculating whether it should be allowed + to load. + </summary> +</histogram> + <histogram name="SubresourceFilter.WriteRuleset.ReplaceFileError" enum="PlatformFileError"> <owner>engedy@chromium.org</owner>
diff --git a/tools/metrics/histograms/pretty_print.py b/tools/metrics/histograms/pretty_print.py index 7e07427..d6bb862 100755 --- a/tools/metrics/histograms/pretty_print.py +++ b/tools/metrics/histograms/pretty_print.py
@@ -32,6 +32,8 @@ UNIT_REWRITES = { + 'microsecond': 'microseconds', + 'us': 'microseconds', 'millisecond': 'ms', 'milliseconds': 'ms', 'kb': 'KB',
diff --git a/tools/perf/benchmarks/page_cycler_v2.py b/tools/perf/benchmarks/page_cycler_v2.py index 4e5b4aa..43a10e9 100644 --- a/tools/perf/benchmarks/page_cycler_v2.py +++ b/tools/perf/benchmarks/page_cycler_v2.py
@@ -167,6 +167,7 @@ cache_temperature.PCV1_COLD, cache_temperature.PCV1_WARM]) +@benchmark.Enabled('android') class PageCyclerV2Top10Mobile(_PageCyclerV2): """Page load time benchmark for the top 10 mobile web pages.