diff --git a/DEPS b/DEPS index df88395..14e469d6 100644 --- a/DEPS +++ b/DEPS
@@ -44,7 +44,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '24a38ed5a84dc6414a938aee5cc7442e6b0faa7d', + 'v8_revision': 'e4336dfaafc0494ff745a163aa458e90a8df39cc', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'cd5e12a9ea397b48056643a7b65126395eec3174', + 'pdfium_revision': '64f4e25304dfd93651ac5c9d5379ed2fffbb993f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '11d3d44fb9d22dea38862472a620d4f0be67ae97', + 'catapult_revision': '3838eb5d96b721896766c557a3d7b514fa427b21', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other.
diff --git a/android_webview/crash_reporter/aw_microdump_crash_reporter.cc b/android_webview/crash_reporter/aw_microdump_crash_reporter.cc index f813842..9f50704 100644 --- a/android_webview/crash_reporter/aw_microdump_crash_reporter.cc +++ b/android_webview/crash_reporter/aw_microdump_crash_reporter.cc
@@ -154,6 +154,10 @@ breakpad::AddGpuFingerprintToMicrodumpCrashHandler(gpu_fingerprint); } +void SetWebViewTextAddrRange(uintptr_t start, uintptr_t end) { + breakpad::SetNativeCodeTextAddrRange(start, end); +} + bool DumpWithoutCrashingToFd(int fd) { return g_crash_reporter_client.Pointer()->DumpWithoutCrashingToFd(fd); }
diff --git a/android_webview/crash_reporter/aw_microdump_crash_reporter.h b/android_webview/crash_reporter/aw_microdump_crash_reporter.h index 33dcc344..cc83295 100644 --- a/android_webview/crash_reporter/aw_microdump_crash_reporter.h +++ b/android_webview/crash_reporter/aw_microdump_crash_reporter.h
@@ -14,6 +14,7 @@ int crash_signal_fd); void AddGpuFingerprintToMicrodumpCrashHandler( const std::string& gpu_fingerprint); +void SetWebViewTextAddrRange(uintptr_t start, uintptr_t end); bool DumpWithoutCrashingToFd(int fd); } // namespace crash_reporter } // namespace android_webview
diff --git a/android_webview/lib/main/aw_main_delegate.cc b/android_webview/lib/main/aw_main_delegate.cc index 3c91dc7..457e91b 100644 --- a/android_webview/lib/main/aw_main_delegate.cc +++ b/android_webview/lib/main/aw_main_delegate.cc
@@ -46,6 +46,21 @@ #include "ui/base/resource/resource_bundle.h" #include "ui/events/gesture_detection/gesture_configuration.h" +// These declarations just provide the addresses determined by the +// linker to this source file in order to determine the extent of the +// webview text section. The declared types are irrelevant - only the +// symbol names and the addresses they reference are important. +extern "C" { +#if defined(ARCH_CPU_MIPSEL) +// the mipsel linker script invoked as a result of chromium link args +// doesn't define __executable_start. +extern char _ftext; +#else +extern char __executable_start; +#endif +extern char __etext; +} + namespace android_webview { namespace { @@ -209,7 +224,15 @@ // crash handler on the same thread as the crash handler was initialized. crash_reporter::AddGpuFingerprintToMicrodumpCrashHandler( content_client_.gpu_fingerprint()); - +#if !defined(COMPONENT_BUILD) + crash_reporter::SetWebViewTextAddrRange( +#if defined(ARCH_CPU_MIPSEL) + reinterpret_cast<uintptr_t>(&_ftext), +#else + reinterpret_cast<uintptr_t>(&__executable_start), +#endif + reinterpret_cast<uintptr_t>(&__etext)); +#endif g_allow_wait_in_ui_thread.Get().reset( new ScopedAllowWaitForLegacyWebViewApi);
diff --git a/chrome/app/address_input_strings.grd b/chrome/app/address_input_strings.grd index cc86c82..cc61b6c2 100644 --- a/chrome/app/address_input_strings.grd +++ b/chrome/app/address_input_strings.grd
@@ -35,7 +35,13 @@ <output filename="address_input_strings_en-GB.pak" type="data_package" lang="en-GB" /> <output filename="address_input_strings_en-US.pak" type="data_package" lang="en" /> <output filename="address_input_strings_es.pak" type="data_package" lang="es" /> - <output filename="address_input_strings_es-419.pak" type="data_package" lang="es-419" /> + <if expr="is_ios"> + <!-- iOS uses es-MX for es-419 --> + <output filename="address_input_strings_es-MX.pak" type="data_package" lang="es-419" /> + </if> + <if expr="not is_ios"> + <output filename="address_input_strings_es-419.pak" type="data_package" lang="es-419" /> + </if> <output filename="address_input_strings_et.pak" type="data_package" lang="et" /> <output filename="address_input_strings_fa.pak" type="data_package" lang="fa" /> <output filename="address_input_strings_fake-bidi.pak" type="data_package" lang="fake-bidi" /> @@ -62,7 +68,13 @@ be 'nb'. --> <output filename="address_input_strings_nb.pak" type="data_package" lang="no" /> <output filename="address_input_strings_pl.pak" type="data_package" lang="pl" /> - <output filename="address_input_strings_pt-BR.pak" type="data_package" lang="pt-BR" /> + <if expr="is_ios"> + <!-- iOS uses pt for pt-BR --> + <output filename="address_input_strings_pt.pak" type="data_package" lang="pt-BR" /> + </if> + <if expr="not is_ios"> + <output filename="address_input_strings_pt-BR.pak" type="data_package" lang="pt-BR" /> + </if> <output filename="address_input_strings_pt-PT.pak" type="data_package" lang="pt-PT" /> <output filename="address_input_strings_ro.pak" type="data_package" lang="ro" /> <output filename="address_input_strings_ru.pak" type="data_package" lang="ru" />
diff --git a/components/crash/content/app/breakpad_linux.cc b/components/crash/content/app/breakpad_linux.cc index 9ebc33f..16c1e5b 100644 --- a/components/crash/content/app/breakpad_linux.cc +++ b/components/crash/content/app/breakpad_linux.cc
@@ -110,7 +110,11 @@ MicrodumpInfo() : microdump_build_fingerprint_(nullptr), microdump_product_info_(nullptr), - microdump_gpu_fingerprint_(nullptr) {} + microdump_gpu_fingerprint_(nullptr), + microdump_process_type_(nullptr), + interest_range_start_(0ul), + interest_range_end_(0ul), + suppress_microdump_based_on_interest_range_(false) {} // The order in which SetGpuFingerprint and Initialize are called // may be dependent on the timing of the availability of GPU @@ -126,6 +130,7 @@ // which a microdump is generated, then the GPU fingerprint will be // UNKNOWN. void SetGpuFingerprint(const std::string& gpu_fingerprint); + void SetMicrodumpInterestRange(uintptr_t start, uintptr_t end); void Initialize(const std::string& process_type, const char* product_name, const char* product_version, @@ -137,6 +142,9 @@ const char* microdump_product_info_; const char* microdump_gpu_fingerprint_; const char* microdump_process_type_; + uintptr_t interest_range_start_; + uintptr_t interest_range_end_; + bool suppress_microdump_based_on_interest_range_; }; base::LazyInstance<MicrodumpInfo> g_microdump_info = @@ -872,6 +880,22 @@ } } +void MicrodumpInfo::SetMicrodumpInterestRange(uintptr_t start, uintptr_t end) { + interest_range_start_ = start; + interest_range_end_ = end; + suppress_microdump_based_on_interest_range_ = true; + + if (g_microdump) { + MinidumpDescriptor descriptor(g_microdump->minidump_descriptor()); + google_breakpad::MicrodumpExtraInfo* microdump_extra_info = + descriptor.microdump_extra_info(); + microdump_extra_info->interest_range_start = interest_range_start_; + microdump_extra_info->interest_range_end = interest_range_end_; + microdump_extra_info->suppress_microdump_based_on_interest_range = true; + g_microdump->set_minidump_descriptor(descriptor); + } +} + void MicrodumpInfo::Initialize(const std::string& process_type, const char* product_name, const char* product_version, @@ -886,31 +910,36 @@ process_type == kBrowserProcessType; MinidumpDescriptor descriptor(MinidumpDescriptor::kMicrodumpOnConsole); + google_breakpad::MicrodumpExtraInfo* microdump_extra_info = + descriptor.microdump_extra_info(); if (product_name && product_version) { microdump_product_info_ = strdup((product_name + std::string(":") + product_version).c_str()); ANNOTATE_LEAKING_OBJECT_PTR(microdump_product_info_); - descriptor.microdump_extra_info()->product_info = microdump_product_info_; + microdump_extra_info->product_info = microdump_product_info_; } microdump_process_type_ = strdup(process_type.empty() ? kBrowserProcessType : process_type.c_str()); ANNOTATE_LEAKING_OBJECT_PTR(microdump_process_type_); - descriptor.microdump_extra_info()->process_type = microdump_process_type_; + microdump_extra_info->process_type = microdump_process_type_; if (android_build_fp) { microdump_build_fingerprint_ = strdup(android_build_fp); ANNOTATE_LEAKING_OBJECT_PTR(microdump_build_fingerprint_); - descriptor.microdump_extra_info()->build_fingerprint = - microdump_build_fingerprint_; + microdump_extra_info->build_fingerprint = microdump_build_fingerprint_; } if (microdump_gpu_fingerprint_) { - descriptor.microdump_extra_info()->gpu_fingerprint = - microdump_gpu_fingerprint_; + microdump_extra_info->gpu_fingerprint = microdump_gpu_fingerprint_; } + microdump_extra_info->interest_range_start = interest_range_start_; + microdump_extra_info->interest_range_end = interest_range_end_; + microdump_extra_info->suppress_microdump_based_on_interest_range = + suppress_microdump_based_on_interest_range_; + g_microdump = new ExceptionHandler(descriptor, nullptr, MicrodumpCrashDone, reinterpret_cast<void*>(is_browser_process), @@ -1934,6 +1963,10 @@ const std::string& gpu_fingerprint) { g_microdump_info.Get().SetGpuFingerprint(gpu_fingerprint); } + +void SetNativeCodeTextAddrRange(uintptr_t start, uintptr_t end) { + g_microdump_info.Get().SetMicrodumpInterestRange(start, end); +} #endif // OS_ANDROID bool IsCrashReporterEnabled() {
diff --git a/components/crash/content/app/breakpad_linux.h b/components/crash/content/app/breakpad_linux.h index 3316fa0..0d70a9d 100644 --- a/components/crash/content/app/breakpad_linux.h +++ b/components/crash/content/app/breakpad_linux.h
@@ -31,6 +31,11 @@ extern void AddGpuFingerprintToMicrodumpCrashHandler( const std::string& gpu_fingerprint); + +// Inform breakpad of the extent of the text section that is +// considered interesting for the purpose of crashes so that this can +// be used to elide crashes that do not reference interesting code. +extern void SetNativeCodeTextAddrRange(uintptr_t start, uintptr_t end); #endif // Checks if crash reporting is enabled. Note that this is not the same as
diff --git a/components/ntp_snippets/pref_names.cc b/components/ntp_snippets/pref_names.cc index 9b0ff032..0fe7edf 100644 --- a/components/ntp_snippets/pref_names.cc +++ b/components/ntp_snippets/pref_names.cc
@@ -41,6 +41,9 @@ "ntp_suggestions.foreign_sessions.dismissed_ids"; const char kDismissedCategories[] = "ntp_suggestions.dismissed_categories"; +const char kLastSuccessfulBackgroundFetchTime[] = + "ntp_suggestions.remote.last_successful_background_fetch_time"; + const char kUserClassifierAverageNTPOpenedPerHour[] = "ntp_suggestions.user_classifier.average_ntp_opened_per_hour"; const char kUserClassifierAverageSuggestionsShownPerHour[] =
diff --git a/components/ntp_snippets/pref_names.h b/components/ntp_snippets/pref_names.h index d474d4c4..a1f7dd1 100644 --- a/components/ntp_snippets/pref_names.h +++ b/components/ntp_snippets/pref_names.h
@@ -40,6 +40,9 @@ // thumbnails. extern const char kSnippetThumbnailsRequestsDay[]; +// The pref name for the time of the last successful background fetch. +extern const char kLastSuccessfulBackgroundFetchTime[]; + extern const char kDismissedAssetDownloadSuggestions[]; extern const char kDismissedRecentOfflineTabSuggestions[]; extern const char kDismissedOfflinePageDownloadSuggestions[];
diff --git a/components/ntp_snippets/remote/ntp_snippets_fetcher.cc b/components/ntp_snippets/remote/ntp_snippets_fetcher.cc index 62236a8..76ec5f1e 100644 --- a/components/ntp_snippets/remote/ntp_snippets_fetcher.cc +++ b/components/ntp_snippets/remote/ntp_snippets_fetcher.cc
@@ -1005,7 +1005,7 @@ DVLOG(1) << "Fetch finished: " << last_status_; - std::move(callback).Run(std::move(categories)); + std::move(callback).Run(status_code, std::move(categories)); } bool NTPSnippetsFetcher::JsonToSnippets(const base::Value& parsed,
diff --git a/components/ntp_snippets/remote/ntp_snippets_fetcher.h b/components/ntp_snippets/remote/ntp_snippets_fetcher.h index 62437c9..772aa05 100644 --- a/components/ntp_snippets/remote/ntp_snippets_fetcher.h +++ b/components/ntp_snippets/remote/ntp_snippets_fetcher.h
@@ -80,12 +80,6 @@ using FetchedCategoriesVector = std::vector<FetchedCategory>; using OptionalFetchedCategories = base::Optional<FetchedCategoriesVector>; - // |snippets| contains parsed snippets if a fetch succeeded. If problems - // occur, |snippets| contains no value (no actual vector in base::Optional). - // Error details can be retrieved using last_status(). - using SnippetsAvailableCallback = - base::OnceCallback<void(OptionalFetchedCategories fetched_categories)>; - // Enumeration listing all possible outcomes for fetch attempts. Used for UMA // histograms, so do not change existing values. Insert new values at the end, // and update the histogram definition. @@ -102,6 +96,13 @@ RESULT_MAX }; + // |snippets| contains parsed snippets if a fetch succeeded. If problems + // occur, |snippets| contains no value (no actual vector in base::Optional). + // Error details can be retrieved using last_status(). + using SnippetsAvailableCallback = + base::OnceCallback<void(FetchResult fetch_result, + OptionalFetchedCategories fetched_categories)>; + // Enumeration listing all possible variants of dealing with personalization. enum class Personalization { kPersonal, kNonPersonal, kBoth };
diff --git a/components/ntp_snippets/remote/ntp_snippets_fetcher_unittest.cc b/components/ntp_snippets/remote/ntp_snippets_fetcher_unittest.cc index c02ffa4..dde8e381 100644 --- a/components/ntp_snippets/remote/ntp_snippets_fetcher_unittest.cc +++ b/components/ntp_snippets/remote/ntp_snippets_fetcher_unittest.cc
@@ -60,8 +60,8 @@ // Artificial time delay for JSON parsing. const int64_t kTestJsonParsingLatencyMs = 20; -ACTION_P(MoveArgumentPointeeTo, ptr) { - *ptr = std::move(*arg0); +ACTION_P(MoveArgument1PointeeTo, ptr) { + *ptr = std::move(*arg1); } MATCHER(HasValue, "") { @@ -149,13 +149,15 @@ public: // Workaround for gMock's lack of support for movable arguments. void WrappedRun( + NTPSnippetsFetcher::FetchResult fetch_result, NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories) { - Run(&fetched_categories); + Run(fetch_result, &fetched_categories); } - MOCK_METHOD1( + MOCK_METHOD2( Run, - void(NTPSnippetsFetcher::OptionalFetchedCategories* fetched_categories)); + void(NTPSnippetsFetcher::FetchResult fetch_result, + NTPSnippetsFetcher::OptionalFetchedCategories* fetched_categories)); }; // Factory for FakeURLFetcher objects that always generate errors. @@ -610,10 +612,10 @@ "}]}"; SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS); - EXPECT_CALL( - mock_callback(), - Run(AllOf(IsSingleArticle("http://localhost/foobar"), - FirstCategoryHasInfo(IsCategoryInfoForArticles())))); + EXPECT_CALL(mock_callback(), + Run(NTPSnippetsFetcher::FetchResult::SUCCESS, + AllOf(IsSingleArticle("http://localhost/foobar"), + FirstCategoryHasInfo(IsCategoryInfoForArticles())))); snippets_fetcher().FetchSnippets( test_params(), ToSnippetsAvailableCallback(&mock_callback())); FastForwardUntilNoTasksRemain(); @@ -648,7 +650,8 @@ SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS); EXPECT_CALL(mock_callback(), - Run(AllOf(IsSingleArticle("http://localhost/foobar"), + Run(NTPSnippetsFetcher::FetchResult::SUCCESS, + AllOf(IsSingleArticle("http://localhost/foobar"), FirstCategoryHasInfo(IsCategoryInfoForArticles())))); snippets_fetcher().FetchSnippets( test_params(), ToSnippetsAvailableCallback(&mock_callback())); @@ -671,7 +674,8 @@ "}]}"; SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS); - EXPECT_CALL(mock_callback(), Run(IsEmptyArticleList())); + EXPECT_CALL(mock_callback(), Run(NTPSnippetsFetcher::FetchResult::SUCCESS, + IsEmptyArticleList())); snippets_fetcher().FetchSnippets( test_params(), ToSnippetsAvailableCallback(&mock_callback())); FastForwardUntilNoTasksRemain(); @@ -722,8 +726,8 @@ SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS); NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories; - EXPECT_CALL(mock_callback(), Run(_)) - .WillOnce(MoveArgumentPointeeTo(&fetched_categories)); + EXPECT_CALL(mock_callback(), Run(NTPSnippetsFetcher::FetchResult::SUCCESS, _)) + .WillOnce(MoveArgument1PointeeTo(&fetched_categories)); snippets_fetcher().FetchSnippets( test_params(), ToSnippetsAvailableCallback(&mock_callback())); FastForwardUntilNoTasksRemain(); @@ -784,8 +788,8 @@ SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS); NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories; - EXPECT_CALL(mock_callback(), Run(_)) - .WillOnce(MoveArgumentPointeeTo(&fetched_categories)); + EXPECT_CALL(mock_callback(), Run(NTPSnippetsFetcher::FetchResult::SUCCESS, _)) + .WillOnce(MoveArgument1PointeeTo(&fetched_categories)); snippets_fetcher().FetchSnippets( test_params(), ToSnippetsAvailableCallback(&mock_callback())); FastForwardUntilNoTasksRemain(); @@ -848,8 +852,8 @@ SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS); NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories; - EXPECT_CALL(mock_callback(), Run(_)) - .WillOnce(MoveArgumentPointeeTo(&fetched_categories)); + EXPECT_CALL(mock_callback(), Run(NTPSnippetsFetcher::FetchResult::SUCCESS, _)) + .WillOnce(MoveArgument1PointeeTo(&fetched_categories)); NTPSnippetsFetcher::Params params = test_params(); params.exclusive_category = base::Optional<Category>( @@ -892,7 +896,8 @@ const std::string kJsonStr = "{\"recos\": []}"; SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS); - EXPECT_CALL(mock_callback(), Run(IsEmptyArticleList())); + EXPECT_CALL(mock_callback(), Run(NTPSnippetsFetcher::FetchResult::SUCCESS, + IsEmptyArticleList())); snippets_fetcher().FetchSnippets( test_params(), ToSnippetsAvailableCallback(&mock_callback())); FastForwardUntilNoTasksRemain(); @@ -940,7 +945,10 @@ // call to the delegate that usually happens on |Start|. // Without the call to the delegate, it leaks the request that owns itself. ASSERT_THAT(fetcher->delegate(), NotNull()); - EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); + EXPECT_CALL(mock_callback(), + Run(NTPSnippetsFetcher::FetchResult::URL_REQUEST_STATUS_ERROR, + /*snippets=*/Not(HasValue()))) + .Times(1); // An 4XX response needs the least configuration to successfully invoke the // callback properly as the results are not important in this test. fetcher->set_response_code(net::HTTP_NOT_FOUND); @@ -951,7 +959,10 @@ TEST_F(NTPSnippetsFetcherTest, ShouldReportUrlStatusError) { SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND, net::URLRequestStatus::FAILED); - EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); + EXPECT_CALL(mock_callback(), + Run(NTPSnippetsFetcher::FetchResult::URL_REQUEST_STATUS_ERROR, + /*snippets=*/Not(HasValue()))) + .Times(1); snippets_fetcher().FetchSnippets( test_params(), ToSnippetsAvailableCallback(&mock_callback())); FastForwardUntilNoTasksRemain(); @@ -971,7 +982,9 @@ TEST_F(NTPSnippetsFetcherTest, ShouldReportHttpError) { SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND, net::URLRequestStatus::SUCCESS); - EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); + EXPECT_CALL(mock_callback(), Run(NTPSnippetsFetcher::FetchResult::HTTP_ERROR, + /*snippets=*/Not(HasValue()))) + .Times(1); snippets_fetcher().FetchSnippets( test_params(), ToSnippetsAvailableCallback(&mock_callback())); FastForwardUntilNoTasksRemain(); @@ -990,7 +1003,10 @@ const std::string kInvalidJsonStr = "{ \"recos\": []"; SetFakeResponse(/*response_data=*/kInvalidJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS); - EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); + EXPECT_CALL(mock_callback(), + Run(NTPSnippetsFetcher::FetchResult::JSON_PARSE_ERROR, + /*snippets=*/Not(HasValue()))) + .Times(1); snippets_fetcher().FetchSnippets( test_params(), ToSnippetsAvailableCallback(&mock_callback())); FastForwardUntilNoTasksRemain(); @@ -1011,7 +1027,10 @@ TEST_F(NTPSnippetsFetcherTest, ShouldReportJsonErrorForEmptyResponse) { SetFakeResponse(/*response_data=*/std::string(), net::HTTP_OK, net::URLRequestStatus::SUCCESS); - EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); + EXPECT_CALL(mock_callback(), + Run(NTPSnippetsFetcher::FetchResult::JSON_PARSE_ERROR, + /*snippets=*/Not(HasValue()))) + .Times(1); snippets_fetcher().FetchSnippets( test_params(), ToSnippetsAvailableCallback(&mock_callback())); FastForwardUntilNoTasksRemain(); @@ -1029,7 +1048,11 @@ "{\"recos\": [{ \"contentInfo\": { \"foo\" : \"bar\" }}]}"; SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS); - EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); + EXPECT_CALL( + mock_callback(), + Run(NTPSnippetsFetcher::FetchResult::INVALID_SNIPPET_CONTENT_ERROR, + /*snippets=*/Not(HasValue()))) + .Times(1); snippets_fetcher().FetchSnippets( test_params(), ToSnippetsAvailableCallback(&mock_callback())); FastForwardUntilNoTasksRemain(); @@ -1048,7 +1071,10 @@ // hard-to-reproduce test failures. TEST_F(NTPSnippetsFetcherTest, ShouldReportHttpErrorForMissingBakedResponse) { InitFakeURLFetcherFactory(); - EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); + EXPECT_CALL(mock_callback(), + Run(NTPSnippetsFetcher::FetchResult::URL_REQUEST_STATUS_ERROR, + /*snippets=*/Not(HasValue()))) + .Times(1); snippets_fetcher().FetchSnippets( test_params(), ToSnippetsAvailableCallback(&mock_callback())); FastForwardUntilNoTasksRemain(); @@ -1058,7 +1084,9 @@ const std::string kJsonStr = "{ \"recos\": [] }"; SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS); - EXPECT_CALL(mock_callback(), Run(IsEmptyArticleList())).Times(5); + EXPECT_CALL(mock_callback(), Run(NTPSnippetsFetcher::FetchResult::SUCCESS, + IsEmptyArticleList())) + .Times(5); snippets_fetcher().FetchSnippets( test_params(), ToSnippetsAvailableCallback(&mock_callback())); // More calls to FetchSnippets() do not interrupt the previous.
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider.cc b/components/ntp_snippets/remote/remote_suggestions_provider.cc index 653c82b..4ff354f 100644 --- a/components/ntp_snippets/remote/remote_suggestions_provider.cc +++ b/components/ntp_snippets/remote/remote_suggestions_provider.cc
@@ -19,6 +19,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/task_runner_util.h" +#include "base/time/default_tick_clock.h" #include "base/time/time.h" #include "base/values.h" #include "components/data_use_measurement/core/data_use_user_data.h" @@ -249,7 +250,8 @@ nuke_when_initialized_(false), thumbnail_requests_throttler_( pref_service, - RequestThrottler::RequestType::CONTENT_SUGGESTION_THUMBNAIL) { + RequestThrottler::RequestType::CONTENT_SUGGESTION_THUMBNAIL), + tick_clock_(base::MakeUnique<base::DefaultTickClock>()) { pref_service_->ClearPref(kDeprecatedSnippetHostsPref); RestoreCategoriesFromPrefs(); @@ -290,6 +292,7 @@ registry->RegisterInt64Pref(prefs::kSnippetBackgroundFetchingIntervalWifi, 0); registry->RegisterInt64Pref(prefs::kSnippetBackgroundFetchingIntervalFallback, 0); + registry->RegisterInt64Pref(prefs::kLastSuccessfulBackgroundFetchTime, 0); RemoteSuggestionsStatusService::RegisterProfilePrefs(registry); } @@ -331,7 +334,7 @@ params.interactive_request = interactive_request; snippets_fetcher_->FetchSnippets( params, base::BindOnce(&RemoteSuggestionsProvider::OnFetchFinished, - base::Unretained(this))); + base::Unretained(this), interactive_request)); } void RemoteSuggestionsProvider::Fetch( @@ -641,6 +644,7 @@ void RemoteSuggestionsProvider::OnFetchMoreFinished( const FetchDoneCallback& fetching_callback, + NTPSnippetsFetcher::FetchResult fetch_result, NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories) { if (!fetched_categories) { // TODO(fhorschig): Disambiguate the kind of error that led here. @@ -702,6 +706,8 @@ } void RemoteSuggestionsProvider::OnFetchFinished( + bool interactive_request, + NTPSnippetsFetcher::FetchResult fetch_result, NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories) { if (!ready()) { // TODO(tschumann): What happens if this was a user-triggered, interactive @@ -709,6 +715,13 @@ return; } + // Record the fetch time of a successfull background fetch. + if (!interactive_request && + fetch_result == NTPSnippetsFetcher::FetchResult::SUCCESS) { + pref_service_->SetInt64(prefs::kLastSuccessfulBackgroundFetchTime, + tick_clock_->NowTicks().ToInternalValue()); + } + // Mark all categories as not provided by the server in the latest fetch. The // ones we got will be marked again below. for (auto& item : category_contents_) {
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider.h b/components/ntp_snippets/remote/remote_suggestions_provider.h index a8081b7e..1c76a58 100644 --- a/components/ntp_snippets/remote/remote_suggestions_provider.h +++ b/components/ntp_snippets/remote/remote_suggestions_provider.h
@@ -151,6 +151,11 @@ return category_contents_.find(category)->second.dismissed; } + // Overrides internal clock for testing purposes. + void SetTickClockForTesting(std::unique_ptr<base::TickClock> tick_clock) { + tick_clock_ = std::move(tick_clock); + } + private: friend class RemoteSuggestionsProviderTest; @@ -261,10 +266,13 @@ // Callback for fetch-more requests with the NTPSnippetsFetcher. void OnFetchMoreFinished( const FetchDoneCallback& fetching_callback, + NTPSnippetsFetcher::FetchResult fetch_result, NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories); // Callback for regular fetch requests with the NTPSnippetsFetcher. void OnFetchFinished( + bool interactive_request, + NTPSnippetsFetcher::FetchResult fetch_status, NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories); // Moves all snippets from |to_archive| into the archive of the |content|. @@ -407,6 +415,9 @@ // Request throttler for limiting requests to thumbnail images. RequestThrottler thumbnail_requests_throttler_; + // A clock for getting the time. This allows to inject a tick clock in tests. + std::unique_ptr<base::TickClock> tick_clock_; + DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsProvider); };
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_provider_unittest.cc index b593ee4..27ac0a2 100644 --- a/components/ntp_snippets/remote/remote_suggestions_provider_unittest.cc +++ b/components/ntp_snippets/remote/remote_suggestions_provider_unittest.cc
@@ -20,6 +20,7 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/test/histogram_tester.h" +#include "base/test/simple_test_tick_clock.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "components/image_fetcher/image_decoder.h" @@ -1593,4 +1594,37 @@ SizeIs(service->GetMaxSnippetCountForTesting() + 1)); } +TEST_F(RemoteSuggestionsProviderTest, StoreLastSuccessfullBackgroundFetchTime) { + // On initialization of the RemoteSuggestionsProvider a background fetch is + // triggered since the snippets DB is empty. Therefore the service must not be + // initialized until the test clock is set. + auto service = MakeSnippetsServiceWithoutInitialization(); + + auto simple_test_tick_clock = base::MakeUnique<base::SimpleTestTickClock>(); + base::SimpleTestTickClock* simple_test_tick_clock_ptr = + simple_test_tick_clock.get(); + service->SetTickClockForTesting(std::move(simple_test_tick_clock)); + + // Test that the preference is correctly initialized with the default value 0. + EXPECT_EQ( + 0, pref_service()->GetInt64(prefs::kLastSuccessfulBackgroundFetchTime)); + + WaitForSnippetsServiceInitialization(service.get(), + /*set_empty_response=*/true); + EXPECT_EQ( + simple_test_tick_clock_ptr->NowTicks().ToInternalValue(), + pref_service()->GetInt64(prefs::kLastSuccessfulBackgroundFetchTime)); + + // Advance the time and check whether the time was updated correctly after the + // background fetch. + simple_test_tick_clock_ptr->Advance(TimeDelta::FromHours(1)); + service->FetchSnippetsInTheBackground(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + simple_test_tick_clock_ptr->NowTicks().ToInternalValue(), + pref_service()->GetInt64(prefs::kLastSuccessfulBackgroundFetchTime)); + // TODO(markusheintz): Add a test that simulates a browser restart once the + // scheduler refactoring is done (crbug.com/672434). +} + } // namespace ntp_snippets
diff --git a/ios/chrome/app/resources/BUILD.gn b/ios/chrome/app/resources/BUILD.gn index f83e2dc4..f89503e 100644 --- a/ios/chrome/app/resources/BUILD.gn +++ b/ios/chrome/app/resources/BUILD.gn
@@ -113,50 +113,3 @@ ios_launchscreen_assets_target, ] } - -bundle_data("terms_of_service_bundle") { - sources = [ - "//components/resources/terms/terms_ar.html", - "//components/resources/terms/terms_bg.html", - "//components/resources/terms/terms_ca.html", - "//components/resources/terms/terms_cs.html", - "//components/resources/terms/terms_da.html", - "//components/resources/terms/terms_de.html", - "//components/resources/terms/terms_el.html", - "//components/resources/terms/terms_en-GB.html", - "//components/resources/terms/terms_en.html", - "//components/resources/terms/terms_es-419.html", - "//components/resources/terms/terms_es.html", - "//components/resources/terms/terms_fa.html", - "//components/resources/terms/terms_fi.html", - "//components/resources/terms/terms_fr.html", - "//components/resources/terms/terms_he.html", - "//components/resources/terms/terms_hi.html", - "//components/resources/terms/terms_hr.html", - "//components/resources/terms/terms_hu.html", - "//components/resources/terms/terms_id.html", - "//components/resources/terms/terms_it.html", - "//components/resources/terms/terms_ja.html", - "//components/resources/terms/terms_ko.html", - "//components/resources/terms/terms_lt.html", - "//components/resources/terms/terms_nb.html", - "//components/resources/terms/terms_nl.html", - "//components/resources/terms/terms_pl.html", - "//components/resources/terms/terms_pt-BR.html", - "//components/resources/terms/terms_pt-PT.html", - "//components/resources/terms/terms_ro.html", - "//components/resources/terms/terms_ru.html", - "//components/resources/terms/terms_sk.html", - "//components/resources/terms/terms_sr.html", - "//components/resources/terms/terms_sv.html", - "//components/resources/terms/terms_th.html", - "//components/resources/terms/terms_tr.html", - "//components/resources/terms/terms_uk.html", - "//components/resources/terms/terms_vi.html", - "//components/resources/terms/terms_zh-CN.html", - "//components/resources/terms/terms_zh-TW.html", - ] - outputs = [ - "{{bundle_resources_dir}}/{{source_file_part}}", - ] -}
diff --git a/ios/chrome/browser/passwords/BUILD.gn b/ios/chrome/browser/passwords/BUILD.gn index d8ca5d4..8aea29c 100644 --- a/ios/chrome/browser/passwords/BUILD.gn +++ b/ios/chrome/browser/passwords/BUILD.gn
@@ -96,6 +96,7 @@ } source_set("unit_tests") { + configs += [ "//build/config/compiler:enable_arc" ] testonly = true sources = [ "credential_manager_js_unittest.mm",
diff --git a/ios/chrome/browser/passwords/credential_manager_js_unittest.mm b/ios/chrome/browser/passwords/credential_manager_js_unittest.mm index 37f0d66..f9f8fbf 100644 --- a/ios/chrome/browser/passwords/credential_manager_js_unittest.mm +++ b/ios/chrome/browser/passwords/credential_manager_js_unittest.mm
@@ -5,7 +5,6 @@ #include <memory> #include "base/mac/foundation_util.h" -#import "base/mac/scoped_nsobject.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #import "ios/chrome/browser/passwords/js_credential_manager.h" @@ -19,6 +18,10 @@ #include "testing/gtest_mac.h" #include "url/gurl.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace { using ::testing::_; @@ -59,9 +62,9 @@ void SetUp() override { web::WebTestWithWebState::SetUp(); - js_credential_manager_.reset(base::mac::ObjCCastStrict<JSCredentialManager>( - [[web_state()->GetJSInjectionReceiver() - instanceOfClass:[JSCredentialManager class]] retain])); + js_credential_manager_ = base::mac::ObjCCastStrict<JSCredentialManager>( + [web_state()->GetJSInjectionReceiver() + instanceOfClass:[JSCredentialManager class]]); observer_.reset(new MockWebStateObserver(web_state())); } @@ -255,7 +258,7 @@ private: // Manager for injected credential manager JavaScript. - base::scoped_nsobject<JSCredentialManager> js_credential_manager_; + JSCredentialManager* js_credential_manager_; // Mock observer for testing. std::unique_ptr<MockWebStateObserver> observer_;
diff --git a/ios/chrome/browser/passwords/credential_manager_unittest.mm b/ios/chrome/browser/passwords/credential_manager_unittest.mm index a66d524..da6a3d07 100644 --- a/ios/chrome/browser/passwords/credential_manager_unittest.mm +++ b/ios/chrome/browser/passwords/credential_manager_unittest.mm
@@ -7,7 +7,6 @@ #include <memory> #include <utility> -#include "base/mac/bind_objc_block.h" #include "base/memory/ref_counted.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" @@ -31,6 +30,10 @@ #include "third_party/ocmock/gtest_support.h" #include "url/gurl.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + using testing::Return; namespace { @@ -105,9 +108,9 @@ // Returns a block that takes a string argument and returns whether it is equal // to |string|. StringPredicate EqualsString(const char* string) { - return [[^BOOL(NSString* other) { + return [^BOOL(NSString* other) { return [base::SysUTF8ToNSString(string) isEqualToString:other]; - } copy] autorelease]; + } copy]; } // A stub PasswordManagerClient for testing. @@ -191,11 +194,11 @@ web::WebTestWithWebState::SetUp(); id originalMock = [OCMockObject niceMockForClass:[JSCredentialManager class]]; - mock_js_credential_manager_.reset([[MockJSCredentialManager alloc] - initWithRepresentedObject:originalMock]); - credential_manager_.reset(new CredentialManager( - web_state(), &stub_client_, &stub_driver_, - static_cast<id>(mock_js_credential_manager_.get()))); + mock_js_credential_manager_ = [[MockJSCredentialManager alloc] + initWithRepresentedObject:originalMock]; + credential_manager_.reset( + new CredentialManager(web_state(), &stub_client_, &stub_driver_, + static_cast<id>(mock_js_credential_manager_))); LoadHtml(@"", GURL(kTestURL)); } @@ -263,7 +266,7 @@ password_manager::StubPasswordManagerDriver stub_driver_; // Mock for JSCredentialManager. - base::scoped_nsobject<MockJSCredentialManager> mock_js_credential_manager_; + MockJSCredentialManager* mock_js_credential_manager_; // CredentialManager for testing. std::unique_ptr<CredentialManager> credential_manager_;
diff --git a/ios/chrome/browser/passwords/password_controller_js_unittest.mm b/ios/chrome/browser/passwords/password_controller_js_unittest.mm index 5b557d2..77f0e1d8 100644 --- a/ios/chrome/browser/passwords/password_controller_js_unittest.mm +++ b/ios/chrome/browser/passwords/password_controller_js_unittest.mm
@@ -10,6 +10,10 @@ #include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest_mac.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + // Unit tests for ios/chrome/browser/web/resources/password_controller.js namespace {
diff --git a/ios/chrome/browser/passwords/password_controller_off_the_record_unittest.mm b/ios/chrome/browser/passwords/password_controller_off_the_record_unittest.mm index ea5a861..8afcc2c 100644 --- a/ios/chrome/browser/passwords/password_controller_off_the_record_unittest.mm +++ b/ios/chrome/browser/passwords/password_controller_off_the_record_unittest.mm
@@ -4,7 +4,6 @@ #include <memory> -#import "base/mac/scoped_nsobject.h" #include "base/memory/ptr_util.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" @@ -13,6 +12,10 @@ #import "ios/web/public/test/web_test_with_web_state.h" #include "testing/gtest/include/gtest/gtest.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace { class IncognitoPasswordManagerClient @@ -42,11 +45,10 @@ public: void SetUp() override { web::WebTestWithWebState::SetUp(); - password_controller_.reset([[PasswordController alloc] + password_controller_ = [[PasswordController alloc] initWithWebState:&off_the_record_web_state_ passwordsUiDelegate:nil - client:base::MakeUnique< - IncognitoPasswordManagerClient>()]); + client:base::MakeUnique<IncognitoPasswordManagerClient>()]; } void TearDown() override { @@ -56,7 +58,7 @@ protected: OffTheRecordWebState off_the_record_web_state_; - base::scoped_nsobject<PasswordController> password_controller_; + PasswordController* password_controller_; }; // Check that if the PasswordController is told (by the PasswordManagerClient)
diff --git a/ios/chrome/browser/passwords/password_controller_unittest.mm b/ios/chrome/browser/passwords/password_controller_unittest.mm index f02a0f7..fda0914 100644 --- a/ios/chrome/browser/passwords/password_controller_unittest.mm +++ b/ios/chrome/browser/passwords/password_controller_unittest.mm
@@ -11,7 +11,6 @@ #include "base/json/json_reader.h" #include "base/mac/bind_objc_block.h" -#import "base/mac/scoped_nsobject.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" #include "base/strings/sys_string_conversions.h" @@ -39,6 +38,10 @@ #import "third_party/ocmock/OCMock/OCPartialMockObject.h" #include "url/gurl.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + using autofill::PasswordForm; using autofill::PasswordFormFillData; using testing::Return; @@ -85,17 +88,16 @@ // using the given |store|. If not null, |weak_client| is filled with a // non-owning pointer to the created client. The created controller is // returned. -base::scoped_nsobject<PasswordController> CreatePasswordController( +PasswordController* CreatePasswordController( web::WebState* web_state, password_manager::PasswordStore* store, MockPasswordManagerClient** weak_client) { auto client = base::MakeUnique<MockPasswordManagerClient>(store); if (weak_client) *weak_client = client.get(); - return base::scoped_nsobject<PasswordController>([[PasswordController alloc] - initWithWebState:web_state - passwordsUiDelegate:nil - client:std::move(client)]); + return [[PasswordController alloc] initWithWebState:web_state + passwordsUiDelegate:nil + client:std::move(client)]; } } // namespace @@ -129,8 +131,6 @@ @property(nonatomic, copy) NSArray* suggestions; -- (void)dealloc; - @end @implementation PasswordsTestSuggestionController @@ -141,10 +141,6 @@ self.suggestions = suggestions; } -- (void)dealloc { - [_suggestions release]; - [super dealloc]; -} @end @@ -164,12 +160,12 @@ // otherwise [passwordController_ suggestionProvider] will be retained // until PlatformTest teardown, at which point all Chrome objects are // already gone and teardown may access invalid memory. - suggestionController_.reset([[PasswordsTestSuggestionController alloc] + suggestionController_ = [[PasswordsTestSuggestionController alloc] initWithWebState:web_state() - providers:@[ [passwordController_ suggestionProvider] ]]); - accessoryViewController_.reset([[FormInputAccessoryViewController alloc] + providers:@[ [passwordController_ suggestionProvider] ]]; + accessoryViewController_ = [[FormInputAccessoryViewController alloc] initWithWebState:web_state() - providers:@[ [suggestionController_ accessoryViewProvider] ]]); + providers:@[ [suggestionController_ accessoryViewProvider] ]]; } } @@ -218,7 +214,7 @@ ++failure_count; // Fetches the completion handler from |invocation| and calls it with // failure status. - void (^completionHandler)(BOOL); + __unsafe_unretained void (^completionHandler)(BOOL); const NSInteger kArgOffset = 1; const NSInteger kCompletionHandlerArgIndex = 4; [invocation getArgument:&completionHandler @@ -235,15 +231,13 @@ } // SuggestionController for testing. - base::scoped_nsobject<PasswordsTestSuggestionController> - suggestionController_; + PasswordsTestSuggestionController* suggestionController_; // FormInputAccessoryViewController for testing. - base::scoped_nsobject<FormInputAccessoryViewController> - accessoryViewController_; + FormInputAccessoryViewController* accessoryViewController_; // PasswordController for testing. - base::scoped_nsobject<PasswordController> passwordController_; + PasswordController* passwordController_; scoped_refptr<password_manager::PasswordStore> store_; }; @@ -1266,7 +1260,7 @@ .WillByDefault(testing::Return(browser_state.get())); MockPasswordManagerClient* weak_client = nullptr; - base::scoped_nsobject<PasswordController> passwordController = + PasswordController* passwordController = CreatePasswordController(&web_state, nullptr, &weak_client); static_cast<TestingPrefServiceSimple*>(weak_client->GetPrefs()) ->registry()
diff --git a/ios/chrome/browser/passwords/password_generation_agent_unittest.mm b/ios/chrome/browser/passwords/password_generation_agent_unittest.mm index 744518e..d96792be 100644 --- a/ios/chrome/browser/passwords/password_generation_agent_unittest.mm +++ b/ios/chrome/browser/passwords/password_generation_agent_unittest.mm
@@ -9,9 +9,9 @@ #include "base/logging.h" #include "base/mac/foundation_util.h" -#import "base/mac/scoped_nsobject.h" #include "base/mac/scoped_objc_class_swizzler.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/strings/string16.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" @@ -35,6 +35,10 @@ #include "third_party/ocmock/gtest_support.h" #include "url/gurl.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace { NSString* const kAccountCreationFormName = @"create-foo-account"; @@ -94,7 +98,7 @@ @implementation DonorWindow - (void)chromeExecuteCommand:(id)sender { - g_chrome_execute_command_sender = [sender retain]; + g_chrome_execute_command_sender = sender; } @end @@ -112,7 +116,6 @@ } ~ScopedWindowSwizzler() { - [g_chrome_execute_command_sender release]; g_chrome_execute_command_sender = nil; } @@ -215,23 +218,23 @@ public: void SetUp() override { web::WebTestWithWebState::SetUp(); - mock_js_suggestion_manager_.reset( - [[OCMockObject niceMockForClass:[JsSuggestionManager class]] retain]); - mock_js_password_manager_.reset( - [[OCMockObject niceMockForClass:[JsPasswordManager class]] retain]); - mock_ui_delegate_.reset([[MockPasswordsUiDelegate alloc] init]); - test_web_state_.reset(new web::TestWebState); - agent_.reset([[PasswordGenerationAgent alloc] + mock_js_suggestion_manager_ = + [OCMockObject niceMockForClass:[JsSuggestionManager class]]; + mock_js_password_manager_ = + [OCMockObject niceMockForClass:[JsPasswordManager class]]; + mock_ui_delegate_ = [[MockPasswordsUiDelegate alloc] init]; + test_web_state_ = base::MakeUnique<web::TestWebState>(); + agent_ = [[PasswordGenerationAgent alloc] initWithWebState:test_web_state_.get() passwordManager:nullptr passwordManagerDriver:nullptr JSPasswordManager:mock_js_password_manager_ JSSuggestionManager:mock_js_suggestion_manager_ - passwordsUiDelegate:mock_ui_delegate_]); + passwordsUiDelegate:mock_ui_delegate_]; @autoreleasepool { - accessory_view_controller_.reset([[FormInputAccessoryViewController alloc] + accessory_view_controller_ = [[FormInputAccessoryViewController alloc] initWithWebState:test_web_state_.get() - providers:@[ agent_ ]]); + providers:@[ agent_ ]]; } } @@ -287,11 +290,11 @@ protected: // Returns the current generation agent. - PasswordGenerationAgent* agent() { return agent_.get(); } + PasswordGenerationAgent* agent() { return agent_; } // Returns the current accessory view controller. FormInputAccessoryViewController* accessory_controller() { - return accessory_view_controller_.get(); + return accessory_view_controller_; } private: @@ -299,20 +302,19 @@ std::unique_ptr<web::TestWebState> test_web_state_; // Mock for JsSuggestionManager; - base::scoped_nsobject<id> mock_js_suggestion_manager_; + id mock_js_suggestion_manager_; // Mock for JsPasswordManager. - base::scoped_nsobject<id> mock_js_password_manager_; + id mock_js_password_manager_; // Mock for the UI delegate. - base::scoped_nsobject<MockPasswordsUiDelegate> mock_ui_delegate_; + MockPasswordsUiDelegate* mock_ui_delegate_; // Controller that shows custom input accessory views. - base::scoped_nsobject<FormInputAccessoryViewController> - accessory_view_controller_; + FormInputAccessoryViewController* accessory_view_controller_; // The current generation agent. - base::scoped_nsobject<PasswordGenerationAgent> agent_; + PasswordGenerationAgent* agent_; }; // Tests that local heuristics skip forms with GAIA realm. @@ -482,7 +484,7 @@ NSString* password = @"abc"; [[[mock_js_password_manager() stub] andDo:^(NSInvocation* invocation) { - void (^completion_handler)(BOOL); + __unsafe_unretained void (^completion_handler)(BOOL); [invocation getArgument:&completion_handler atIndex:4]; completion_handler(YES); }] fillPasswordForm:kAccountCreationFormName
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn index 9a17561..ebaf2c47 100644 --- a/ios/chrome/browser/ui/BUILD.gn +++ b/ios/chrome/browser/ui/BUILD.gn
@@ -44,7 +44,6 @@ deps = [ "//base", "//base:i18n", - "//ios/chrome/app/resources:terms_of_service_bundle", "//ios/chrome/browser", "//ios/chrome/browser/favicon", "//ios/chrome/browser/ui/commands", @@ -108,6 +107,49 @@ "resources/keyboard_button@2x~ipad.png", "resources/keyboard_button@3x.png", "resources/keyboard_button~ipad.png", + + # On iOS, the terms of service file need to be loaded from the application + # bundle, not from a datapack. As GetTermsOfServicePath() returns path to + # those files, they are added to //ios/chrome/browser/ui:resources. + "//components/resources/terms/terms_ar.html", + "//components/resources/terms/terms_bg.html", + "//components/resources/terms/terms_ca.html", + "//components/resources/terms/terms_cs.html", + "//components/resources/terms/terms_da.html", + "//components/resources/terms/terms_de.html", + "//components/resources/terms/terms_el.html", + "//components/resources/terms/terms_en-GB.html", + "//components/resources/terms/terms_en.html", + "//components/resources/terms/terms_es-419.html", + "//components/resources/terms/terms_es.html", + "//components/resources/terms/terms_fa.html", + "//components/resources/terms/terms_fi.html", + "//components/resources/terms/terms_fr.html", + "//components/resources/terms/terms_he.html", + "//components/resources/terms/terms_hi.html", + "//components/resources/terms/terms_hr.html", + "//components/resources/terms/terms_hu.html", + "//components/resources/terms/terms_id.html", + "//components/resources/terms/terms_it.html", + "//components/resources/terms/terms_ja.html", + "//components/resources/terms/terms_ko.html", + "//components/resources/terms/terms_lt.html", + "//components/resources/terms/terms_nb.html", + "//components/resources/terms/terms_nl.html", + "//components/resources/terms/terms_pl.html", + "//components/resources/terms/terms_pt-BR.html", + "//components/resources/terms/terms_pt-PT.html", + "//components/resources/terms/terms_ro.html", + "//components/resources/terms/terms_ru.html", + "//components/resources/terms/terms_sk.html", + "//components/resources/terms/terms_sr.html", + "//components/resources/terms/terms_sv.html", + "//components/resources/terms/terms_th.html", + "//components/resources/terms/terms_tr.html", + "//components/resources/terms/terms_uk.html", + "//components/resources/terms/terms_vi.html", + "//components/resources/terms/terms_zh-CN.html", + "//components/resources/terms/terms_zh-TW.html", ] outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}",
diff --git a/ios/chrome/test/earl_grey/resources/Chrome.entitlements b/ios/chrome/test/earl_grey/resources/Chrome.entitlements new file mode 100644 index 0000000..682f4cb --- /dev/null +++ b/ios/chrome/test/earl_grey/resources/Chrome.entitlements
@@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>application-identifier</key> + <string>$(AppIdentifierPrefix)$(CFBundleIdentifier)</string> +</dict> +</plist>
diff --git a/ios/web/public/test/test_web_state.h b/ios/web/public/test/test_web_state.h index c156c80..4b7f139 100644 --- a/ios/web/public/test/test_web_state.h +++ b/ios/web/public/test/test_web_state.h
@@ -9,6 +9,7 @@ #include <string> +#include "base/observer_list.h" #include "base/strings/string16.h" #include "ios/web/public/web_state/url_verification_constants.h" #include "ios/web/public/web_state/web_state.h" @@ -57,8 +58,11 @@ CRWWebViewProxyType GetWebViewProxy() const override; bool IsShowingWebInterstitial() const override; WebInterstitial* GetWebInterstitial() const override; - void AddObserver(WebStateObserver* observer) override {} - void RemoveObserver(WebStateObserver* observer) override {} + + void AddObserver(WebStateObserver* observer) override; + + void RemoveObserver(WebStateObserver* observer) override; + void AddPolicyDecider(WebStatePolicyDecider* decider) override {} void RemovePolicyDecider(WebStatePolicyDecider* decider) override {} int DownloadImage(const GURL& url, @@ -84,6 +88,9 @@ bool content_is_html_; std::string mime_type_; std::string content_language_; + + // A list of observers notified when page state changes. Weak references. + base::ObserverList<WebStateObserver, true> observers_; }; } // namespace web
diff --git a/ios/web/public/test/test_web_state.mm b/ios/web/public/test/test_web_state.mm index 3906434..3d35c1f7 100644 --- a/ios/web/public/test/test_web_state.mm +++ b/ios/web/public/test/test_web_state.mm
@@ -7,16 +7,30 @@ #include <stdint.h> #include "base/callback.h" +#include "ios/web/public/web_state/web_state_observer.h" namespace web { +void TestWebState::AddObserver(WebStateObserver* observer) { + observers_.AddObserver(observer); +} + +void TestWebState::RemoveObserver(WebStateObserver* observer) { + observers_.RemoveObserver(observer); +} + TestWebState::TestWebState() : web_usage_enabled_(false), is_loading_(false), trust_level_(kAbsolute), content_is_html_(true) {} -TestWebState::~TestWebState() = default; +TestWebState::~TestWebState() { + for (auto& observer : observers_) + observer.WebStateDestroyed(); + for (auto& observer : observers_) + observer.ResetWebState(); +}; WebStateDelegate* TestWebState::GetDelegate() { return nil;
diff --git a/ios/web/public/web_state/web_state_observer.h b/ios/web/public/web_state/web_state_observer.h index c48eed6..d0b76cd 100644 --- a/ios/web/public/web_state/web_state_observer.h +++ b/ios/web/public/web_state/web_state_observer.h
@@ -20,6 +20,7 @@ struct FaviconURL; struct LoadCommittedDetails; class WebState; +class TestWebState; class WebStateImpl; enum class PageLoadCompletionStatus : bool { SUCCESS = 0, FAILURE = 1 }; @@ -156,6 +157,7 @@ private: friend class WebStateImpl; + friend class TestWebState; // Stops observing the current web state. void ResetWebState();
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 198f007..988812a 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2162,3 +2162,8 @@ # Added 2016-11-30 crbug.com/669911 [ Win7 Win10 ] virtual/threaded/animations/zoom-responsive-transform-animation.html [ Pass Failure Timeout ] + +# Added 2016-12-06 +crbug.com/671618 http/tests/websocket/workers/worker-reload.html [ Pass Timeout ] +crbug.com/671618 virtual/mojo-loading/http/tests/websocket/workers/worker-reload.html [ Pass Timeout ] +crbug.com/671618 virtual/mojo-loading/http/tests/websocket/workers/worker-shutdown-race.html [ Pass Timeout ]
diff --git a/third_party/WebKit/LayoutTests/css3/motion-path/property-use-count-motion-rotation.html b/third_party/WebKit/LayoutTests/css3/motion-path/property-use-count-motion-rotation.html new file mode 100644 index 0000000..3c696f1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/css3/motion-path/property-use-count-motion-rotation.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<head> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +</head> + +<div id="target" class="p"></div> +<script> +test(function() { + assert_false(internals.isCSSPropertyUseCounted(document, "motion-rotation")); + + var styleElement = document.createElement('style'); + styleElement.textContent = ".p { motion-rotation: 0deg; }"; + document.head.appendChild(styleElement); + getComputedStyle(target); + + assert_true(internals.isCSSPropertyUseCounted(document, "motion-rotation")); + assert_false(internals.isCSSPropertyUseCounted(document, "offset-rotation")); + assert_false(internals.isCSSPropertyUseCounted(document, "offset-rotate")); +}); +</script>
diff --git a/third_party/WebKit/LayoutTests/css3/motion-path/property-use-count-offset-rotate.html b/third_party/WebKit/LayoutTests/css3/motion-path/property-use-count-offset-rotate.html new file mode 100644 index 0000000..34d93fe --- /dev/null +++ b/third_party/WebKit/LayoutTests/css3/motion-path/property-use-count-offset-rotate.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<head> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +</head> + +<div id="target" class="p"></div> +<script> +test(function() { + assert_false(internals.isCSSPropertyUseCounted(document, "offset-rotate")); + + var styleElement = document.createElement('style'); + styleElement.textContent = ".p { offset-rotate: 0deg; }"; + document.head.appendChild(styleElement); + getComputedStyle(target); + + assert_true(internals.isCSSPropertyUseCounted(document, "offset-rotate")); + assert_false(internals.isCSSPropertyUseCounted(document, "motion-rotation")); + assert_false(internals.isCSSPropertyUseCounted(document, "offset-rotation")); +}); +</script>
diff --git a/third_party/WebKit/LayoutTests/css3/motion-path/property-use-count-offset-rotation.html b/third_party/WebKit/LayoutTests/css3/motion-path/property-use-count-offset-rotation.html new file mode 100644 index 0000000..7deb34d7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/css3/motion-path/property-use-count-offset-rotation.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<head> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +</head> + +<div id="target" class="p"></div> +<script> +test(function() { + assert_false(internals.isCSSPropertyUseCounted(document, "offset-rotation")); + + var styleElement = document.createElement('style'); + styleElement.textContent = ".p { offset-rotation: 0deg; }"; + document.head.appendChild(styleElement); + getComputedStyle(target); + + assert_true(internals.isCSSPropertyUseCounted(document, "offset-rotation")); + assert_false(internals.isCSSPropertyUseCounted(document, "motion-rotation")); + assert_false(internals.isCSSPropertyUseCounted(document, "offset-rotate")); +}); +</script>
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn index 34a22e9e..5a9b9f7c 100644 --- a/third_party/WebKit/Source/core/BUILD.gn +++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1312,6 +1312,7 @@ "timing/PerformanceObserverTest.cpp", "timing/PerformanceTest.cpp", "workers/DedicatedWorkerTest.cpp", + "workers/MainThreadWorkletTest.cpp", "workers/WorkerThreadTest.cpp", "workers/WorkerThreadTestHelper.h", "xml/XPathFunctionsTest.cpp",
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.cpp b/third_party/WebKit/Source/core/frame/Deprecation.cpp index 43d8097..3369b6a 100644 --- a/third_party/WebKit/Source/core/frame/Deprecation.cpp +++ b/third_party/WebKit/Source/core/frame/Deprecation.cpp
@@ -10,7 +10,7 @@ #include "core/frame/FrameHost.h" #include "core/frame/LocalFrame.h" #include "core/inspector/ConsoleMessage.h" -#include "core/workers/WorkerGlobalScope.h" +#include "core/workers/WorkerOrWorkletGlobalScope.h" namespace { @@ -148,8 +148,8 @@ Deprecation::countDeprecation(*toDocument(context), feature); return; } - if (context->isWorkerGlobalScope()) - toWorkerGlobalScope(context)->countDeprecation(feature); + if (context->isWorkerOrWorkletGlobalScope()) + toWorkerOrWorkletGlobalScope(context)->countDeprecation(feature); } void Deprecation::countDeprecation(const Document& document,
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.cpp b/third_party/WebKit/Source/core/frame/UseCounter.cpp index e07d0d6..80e9609 100644 --- a/third_party/WebKit/Source/core/frame/UseCounter.cpp +++ b/third_party/WebKit/Source/core/frame/UseCounter.cpp
@@ -34,7 +34,7 @@ #include "core/frame/FrameHost.h" #include "core/frame/LocalFrame.h" #include "core/inspector/ConsoleMessage.h" -#include "core/workers/WorkerGlobalScope.h" +#include "core/workers/WorkerOrWorkletGlobalScope.h" #include "platform/Histogram.h" #include "platform/tracing/TraceEvent.h" @@ -45,7 +45,7 @@ } // Make sure update_use_counter_css.py was run which updates histograms.xml. -constexpr int kMaximumCSSSampleId = 547; +constexpr int kMaximumCSSSampleId = 548; } // namespace @@ -1050,9 +1050,7 @@ return 540; case CSSPropertyOffsetPath: return 541; - case CSSPropertyOffsetRotate: case CSSPropertyOffsetRotation: - // TODO(ericwilligers): Distinct use counter for CSSPropertyOffsetRotate. return 542; case CSSPropertyOffset: return 543; @@ -1064,6 +1062,8 @@ return 546; case CSSPropertyCaretColor: return 547; + case CSSPropertyOffsetRotate: + return 548; // 1. Add new features above this line (don't change the assigned numbers of // the existing items). // 2. Update kMaximumCSSSampleId with the new maximum value.
diff --git a/third_party/WebKit/Source/core/frame/csp/SourceListDirective.cpp b/third_party/WebKit/Source/core/frame/csp/SourceListDirective.cpp index 49ae246..32d8071 100644 --- a/third_party/WebKit/Source/core/frame/csp/SourceListDirective.cpp +++ b/third_party/WebKit/Source/core/frame/csp/SourceListDirective.cpp
@@ -618,6 +618,8 @@ bool allowDynamicOther = other[0]->m_allowDynamic; bool allowHashedAttributesOther = other[0]->m_allowHashedAttributes; bool isHashOrNoncePresentOther = other[0]->isHashOrNoncePresent(); + HashSet<String> noncesB = other[0]->m_nonces; + HashSet<CSPHashValue> hashesB = other[0]->m_hashes; for (size_t i = 1; i < other.size(); i++) { allowInlineOther = allowInlineOther && other[i]->m_allowInline; @@ -627,9 +629,14 @@ allowHashedAttributesOther && other[i]->m_allowHashedAttributes; isHashOrNoncePresentOther = isHashOrNoncePresentOther && other[i]->isHashOrNoncePresent(); + noncesB = other[i]->getIntersectNonces(noncesB); + hashesB = other[i]->getIntersectHashes(hashesB); normalizedB = other[i]->getIntersectCSPSources(normalizedB); } + if (!subsumesNoncesAndHashes(noncesB, hashesB)) + return false; + const ContentSecurityPolicy::DirectiveType type = ContentSecurityPolicy::getDirectiveType(m_directiveName); if (type == ContentSecurityPolicy::DirectiveType::ScriptSrc || @@ -649,6 +656,49 @@ return CSPSource::firstSubsumesSecond(normalizedA, normalizedB); } +bool SourceListDirective::subsumesNoncesAndHashes( + const HashSet<String>& nonces, + const HashSet<CSPHashValue> hashes) const { + for (const auto& nonce : nonces) { + if (!m_nonces.contains(nonce)) + return false; + } + for (const auto& hash : hashes) { + if (!m_hashes.contains(hash)) + return false; + } + + return true; +} + +HashSet<String> SourceListDirective::getIntersectNonces( + const HashSet<String>& other) const { + if (!m_nonces.size() || !other.size()) + return !m_nonces.size() ? m_nonces : other; + + HashSet<String> normalized; + for (const auto& nonce : m_nonces) { + if (other.contains(nonce)) + normalized.add(nonce); + } + + return normalized; +} + +HashSet<CSPHashValue> SourceListDirective::getIntersectHashes( + const HashSet<CSPHashValue>& other) const { + if (!m_hashes.size() || !other.size()) + return !m_hashes.size() ? m_hashes : other; + + HashSet<CSPHashValue> normalized; + for (const auto& hash : m_hashes) { + if (other.contains(hash)) + normalized.add(hash); + } + + return normalized; +} + HeapHashMap<String, Member<CSPSource>> SourceListDirective::getIntersectSchemesOnly( const HeapVector<Member<CSPSource>>& other) const {
diff --git a/third_party/WebKit/Source/core/frame/csp/SourceListDirective.h b/third_party/WebKit/Source/core/frame/csp/SourceListDirective.h index 6a3bbd5..cd01cb5 100644 --- a/third_party/WebKit/Source/core/frame/csp/SourceListDirective.h +++ b/third_party/WebKit/Source/core/frame/csp/SourceListDirective.h
@@ -56,6 +56,8 @@ FRIEND_TEST_ALL_PREFIXES(SourceListDirectiveTest, GetIntersectCSPSources); FRIEND_TEST_ALL_PREFIXES(SourceListDirectiveTest, GetIntersectCSPSourcesSchemes); + FRIEND_TEST_ALL_PREFIXES(SourceListDirectiveTest, GetIntersectNonces); + FRIEND_TEST_ALL_PREFIXES(SourceListDirectiveTest, GetIntersectHashes); FRIEND_TEST_ALL_PREFIXES(CSPDirectiveListTest, GetSourceVector); FRIEND_TEST_ALL_PREFIXES(CSPDirectiveListTest, OperativeDirectiveGivenType); @@ -97,10 +99,15 @@ CSPSource*); bool hasSourceMatchInList(const KURL&, ResourceRequest::RedirectStatus) const; + HashSet<String> getIntersectNonces(const HashSet<String>& other) const; + HashSet<CSPHashValue> getIntersectHashes( + const HashSet<CSPHashValue>& other) const; HeapVector<Member<CSPSource>> getIntersectCSPSources( const HeapVector<Member<CSPSource>>& other) const; HeapHashMap<String, Member<CSPSource>> getIntersectSchemesOnly( const HeapVector<Member<CSPSource>>& other) const; + bool subsumesNoncesAndHashes(const HashSet<String>& nonces, + const HashSet<CSPHashValue> hashes) const; Member<ContentSecurityPolicy> m_policy; HeapVector<Member<CSPSource>> m_list;
diff --git a/third_party/WebKit/Source/core/frame/csp/SourceListDirectiveTest.cpp b/third_party/WebKit/Source/core/frame/csp/SourceListDirectiveTest.cpp index 0e1fcc3..03f858d 100644 --- a/third_party/WebKit/Source/core/frame/csp/SourceListDirectiveTest.cpp +++ b/third_party/WebKit/Source/core/frame/csp/SourceListDirectiveTest.cpp
@@ -851,4 +851,204 @@ } } +TEST_F(SourceListDirectiveTest, GetIntersectNonces) { + SourceListDirective listA( + "script-src", + "http://example.com 'nonce-abc' 'nonce-xyz' 'nonce-' 'unsafe-inline'", + csp.get()); + struct TestCase { + String sources; + String expected; + } cases[] = { + {"http:", ""}, + {"http://example.com", ""}, + {"example.com", ""}, + {"'unsafe-inline'", ""}, + {"'nonce-abc'", "'nonce-abc'"}, + {"'nonce-xyz'", "'nonce-xyz'"}, + {"'nonce-123'", ""}, + {"'nonce-abc' 'nonce-xyz'", "'nonce-abc' 'nonce-xyz'"}, + {"'nonce-abc' 'nonce-xyz' 'nonce'", "'nonce-abc' 'nonce-xyz'"}, + {"'nonce-abc' 'nonce-123'", "'nonce-abc'"}, + {"'nonce-123' 'nonce-123'", ""}, + {"'nonce-123' 'nonce-abc'", "'nonce-abc'"}, + {"'nonce-123' 'nonce-xyz'", "'nonce-xyz'"}, + {"'nonce-123' 'nonce-xyx'", ""}, + }; + + for (const auto& test : cases) { + SourceListDirective listB("script-src", test.sources, csp.get()); + HashSet<String> normalized = listA.getIntersectNonces(listB.m_nonces); + + SourceListDirective expectedList("script-src", test.expected, csp.get()); + HashSet<String> expected = expectedList.m_nonces; + EXPECT_EQ(normalized.size(), expected.size()); + for (const auto& nonce : normalized) { + EXPECT_TRUE(expected.contains(nonce)); + } + } +} + +TEST_F(SourceListDirectiveTest, GetIntersectHashes) { + SourceListDirective listA( + "script-src", + "http://example.com 'sha256-abc123' 'sha384-' 'sha512-321cba' 'self'", + csp.get()); + struct TestCase { + String sources; + String expected; + } cases[] = { + {"http:", ""}, + {"http://example.com", ""}, + {"example.com", ""}, + {"'unsafe-inline'", ""}, + {"'sha384-abc'", ""}, + {"'sha384-'", ""}, + {"'sha256-abc123'", "'sha256-abc123'"}, + {"'sha256-abc123' 'sha384-'", "'sha256-abc123'"}, + {"'sha256-abc123' 'sha512-321cba'", "'sha512-321cba' 'sha256-abc123'"}, + {"'sha256-abc123' 'sha384-' 'sha512-321cba'", + "'sha256-abc123' 'sha512-321cba' "}, + {"'sha256-else' 'sha384-' 'sha512-321cba'", "'sha512-321cba' "}, + {"'hash-123'", ""}, + {"'sha256-123'", ""}, + }; + + for (const auto& test : cases) { + SourceListDirective listB("script-src", test.sources, csp.get()); + HashSet<CSPHashValue> normalized = listA.getIntersectHashes(listB.m_hashes); + + SourceListDirective expectedList("script-src", test.expected, csp.get()); + HashSet<CSPHashValue> expected = expectedList.m_hashes; + EXPECT_EQ(normalized.size(), expected.size()); + for (const auto& hash : normalized) { + EXPECT_TRUE(expected.contains(hash)); + } + } +} + +TEST_F(SourceListDirectiveTest, SubsumesNoncesAndHashes) { + struct TestCase { + bool isScriptSrc; + String sourcesA; + std::vector<String> sourcesB; + bool expected; + } cases[] = { + // Check nonces. + {true, + "http://example1.com/foo/ 'unsafe-inline' 'nonce-abc'", + {"'unsafe-inline'"}, + false}, + {true, + "http://example1.com/foo/ 'self' 'unsafe-inline' 'nonce-abc'", + {"'nonce-abc'"}, + true}, + {true, + "http://example1.com/foo/ 'self' 'unsafe-inline'", + {"'unsafe-inline' 'nonce-yay'", "'nonce-yay'"}, + false}, + {true, + "http://example1.com/foo/ 'self' 'nonce-yay'", + {"'unsafe-inline' 'nonce-yay'", "'nonce-yay'"}, + true}, + {true, + "http://example1.com/foo/ 'self' 'nonce-abc' 'nonce-yay'", + {"'unsafe-inline' https://example.test/"}, + false}, + {true, + "http://example1.com/foo/ 'self' 'nonce-abc' 'nonce-yay'", + {"'nonce-abc' https://example1.com/foo/"}, + true}, + {true, + "http://example1.com/foo/ 'self' 'unsafe-inline' 'nonce-yay' " + "'strict-dynamic'", + {"https://example.test/ 'nonce-yay'"}, + false}, + {false, + "http://example1.com/foo/ 'self' 'unsafe-inline' 'nonce-yay' " + "'strict-dynamic'", + {"'nonce-yay' https://example1.com/foo/"}, + true}, + // Check hashes. + {true, + "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321cba'", + {"http://example1.com/foo/page.html 'strict-dynamic'", + "https://example1.com/foo/ 'sha512-321cba'"}, + true}, + {true, + "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321cba'", + {"http://some-other.com/ 'strict-dynamic' 'sha512-321cba'", + "http://example1.com/foo/ 'unsafe-inline' 'sha512-321cba'"}, + true}, + {true, + "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321cba'", + {"http://example1.com/foo/ 'sha512-321abc' 'sha512-321cba'", + "http://example1.com/foo/ 'sha512-321abc' 'sha512-321cba'"}, + false}, + {true, + "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321cba'", + {"http://example1.com/foo/ 'unsafe-inline'", + "http://example1.com/foo/ 'sha512-321cba'"}, + true}, + {true, + "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321abc'", + {"http://example1.com/foo/ 'unsafe-inline' 'sha512-321abc'", + "http://example1.com/foo/ 'sha512-321abc'"}, + true}, + {true, + "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321abc'", + {"'unsafe-inline' 'sha512-321abc'", + "http://example1.com/foo/ 'sha512-321abc'"}, + true}, + // Nonces and hashes together. + {true, + "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321abc' " + "'nonce-abc'", + {"'unsafe-inline' 'sha512-321abc' 'self'", + "'unsafe-inline''sha512-321abc' https://example.test/"}, + true}, + {true, + "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321abc' " + "'nonce-abc'", + {"'unsafe-inline' 'sha512-321abc' 'self' 'nonce-abc'", + "'sha512-321abc' https://example.test/"}, + true}, + {true, + "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321abc' " + "'nonce-abc'", + {"'unsafe-inline' 'sha512-321abc' 'self'", + " 'sha512-321abc' https://example.test/ 'nonce-abc'"}, + true}, + {true, + "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321abc' " + "'nonce-abc'", + {"'unsafe-inline' 'sha512-321abc' 'self' 'nonce-xyz'", + "unsafe-inline' 'sha512-321abc' https://example.test/ 'nonce-xyz'"}, + false}, + {true, + "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321abc' " + "'nonce-abc'", + {"'unsafe-inline' 'sha512-321abc' 'self' 'sha512-xyz'", + "unsafe-inline' 'sha512-321abc' https://example.test/ 'sha512-xyz'"}, + false}, + + }; + + for (const auto& test : cases) { + SourceListDirective A(test.isScriptSrc ? "script-src" : "style-src", + test.sourcesA, csp.get()); + ContentSecurityPolicy* cspB = + SetUpWithOrigin("https://another.test/image.png"); + + HeapVector<Member<SourceListDirective>> vectorB; + for (const auto& sources : test.sourcesB) { + SourceListDirective* member = new SourceListDirective( + test.isScriptSrc ? "script-src" : "style-src", sources, cspB); + vectorB.append(member); + } + + EXPECT_EQ(A.subsumes(vectorB), test.expected); + } +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.cpp b/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.cpp index f017b2f0..95957ef3b 100644 --- a/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.cpp +++ b/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.cpp
@@ -25,17 +25,19 @@ MainThreadWorkletGlobalScope::~MainThreadWorkletGlobalScope() {} void MainThreadWorkletGlobalScope::countFeature(UseCounter::Feature feature) { - // TODO(nhiroki): Support UseCounter for main thread worklets. A parent - // document is on the same thread, so just record API use in the document's - // UseCounter (https://crbug.com/667357). + DCHECK(isMainThread()); + // A parent document is on the same thread, so just record API use in the + // document's UseCounter. + UseCounter::count(frame(), feature); } void MainThreadWorkletGlobalScope::countDeprecation( UseCounter::Feature feature) { + DCHECK(isMainThread()); + // A parent document is on the same thread, so just record API use in the + // document's UseCounter. addDeprecationMessage(feature); - // TODO(nhiroki): Support UseCounter for main thread worklets. A parent - // document is on the same thread, so just record API use in the document's - // UseCounter (https://crbug.com/667357). + Deprecation::countDeprecation(frame(), feature); } WorkerThread* MainThreadWorkletGlobalScope::thread() const {
diff --git a/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.h b/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.h index 9c9e3e96..90505f6 100644 --- a/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.h +++ b/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.h
@@ -20,7 +20,14 @@ class CORE_EXPORT MainThreadWorkletGlobalScope : public WorkletGlobalScope, public WorkletGlobalScopeProxy, public DOMWindowProperty { + USING_GARBAGE_COLLECTED_MIXIN(MainThreadWorkletGlobalScope); + public: + MainThreadWorkletGlobalScope(LocalFrame*, + const KURL&, + const String& userAgent, + PassRefPtr<SecurityOrigin>, + v8::Isolate*); ~MainThreadWorkletGlobalScope() override; bool isMainThreadWorkletGlobalScope() const final { return true; } @@ -40,13 +47,6 @@ WorkletGlobalScope::trace(visitor); DOMWindowProperty::trace(visitor); } - - protected: - MainThreadWorkletGlobalScope(LocalFrame*, - const KURL&, - const String& userAgent, - PassRefPtr<SecurityOrigin>, - v8::Isolate*); }; DEFINE_TYPE_CASTS(MainThreadWorkletGlobalScope,
diff --git a/third_party/WebKit/Source/core/workers/MainThreadWorkletTest.cpp b/third_party/WebKit/Source/core/workers/MainThreadWorkletTest.cpp new file mode 100644 index 0000000..c5629a5 --- /dev/null +++ b/third_party/WebKit/Source/core/workers/MainThreadWorkletTest.cpp
@@ -0,0 +1,54 @@ +// 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 "core/frame/UseCounter.h" +#include "core/testing/DummyPageHolder.h" +#include "core/workers/MainThreadWorkletGlobalScope.h" +#include "platform/weborigin/SecurityOrigin.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace blink { + +class MainThreadWorkletTest : public ::testing::Test { + public: + void SetUp() override { + KURL url(ParsedURLString, "https://example.com/"); + m_page = DummyPageHolder::create(); + m_securityOrigin = SecurityOrigin::create(url); + m_globalScope = new MainThreadWorkletGlobalScope( + &m_page->frame(), url, "fake user agent", m_securityOrigin.get(), + toIsolate(m_page->frame().document())); + } + + void TearDown() override { m_globalScope->terminateWorkletGlobalScope(); } + + protected: + RefPtr<SecurityOrigin> m_securityOrigin; + std::unique_ptr<DummyPageHolder> m_page; + Persistent<MainThreadWorkletGlobalScope> m_globalScope; +}; + +TEST_F(MainThreadWorkletTest, UseCounter) { + Document& document = *m_page->frame().document(); + + // This feature is randomly selected. + const UseCounter::Feature feature1 = UseCounter::Feature::RequestFileSystem; + + // API use on the MainThreadWorkletGlobalScope should be recorded in + // UseCounter on the Document. + EXPECT_FALSE(UseCounter::isCounted(document, feature1)); + UseCounter::count(m_globalScope, feature1); + EXPECT_TRUE(UseCounter::isCounted(document, feature1)); + + // This feature is randomly selected from Deprecation::deprecationMessage(). + const UseCounter::Feature feature2 = UseCounter::Feature::PrefixedStorageInfo; + + // Deprecated API use on the MainThreadWorkletGlobalScope should be recorded + // in UseCounter on the Document. + EXPECT_FALSE(UseCounter::isCounted(document, feature2)); + Deprecation::countDeprecation(m_globalScope, feature2); + EXPECT_TRUE(UseCounter::isCounted(document, feature2)); +} + +} // namespace blink
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 35be8bcd..a667b94 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -94133,6 +94133,8 @@ <int value="544" label="offset-anchor"/> <int value="545" label="offset-position"/> <int value="546" label="text-decoration-skip"/> + <int value="547" label="caret-color"/> + <int value="548" label="offset-rotate"/> </enum> <enum name="MappedEditingCommands" type="int">
diff --git a/tools/metrics/histograms/update_use_counter_css.py b/tools/metrics/histograms/update_use_counter_css.py index a598439..a4dd286 100755 --- a/tools/metrics/histograms/update_use_counter_css.py +++ b/tools/metrics/histograms/update_use_counter_css.py
@@ -36,19 +36,23 @@ with open(path_util.GetInputFile(filename)) as f: content = f.readlines() - # Looking for a line like "case CSSPropertyGrid: return 453;". + # Looking for a pair of lines like "case CSSPropertyGrid:\n return 453;". ENUM_REGEX = re.compile(r"""CSSProperty(.*): # capture the enum name \s*return\s* ([0-9]+) # capture the id """, re.VERBOSE) properties = {} + previous_line = '' for line in content: - enum_match = ENUM_REGEX.search(line) + enum_match = ENUM_REGEX.search(previous_line + '\n' + line) if enum_match: enum_name = enum_match.group(1) property_id = int(enum_match.group(2)) properties[property_id] = EnumToCssProperty(enum_name) + previous_line = '' + else: + previous_line = line return properties
diff --git a/tools/perf/page_sets/data/system_health_desktop.json b/tools/perf/page_sets/data/system_health_desktop.json index 76d50bd..b6640c6 100644 --- a/tools/perf/page_sets/data/system_health_desktop.json +++ b/tools/perf/page_sets/data/system_health_desktop.json
@@ -112,7 +112,10 @@ ], "system_health_desktop_036.wpr": [ "browse:media:tumblr" + ], + "system_health_desktop_037.wpr": [ + "browse:search:google" ] }, "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating." -} +} \ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_desktop_037.wpr.sha1 b/tools/perf/page_sets/data/system_health_desktop_037.wpr.sha1 new file mode 100644 index 0000000..c762889e --- /dev/null +++ b/tools/perf/page_sets/data/system_health_desktop_037.wpr.sha1
@@ -0,0 +1 @@ +f2a5ba6c89cbcf3ea63bfe58c022c36bf9cbba16 \ No newline at end of file
diff --git a/tools/perf/page_sets/system_health/browsing_stories.py b/tools/perf/page_sets/system_health/browsing_stories.py index 10f97613..27ce50e 100644 --- a/tools/perf/page_sets/system_health/browsing_stories.py +++ b/tools/perf/page_sets/system_health/browsing_stories.py
@@ -234,6 +234,62 @@ ############################################################################## +# Search browsing stories. +############################################################################## + + +class GoogleDesktopStory(_NewsBrowsingStory): + """ + A typical google search story: + _ Start at https://www.google.com/search?q=flower + _ Click on the wikipedia link & navigate to + https://en.wikipedia.org/wiki/Flower + _ Scroll down the wikipedia page about flower. + _ Back to the search main page. + _ Refine the search query to 'flower delivery'. + _ Scroll down the page. + _ Click the next page result of 'flower delivery'. + _ Scroll the search page. + + """ + NAME = 'browse:search:google' + URL = 'https://www.google.com/search?q=flower' + _SEARCH_BOX_SELECTOR = 'input[aria-label="Search"]' + _SEARCH_PAGE_2_SELECTOR = 'a[aria-label=\'Page 2\']' + SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY + + def _DidLoadDocument(self, action_runner): + # Click on flower Wikipedia link. + action_runner.Wait(2) + action_runner.ClickElement(text='Flower - Wikipedia') + action_runner.WaitForNavigate() + + # Scroll the flower Wikipedia page, then navigate back. + action_runner.Wait(2) + action_runner.ScrollPage() + action_runner.Wait(2) + action_runner.NavigateBack() + + # Click on the search box. + action_runner.WaitForElement(selector=self._SEARCH_BOX_SELECTOR) + action_runner.ClickElement(selector=self._SEARCH_BOX_SELECTOR) + action_runner.Wait(2) + + # Submit search query. + action_runner.EnterText(' delivery') + action_runner.Wait(0.5) + action_runner.PressKey('Return') + + # Scroll down & click next search result page. + action_runner.Wait(2) + action_runner.ScrollPageToElement(selector=self._SEARCH_PAGE_2_SELECTOR) + action_runner.Wait(2) + action_runner.ClickElement(selector=self._SEARCH_PAGE_2_SELECTOR) + action_runner.Wait(2) + action_runner.ScrollPage() + + +############################################################################## # Media browsing stories. ##############################################################################