diff --git a/BUILD.gn b/BUILD.gn index 533f7c1..d24c2da 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -682,6 +682,7 @@ "//testing/libfuzzer/fuzzers", "//testing/libfuzzer/tests:libfuzzer_tests", "//third_party/icu/fuzzers", + "//third_party/qcms:fuzzers", ] # TODO(miu): Remove this dependency once the build configuration in
diff --git a/DEPS b/DEPS index 32714fc4..f4a9f797 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': '2e896f6f6039add01a0d1d5efe6d5efe942c38a1', + 'v8_revision': 'fe9bb7e6e251159852770160cfb21dad3cf03523', # 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. @@ -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': '41bda73617edc29dbca3eda9b97a7b33f665c393', + 'catapult_revision': '4709b3a00e515aaac4e58b904dfbf1622c7a340a', # 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/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java index ead68bc..5a5d768 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -115,6 +115,7 @@ private float mUrlFocusChangePercent; private boolean mDisableUrlFocusChangeAnimations; + private boolean mIsMovingNewTabPageView; /** Flag used to request some layout changes after the next layout pass is completed. */ private boolean mTileCountChanged; @@ -190,7 +191,7 @@ // was dismissed, avoid also manipulating its vertical offset in our scroll handling // at the same time. The onScrolled() method is called when an item is dismissed and // the item at the top of the viewport is repositioned. - if (holder.itemView == mNewTabPageLayout) setUrlFocusAnimationsDisabled(true); + if (holder.itemView == mNewTabPageLayout) mIsMovingNewTabPageView = true; // Cancel any pending scroll update handling, a new one will be scheduled in // onAnimationFinished(). @@ -210,7 +211,7 @@ // from here, as the RecyclerView will animate multiple items when one is dismissed, // and some will "finish" synchronously if they are already in the correct place, // before other moves have even been scheduled. - if (viewHolder.itemView == mNewTabPageLayout) setUrlFocusAnimationsDisabled(false); + if (viewHolder.itemView == mNewTabPageLayout) mIsMovingNewTabPageView = false; mRecyclerView.removeCallbacks(mUpdateSearchBoxOnScrollRunnable); mRecyclerView.post(mUpdateSearchBoxOnScrollRunnable); } @@ -401,7 +402,7 @@ } private void updateSearchBoxOnScroll() { - if (mDisableUrlFocusChangeAnimations) return; + if (mDisableUrlFocusChangeAnimations || mIsMovingNewTabPageView) return; // When the page changes (tab switching or new page loading), it is possible that events // (e.g. delayed RecyclerView change notifications) trigger calls to these methods after @@ -632,7 +633,10 @@ } private void onUrlFocusAnimationChanged() { - if (mDisableUrlFocusChangeAnimations || FeatureUtilities.isChromeHomeEnabled()) return; + if (mDisableUrlFocusChangeAnimations || FeatureUtilities.isChromeHomeEnabled() + || mIsMovingNewTabPageView) { + return; + } // Translate so that the search box is at the top, but only upwards. float percent = mSearchProviderHasLogo ? mUrlFocusChangePercent : 0;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java index 2dad1b2..a5dc53af 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
@@ -205,14 +205,15 @@ // from moving later. setDefaultFaviconOnView(); try { + long faviconFetchStartTimeMs = SystemClock.elapsedRealtime(); URI pageUrl = new URI(mArticle.mUrl); if (!article.isArticle() || !SnippetsConfig.isFaviconsFromNewServerEnabled()) { // The old code path. Remove when the experiment is successful. // Currently, we have to use this for non-articles, due to privacy. - fetchFaviconFromLocalCache(pageUrl, true); + fetchFaviconFromLocalCache(pageUrl, true, faviconFetchStartTimeMs); } else { // The new code path. - fetchFaviconFromLocalCacheOrGoogleServer(); + fetchFaviconFromLocalCacheOrGoogleServer(faviconFetchStartTimeMs); } } catch (URISyntaxException e) { // Do nothing, stick to the default favicon. @@ -402,27 +403,52 @@ transitionDrawable.startTransition(FADE_IN_ANIMATION_TIME_MS); } - private void fetchFaviconFromLocalCacheOrGoogleServer() { + private void fetchFaviconFromLocalCacheOrGoogleServer(final long faviconFetchStartTimeMs) { // Set the desired size to 0 to specify we do not want to resize in c++, we'll resize here. mUiDelegate.getSuggestionsSource().fetchSuggestionFavicon(mArticle, PUBLISHER_FAVICON_MINIMUM_SIZE_PX, /* desiredSizePx */ 0, new Callback<Bitmap>() { @Override public void onResult(Bitmap image) { + recordFaviconFetchTime(faviconFetchStartTimeMs); if (image == null) return; setFaviconOnView(image); } }); } - private void fetchFaviconFromLocalCache(final URI snippetUri, final boolean fallbackToService) { + private void recordFaviconFetchTime(long faviconFetchStartTimeMs) { + RecordHistogram.recordMediumTimesHistogram( + "NewTabPage.ContentSuggestions.ArticleFaviconFetchTime", + SystemClock.elapsedRealtime() - faviconFetchStartTimeMs, TimeUnit.MILLISECONDS); + } + + private void recordFaviconFetchResult( + @FaviconFetchResult int result, long faviconFetchStartTimeMs) { + // Record the histogram for articles only to have a fair comparision. + if (!mArticle.isArticle()) return; + RecordHistogram.recordEnumeratedHistogram( + "NewTabPage.ContentSuggestions.ArticleFaviconFetchResult", result, + FaviconFetchResult.COUNT); + recordFaviconFetchTime(faviconFetchStartTimeMs); + } + + private void fetchFaviconFromLocalCache(final URI snippetUri, final boolean fallbackToService, + final long faviconFetchStartTimeMs) { mUiDelegate.getLocalFaviconImageForURL( getSnippetDomain(snippetUri), mPublisherFaviconSizePx, new FaviconImageCallback() { @Override public void onFaviconAvailable(Bitmap image, String iconUrl) { if (image != null) { setFaviconOnView(image); + recordFaviconFetchResult(fallbackToService + ? FaviconFetchResult.SUCCESS_CACHED + : FaviconFetchResult.SUCCESS_FETCHED, + faviconFetchStartTimeMs); } else if (fallbackToService) { - fetchFaviconFromService(snippetUri); + if (!fetchFaviconFromService(snippetUri, faviconFetchStartTimeMs)) { + recordFaviconFetchResult( + FaviconFetchResult.FAILURE, faviconFetchStartTimeMs); + } } // Else do nothing, we already have the placeholder set. } @@ -431,10 +457,11 @@ // TODO(crbug.com/635567): Fix this properly. @SuppressLint("DefaultLocale") - private void fetchFaviconFromService(final URI snippetUri) { - if (!mUseFaviconService) return; + private boolean fetchFaviconFromService( + final URI snippetUri, final long faviconFetchStartTimeMs) { + if (!mUseFaviconService) return false; int sizePx = getFaviconServiceSupportedSize(); - if (sizePx == 0) return; + if (sizePx == 0) return false; // Replace the default icon by another one from the service when it is fetched. mUiDelegate.ensureIconIsAvailable( @@ -443,11 +470,17 @@ /*useLargeIcon=*/false, /*isTemporary=*/true, new IconAvailabilityCallback() { @Override public void onIconAvailabilityChecked(boolean newlyAvailable) { - if (!newlyAvailable) return; + if (!newlyAvailable) { + recordFaviconFetchResult( + FaviconFetchResult.FAILURE, faviconFetchStartTimeMs); + return; + } // The download succeeded, the favicon is in the cache; fetch it. - fetchFaviconFromLocalCache(snippetUri, /*fallbackToService=*/false); + fetchFaviconFromLocalCache( + snippetUri, /*fallbackToService=*/false, faviconFetchStartTimeMs); } }); + return true; } private int getFaviconServiceSupportedSize() {
diff --git a/chrome/app/nibs/OWNERS b/chrome/app/nibs/OWNERS index f40e0c9..5a19c18 100644 --- a/chrome/app/nibs/OWNERS +++ b/chrome/app/nibs/OWNERS
@@ -1 +1,2 @@ +set noparent file://chrome/browser/ui/cocoa/OWNERS
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 97f28975..ab942d6 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -3483,6 +3483,11 @@ "repost_form_warning_controller.h", "search/local_ntp_source.cc", "search/local_ntp_source.h", + "search/one_google_bar/one_google_bar_data.cc", + "search/one_google_bar/one_google_bar_data.h", + "search/one_google_bar/one_google_bar_fetcher.h", + "search/one_google_bar/one_google_bar_fetcher_impl.cc", + "search/one_google_bar/one_google_bar_fetcher_impl.h", "signin/signin_promo.cc", "signin/signin_promo.h", "signin/signin_ui_util.cc",
diff --git a/chrome/browser/android/vr_shell/vr_gl_thread.cc b/chrome/browser/android/vr_shell/vr_gl_thread.cc index e5555f6..0697b1d 100644 --- a/chrome/browser/android/vr_shell/vr_gl_thread.cc +++ b/chrome/browser/android/vr_shell/vr_gl_thread.cc
@@ -44,6 +44,8 @@ void VrGLThread::CleanUp() { vr_shell_gl_.reset(); + scene_manager_.reset(); + scene_.reset(); } } // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.cc b/chrome/browser/android/vr_shell/vr_shell_gl.cc index 5736237..81397edd8 100644 --- a/chrome/browser/android/vr_shell/vr_shell_gl.cc +++ b/chrome/browser/android/vr_shell/vr_shell_gl.cc
@@ -727,25 +727,37 @@ // Once the user starts scrolling send all the scroll events to this // element until the scrolling stops. case WebInputEvent::kGestureScrollBegin: - current_scroll_target = input_target; - if (current_scroll_target != InputTarget::NONE) { - SendGesture(current_scroll_target, std::move(movableGesture)); + current_scroll_target_ = input_target; + if (current_scroll_target_ != InputTarget::NONE) { + SendGesture(current_scroll_target_, std::move(movableGesture)); } break; case WebInputEvent::kGestureScrollEnd: - if (current_scroll_target != InputTarget::NONE) { - SendGesture(current_scroll_target, std::move(movableGesture)); + if (current_scroll_target_ != InputTarget::NONE) { + SendGesture(current_scroll_target_, std::move(movableGesture)); } - current_scroll_target = InputTarget::NONE; + current_fling_target_ = current_scroll_target_; + current_scroll_target_ = InputTarget::NONE; break; case WebInputEvent::kGestureScrollUpdate: - case WebInputEvent::kGestureFlingCancel: + if (current_scroll_target_ != InputTarget::NONE) { + SendGesture(current_scroll_target_, std::move(movableGesture)); + } + break; case WebInputEvent::kGestureFlingStart: - if (current_scroll_target != InputTarget::NONE) { - SendGesture(current_scroll_target, std::move(movableGesture)); + if (current_fling_target_ != InputTarget::NONE) { + SendGesture(current_fling_target_, std::move(movableGesture)); + } + current_fling_target_ = InputTarget::NONE; + break; + case WebInputEvent::kGestureFlingCancel: + current_fling_target_ = InputTarget::NONE; + if (input_target != InputTarget::NONE) { + SendGesture(input_target, std::move(movableGesture)); } break; case WebInputEvent::kGestureTapDown: + current_fling_target_ = InputTarget::NONE; if (input_target != InputTarget::NONE) { SendGesture(input_target, std::move(movableGesture)); }
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.h b/chrome/browser/android/vr_shell/vr_shell_gl.h index 15606b999..2d14b66 100644 --- a/chrome/browser/android/vr_shell/vr_shell_gl.h +++ b/chrome/browser/android/vr_shell/vr_shell_gl.h
@@ -200,7 +200,8 @@ gfx::Point3F target_point_; const UiElement* target_element_ = nullptr; InputTarget current_input_target_ = InputTarget::NONE; - InputTarget current_scroll_target = InputTarget::NONE; + InputTarget current_scroll_target_ = InputTarget::NONE; + InputTarget current_fling_target_ = InputTarget::NONE; int ui_tex_css_width_ = 0; int ui_tex_css_height_ = 0; int content_tex_css_width_ = 0;
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc index 4074995..155f9bf 100644 --- a/chrome/browser/autofill/autofill_interactive_uitest.cc +++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -764,10 +764,12 @@ // Test that an input field is not rendered with the yellow autofilled // background color when choosing an option from the datalist suggestion list. -#if defined(OS_MACOSX) || defined(OS_CHROMEOS) +#if defined(OS_MACOSX) || defined(OS_CHROMEOS) || defined(OS_WIN) || \ + defined(OS_LINUX) // Flakily triggers and assert on Mac; flakily gets empty string instead // of "Adam" on ChromeOS. // http://crbug.com/419868, http://crbug.com/595385. +// Flaky on Windows and Linux as well: http://crbug.com/595385 #define MAYBE_OnSelectOptionFromDatalist DISABLED_OnSelectOptionFromDatalist #else #define MAYBE_OnSelectOptionFromDatalist OnSelectOptionFromDatalist
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index e8c3638..ce20f98 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -35,6 +35,7 @@ #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/sys_info.h" +#include "base/task_scheduler/post_task.h" #include "base/threading/platform_thread.h" #include "base/time/default_tick_clock.h" #include "base/time/time.h" @@ -1706,7 +1707,8 @@ // Verify that the profile is not on a network share and if so prepare to show // notification to the user. if (NetworkProfileBubble::ShouldCheckNetworkProfile(profile_)) { - BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, + base::PostTaskWithTraits( + FROM_HERE, base::TaskTraits().MayBlock(), base::Bind(&NetworkProfileBubble::CheckNetworkProfile, profile_->GetPath())); }
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index 7179ba56..6f39cd9 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -121,13 +121,9 @@ "audioRepeatOneModeMultipleFileDrive"))); // Fails on official build. http://crbug.com/429294 -#if defined(DISABLE_SLOW_FILESAPP_TESTS) || defined(OFFICIAL_BUILD) -#define MAYBE_OpenImageFiles DISABLED_OpenImageFiles -#else -#define MAYBE_OpenImageFiles OpenImageFiles -#endif +// Flaky: http://crbug.com/711290 WRAPPED_INSTANTIATE_TEST_CASE_P( - MAYBE_OpenImageFiles, + DISABLED_OpenImageFiles, FileManagerBrowserTest, ::testing::Values(TestParameter(IN_GUEST_MODE, "imageOpenDownloads"), TestParameter(NOT_IN_GUEST_MODE, "imageOpenDownloads"),
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_data.cc b/chrome/browser/search/one_google_bar/one_google_bar_data.cc new file mode 100644 index 0000000..eac69e8 --- /dev/null +++ b/chrome/browser/search/one_google_bar/one_google_bar_data.cc
@@ -0,0 +1,14 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/search/one_google_bar/one_google_bar_data.h" + +OneGoogleBarData::OneGoogleBarData() = default; +OneGoogleBarData::OneGoogleBarData(const OneGoogleBarData&) = default; +OneGoogleBarData::OneGoogleBarData(OneGoogleBarData&&) = default; +OneGoogleBarData::~OneGoogleBarData() = default; + +OneGoogleBarData& OneGoogleBarData::operator=(const OneGoogleBarData&) = + default; +OneGoogleBarData& OneGoogleBarData::operator=(OneGoogleBarData&&) = default;
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_data.h b/chrome/browser/search/one_google_bar/one_google_bar_data.h new file mode 100644 index 0000000..caf3a27 --- /dev/null +++ b/chrome/browser/search/one_google_bar/one_google_bar_data.h
@@ -0,0 +1,32 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SEARCH_ONE_GOOGLE_BAR_ONE_GOOGLE_BAR_DATA_H_ +#define CHROME_BROWSER_SEARCH_ONE_GOOGLE_BAR_ONE_GOOGLE_BAR_DATA_H_ + +#include <string> + +// This struct contains all the data needed to inject a OneGoogleBar into a +// page. +struct OneGoogleBarData { + OneGoogleBarData(); + OneGoogleBarData(const OneGoogleBarData&); + OneGoogleBarData(OneGoogleBarData&&); + ~OneGoogleBarData(); + + OneGoogleBarData& operator=(const OneGoogleBarData&); + OneGoogleBarData& operator=(OneGoogleBarData&&); + + // The main HTML for the bar itself. + std::string bar_html; + + // "Page hooks" that need to be inserted at certain points in the page HTML. + std::string in_head_script; + std::string in_head_style; + std::string after_bar_script; + std::string end_of_body_html; + std::string end_of_body_script; +}; + +#endif // CHROME_BROWSER_SEARCH_ONE_GOOGLE_BAR_ONE_GOOGLE_BAR_DATA_H_
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_fetcher.h b/chrome/browser/search/one_google_bar/one_google_bar_fetcher.h new file mode 100644 index 0000000..4b42d421 --- /dev/null +++ b/chrome/browser/search/one_google_bar/one_google_bar_fetcher.h
@@ -0,0 +1,24 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SEARCH_ONE_GOOGLE_BAR_ONE_GOOGLE_BAR_FETCHER_H_ +#define CHROME_BROWSER_SEARCH_ONE_GOOGLE_BAR_ONE_GOOGLE_BAR_FETCHER_H_ + +#include "base/callback_forward.h" +#include "base/optional.h" + +struct OneGoogleBarData; + +// Interface for fetching OneGoogleBarData over the network. +class OneGoogleBarFetcher { + public: + using OneGoogleCallback = + base::OnceCallback<void(const base::Optional<OneGoogleBarData>&)>; + + // Initiates a fetch from the network. On completion (successful or not), the + // callback will be called with the result, which will be nullopt on failure. + virtual void Fetch(OneGoogleCallback callback) = 0; +}; + +#endif // CHROME_BROWSER_SEARCH_ONE_GOOGLE_BAR_ONE_GOOGLE_BAR_FETCHER_H_
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.cc b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.cc new file mode 100644 index 0000000..704f878 --- /dev/null +++ b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.cc
@@ -0,0 +1,374 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.h" + +#include <string> +#include <utility> + +#include "base/callback.h" +#include "base/command_line.h" +#include "base/json/json_writer.h" +#include "base/memory/ptr_util.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "base/values.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/search/one_google_bar/one_google_bar_data.h" +#include "chrome/common/chrome_content_client.h" +#include "components/google/core/browser/google_url_tracker.h" +#include "components/safe_json/safe_json_parser.h" +#include "components/signin/core/browser/access_token_fetcher.h" +#include "components/signin/core/browser/signin_manager.h" +#include "components/variations/net/variations_http_headers.h" +#include "google_apis/gaia/oauth2_token_service.h" +#include "google_apis/google_api_keys.h" +#include "net/base/load_flags.h" +#include "net/http/http_status_code.h" +#include "net/url_request/url_fetcher.h" +#include "net/url_request/url_fetcher_delegate.h" + +namespace { + +const char kApiUrl[] = "https://onegoogle-pa.googleapis.com/v1/getbar"; + +const char kApiKeyFormat[] = "?key=%s"; + +const char kApiScope[] = "https://www.googleapis.com/auth/onegoogle.readonly"; +const char kAuthorizationRequestHeaderFormat[] = "Bearer %s"; + +const char kResponsePreamble[] = ")]}'"; + +// This namespace contains helpers to extract SafeHtml-wrapped strings (see +// https://github.com/google/safe-html-types) from the response json. If there +// is ever a C++ version of the SafeHtml types, we should consider using that +// instead of these custom functions. +namespace safe_html { + +bool GetImpl(const base::DictionaryValue& dict, + const std::string& name, + const std::string& wrapped_field_name, + std::string* out) { + const base::DictionaryValue* value = nullptr; + if (!dict.GetDictionary(name, &value)) { + out->clear(); + return false; + } + + if (!value->GetString(wrapped_field_name, out)) { + out->clear(); + return false; + } + + return true; +} + +bool GetHtml(const base::DictionaryValue& dict, + const std::string& name, + std::string* out) { + return GetImpl(dict, name, "privateDoNotAccessOrElseSafeHtmlWrappedValue", + out); +} + +bool GetScript(const base::DictionaryValue& dict, + const std::string& name, + std::string* out) { + return GetImpl(dict, name, "privateDoNotAccessOrElseSafeScriptWrappedValue", + out); +} + +bool GetStyleSheet(const base::DictionaryValue& dict, + const std::string& name, + std::string* out) { + return GetImpl(dict, name, + "privateDoNotAccessOrElseSafeStyleSheetWrappedValue", out); +} + +} // namespace safe_html + +base::Optional<OneGoogleBarData> JsonToOGBData(const base::Value& value) { + const base::DictionaryValue* dict = nullptr; + if (!value.GetAsDictionary(&dict)) { + DLOG(WARNING) << "Parse error: top-level dictionary not found"; + return base::nullopt; + } + + const base::DictionaryValue* one_google_bar = nullptr; + if (!dict->GetDictionary("oneGoogleBar", &one_google_bar)) { + DLOG(WARNING) << "Parse error: no oneGoogleBar"; + return base::nullopt; + } + + OneGoogleBarData result; + + if (!safe_html::GetHtml(*one_google_bar, "html", &result.bar_html)) { + DLOG(WARNING) << "Parse error: no html"; + return base::nullopt; + } + + const base::DictionaryValue* page_hooks = nullptr; + if (!one_google_bar->GetDictionary("pageHooks", &page_hooks)) { + DLOG(WARNING) << "Parse error: no pageHooks"; + return base::nullopt; + } + + safe_html::GetScript(*page_hooks, "inHeadScript", &result.in_head_script); + safe_html::GetStyleSheet(*page_hooks, "inHeadStyle", &result.in_head_style); + safe_html::GetScript(*page_hooks, "afterBarScript", &result.after_bar_script); + safe_html::GetHtml(*page_hooks, "endOfBodyHtml", &result.end_of_body_html); + safe_html::GetScript(*page_hooks, "endOfBodyScript", + &result.end_of_body_script); + + return result; +} + +} // namespace + +class OneGoogleBarFetcherImpl::AuthenticatedURLFetcher + : public net::URLFetcherDelegate { + public: + using FetchDoneCallback = base::OnceCallback<void(const net::URLFetcher*)>; + + AuthenticatedURLFetcher(SigninManagerBase* signin_manager, + OAuth2TokenService* token_service, + net::URLRequestContextGetter* request_context, + const GURL& google_base_url, + FetchDoneCallback callback); + ~AuthenticatedURLFetcher() override = default; + + void Start(); + + private: + GURL GetApiUrl(bool use_oauth) const; + std::string GetRequestBody() const; + std::string GetExtraRequestHeaders(const GURL& url, + const std::string& access_token) const; + + void GotAccessToken(const GoogleServiceAuthError& error, + const std::string& access_token); + + // URLFetcherDelegate implementation. + void OnURLFetchComplete(const net::URLFetcher* source) override; + + SigninManagerBase* const signin_manager_; + OAuth2TokenService* const token_service_; + net::URLRequestContextGetter* const request_context_; + const GURL google_base_url_; + + FetchDoneCallback callback_; + + std::unique_ptr<AccessTokenFetcher> token_fetcher_; + + // The underlying URLFetcher which does the actual fetch. + std::unique_ptr<net::URLFetcher> url_fetcher_; +}; + +OneGoogleBarFetcherImpl::AuthenticatedURLFetcher::AuthenticatedURLFetcher( + SigninManagerBase* signin_manager, + OAuth2TokenService* token_service, + net::URLRequestContextGetter* request_context, + const GURL& google_base_url, + FetchDoneCallback callback) + : signin_manager_(signin_manager), + token_service_(token_service), + request_context_(request_context), + google_base_url_(google_base_url), + callback_(std::move(callback)) {} + +void OneGoogleBarFetcherImpl::AuthenticatedURLFetcher::Start() { + if (!signin_manager_->IsAuthenticated()) { + GotAccessToken(GoogleServiceAuthError::AuthErrorNone(), std::string()); + return; + } + OAuth2TokenService::ScopeSet scopes; + scopes.insert(kApiScope); + token_fetcher_ = base::MakeUnique<AccessTokenFetcher>( + "one_google", signin_manager_, token_service_, scopes, + base::BindOnce(&AuthenticatedURLFetcher::GotAccessToken, + base::Unretained(this))); +} + +GURL OneGoogleBarFetcherImpl::AuthenticatedURLFetcher::GetApiUrl( + bool use_oauth) const { + std::string api_url(kApiUrl); + // TODO(treib): Attach to feature instead of cmdline. + base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); + if (cmdline->HasSwitch("one-google-api-url")) + api_url = cmdline->GetSwitchValueASCII("one-google-api-url"); + // Append the API key only for unauthenticated requests. + if (!use_oauth) { + api_url += + base::StringPrintf(kApiKeyFormat, google_apis::GetAPIKey().c_str()); + } + + return GURL(api_url); +} + +std::string OneGoogleBarFetcherImpl::AuthenticatedURLFetcher::GetRequestBody() + const { + // TODO(treib): Attach to feature instead of cmdline. + base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); + if (cmdline->HasSwitch("one-google-bar-options")) + return cmdline->GetSwitchValueASCII("one-google-bar-options"); + + base::DictionaryValue dict; + dict.SetInteger("subproduct", 243); + dict.SetBoolean("enable_multilogin", true); + dict.SetString("user_agent", GetUserAgent()); + dict.SetString("accept_language", g_browser_process->GetApplicationLocale()); + dict.SetString("original_request_url", google_base_url_.spec()); + auto material_options_dict = base::MakeUnique<base::DictionaryValue>(); + material_options_dict->SetString("page_title", " "); + material_options_dict->SetBoolean("position_fixed", true); + material_options_dict->SetBoolean("disable_moving_userpanel_to_menu", true); + auto styling_options_dict = base::MakeUnique<base::DictionaryValue>(); + auto background_color_dict = base::MakeUnique<base::DictionaryValue>(); + auto alpha_dict = base::MakeUnique<base::DictionaryValue>(); + alpha_dict->SetInteger("value", 0); + background_color_dict->Set("alpha", std::move(alpha_dict)); + styling_options_dict->Set("background_color", + std::move(background_color_dict)); + material_options_dict->Set("styling_options", + std::move(styling_options_dict)); + dict.Set("material_options", std::move(material_options_dict)); + + std::string result; + base::JSONWriter::Write(dict, &result); + return result; +} + +std::string +OneGoogleBarFetcherImpl::AuthenticatedURLFetcher::GetExtraRequestHeaders( + const GURL& url, + const std::string& access_token) const { + net::HttpRequestHeaders headers; + headers.SetHeader("Content-Type", "application/json; charset=UTF-8"); + if (!access_token.empty()) { + headers.SetHeader("Authorization", + base::StringPrintf(kAuthorizationRequestHeaderFormat, + access_token.c_str())); + } + // Note: It's OK to pass |is_signed_in| false if it's unknown, as it does + // not affect transmission of experiments coming from the variations server. + variations::AppendVariationHeaders(url, + /*incognito=*/false, /*uma_enabled=*/false, + /*is_signed_in=*/false, &headers); + return headers.ToString(); +} + +void OneGoogleBarFetcherImpl::AuthenticatedURLFetcher::GotAccessToken( + const GoogleServiceAuthError& error, + const std::string& access_token) { + // Delete the token fetcher after we leave this method. + std::unique_ptr<AccessTokenFetcher> deleter(std::move(token_fetcher_)); + + bool use_oauth = !access_token.empty(); + GURL url = GetApiUrl(use_oauth); + url_fetcher_ = net::URLFetcher::Create(0, url, net::URLFetcher::POST, this); + url_fetcher_->SetRequestContext(request_context_); + + url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_AUTH_DATA | + net::LOAD_DO_NOT_SEND_COOKIES | + net::LOAD_DO_NOT_SAVE_COOKIES); + url_fetcher_->SetUploadData("application/json", GetRequestBody()); + url_fetcher_->SetExtraRequestHeaders( + GetExtraRequestHeaders(url, access_token)); + + url_fetcher_->Start(); +} + +void OneGoogleBarFetcherImpl::AuthenticatedURLFetcher::OnURLFetchComplete( + const net::URLFetcher* source) { + std::move(callback_).Run(source); +} + +OneGoogleBarFetcherImpl::OneGoogleBarFetcherImpl( + SigninManagerBase* signin_manager, + OAuth2TokenService* token_service, + net::URLRequestContextGetter* request_context, + GoogleURLTracker* google_url_tracker) + : signin_manager_(signin_manager), + token_service_(token_service), + request_context_(request_context), + google_url_tracker_(google_url_tracker), + weak_ptr_factory_(this) {} + +OneGoogleBarFetcherImpl::~OneGoogleBarFetcherImpl() = default; + +void OneGoogleBarFetcherImpl::Fetch(OneGoogleCallback callback) { + callbacks_.push_back(std::move(callback)); + IssueRequestIfNoneOngoing(); +} + +void OneGoogleBarFetcherImpl::IssueRequestIfNoneOngoing() { + // If there is an ongoing request, let it complete. + if (pending_request_.get()) + return; + + pending_request_ = base::MakeUnique<AuthenticatedURLFetcher>( + signin_manager_, token_service_, request_context_, + google_url_tracker_->google_url(), + base::BindOnce(&OneGoogleBarFetcherImpl::FetchDone, + base::Unretained(this))); + pending_request_->Start(); +} + +void OneGoogleBarFetcherImpl::FetchDone(const net::URLFetcher* source) { + // The fetcher will be deleted when the request is handled. + std::unique_ptr<AuthenticatedURLFetcher> deleter(std::move(pending_request_)); + + const net::URLRequestStatus& request_status = source->GetStatus(); + if (request_status.status() != net::URLRequestStatus::SUCCESS) { + // This represents network errors (i.e. the server did not provide a + // response). + DLOG(WARNING) << "Request failed with error: " << request_status.error() + << ": " << net::ErrorToString(request_status.error()); + Respond(base::nullopt); + return; + } + + const int response_code = source->GetResponseCode(); + if (response_code != net::HTTP_OK) { + DLOG(WARNING) << "Response code: " << response_code; + std::string response; + source->GetResponseAsString(&response); + DLOG(WARNING) << "Response: " << response; + Respond(base::nullopt); + return; + } + + std::string response; + bool success = source->GetResponseAsString(&response); + DCHECK(success); + + // The response may start with )]}'. Ignore this. + if (base::StartsWith(response, kResponsePreamble, + base::CompareCase::SENSITIVE)) { + response = response.substr(strlen(kResponsePreamble)); + } + + safe_json::SafeJsonParser::Parse( + response, + base::Bind(&OneGoogleBarFetcherImpl::JsonParsed, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&OneGoogleBarFetcherImpl::JsonParseFailed, + weak_ptr_factory_.GetWeakPtr())); +} + +void OneGoogleBarFetcherImpl::JsonParsed(std::unique_ptr<base::Value> value) { + Respond(JsonToOGBData(*value)); +} + +void OneGoogleBarFetcherImpl::JsonParseFailed(const std::string& message) { + DLOG(WARNING) << "Parsing JSON failed: " << message; + Respond(base::nullopt); +} + +void OneGoogleBarFetcherImpl::Respond( + const base::Optional<OneGoogleBarData>& data) { + for (auto& callback : callbacks_) { + std::move(callback).Run(data); + } + callbacks_.clear(); +}
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.h b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.h new file mode 100644 index 0000000..40538ef --- /dev/null +++ b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.h
@@ -0,0 +1,67 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SEARCH_ONE_GOOGLE_BAR_ONE_GOOGLE_BAR_FETCHER_IMPL_H_ +#define CHROME_BROWSER_SEARCH_ONE_GOOGLE_BAR_ONE_GOOGLE_BAR_FETCHER_IMPL_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/optional.h" +#include "chrome/browser/search/one_google_bar/one_google_bar_fetcher.h" + +class GoogleURLTracker; +class OAuth2TokenService; +class SigninManagerBase; + +namespace base { +class Value; +} + +namespace net { +class URLFetcher; +class URLRequestContextGetter; +} // namespace net + +struct OneGoogleBarData; + +class OneGoogleBarFetcherImpl : public OneGoogleBarFetcher { + public: + OneGoogleBarFetcherImpl(SigninManagerBase* signin_manager, + OAuth2TokenService* token_service, + net::URLRequestContextGetter* request_context, + GoogleURLTracker* google_url_tracker); + ~OneGoogleBarFetcherImpl(); + + void Fetch(OneGoogleCallback callback) override; + + private: + class AuthenticatedURLFetcher; + + void IssueRequestIfNoneOngoing(); + + void FetchDone(const net::URLFetcher* source); + + void JsonParsed(std::unique_ptr<base::Value> value); + void JsonParseFailed(const std::string& message); + + void Respond(const base::Optional<OneGoogleBarData>& data); + + SigninManagerBase* signin_manager_; + OAuth2TokenService* token_service_; + net::URLRequestContextGetter* request_context_; + GoogleURLTracker* google_url_tracker_; + + std::vector<OneGoogleCallback> callbacks_; + std::unique_ptr<AuthenticatedURLFetcher> pending_request_; + + base::WeakPtrFactory<OneGoogleBarFetcherImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(OneGoogleBarFetcherImpl); +}; + +#endif // CHROME_BROWSER_SEARCH_ONE_GOOGLE_BAR_ONE_GOOGLE_BAR_FETCHER_IMPL_H_
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl_unittest.cc b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl_unittest.cc new file mode 100644 index 0000000..7e05f845 --- /dev/null +++ b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl_unittest.cc
@@ -0,0 +1,291 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.h" + +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/memory/ref_counted.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/test/mock_callback.h" +#include "base/test/test_simple_task_runner.h" +#include "base/time/time.h" +#include "chrome/browser/search/one_google_bar/one_google_bar_data.h" +#include "components/google/core/browser/google_url_tracker.h" +#include "components/safe_json/testing_json_parser.h" +#include "components/signin/core/browser/account_tracker_service.h" +#include "components/signin/core/browser/fake_profile_oauth2_token_service.h" +#include "components/signin/core/browser/fake_signin_manager.h" +#include "components/signin/core/browser/test_signin_client.h" +#include "components/sync_preferences/testing_pref_service_syncable.h" +#include "google_apis/gaia/fake_oauth2_token_service_delegate.h" +#include "net/http/http_request_headers.h" +#include "net/http/http_status_code.h" +#include "net/url_request/test_url_fetcher_factory.h" +#include "net/url_request/url_request_status.h" +#include "net/url_request/url_request_test_util.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::_; +using testing::Eq; +using testing::IsEmpty; +using testing::SaveArg; +using testing::StartsWith; + +namespace { + +const char kMinimalValidResponse[] = R"json({"oneGoogleBar": { + "html": { "privateDoNotAccessOrElseSafeHtmlWrappedValue": "" }, + "pageHooks": {} +}})json"; + +// Required to instantiate a GoogleUrlTracker in UNIT_TEST_MODE. +class GoogleURLTrackerClientStub : public GoogleURLTrackerClient { + public: + GoogleURLTrackerClientStub() {} + ~GoogleURLTrackerClientStub() override {} + + bool IsBackgroundNetworkingEnabled() override { return true; } + PrefService* GetPrefs() override { return nullptr; } + net::URLRequestContextGetter* GetRequestContext() override { return nullptr; } + + private: + DISALLOW_COPY_AND_ASSIGN(GoogleURLTrackerClientStub); +}; + +} // namespace + +class OneGoogleBarFetcherImplTest : public testing::Test { + public: + OneGoogleBarFetcherImplTest() + : signin_client_(&pref_service_), + signin_manager_(&signin_client_, &account_tracker_), + task_runner_(new base::TestSimpleTaskRunner()), + request_context_getter_( + new net::TestURLRequestContextGetter(task_runner_)), + token_service_(base::MakeUnique<FakeOAuth2TokenServiceDelegate>( + request_context_getter_.get())), + google_url_tracker_(base::MakeUnique<GoogleURLTrackerClientStub>(), + GoogleURLTracker::UNIT_TEST_MODE), + one_google_bar_fetcher_(&signin_manager_, + &token_service_, + request_context_getter_.get(), + &google_url_tracker_) { + SigninManagerBase::RegisterProfilePrefs(pref_service_.registry()); + SigninManagerBase::RegisterPrefs(pref_service_.registry()); + } + + void SignIn() { + signin_manager_.SignIn("account"); + token_service_.GetDelegate()->UpdateCredentials("account", "refresh_token"); + } + + void IssueAccessToken() { + token_service_.IssueAllTokensForAccount( + "account", "access_token", + base::Time::Now() + base::TimeDelta::FromHours(1)); + } + + void IssueAccessTokenError() { + token_service_.IssueErrorForAllPendingRequestsForAccount( + "account", + GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE)); + } + + net::TestURLFetcher* GetRunningURLFetcher() { + // All created URLFetchers have ID 0 by default. + net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0); + DCHECK(url_fetcher); + return url_fetcher; + } + + void RespondWithData(const std::string& data) { + net::TestURLFetcher* url_fetcher = GetRunningURLFetcher(); + url_fetcher->set_status(net::URLRequestStatus()); + url_fetcher->set_response_code(net::HTTP_OK); + url_fetcher->SetResponseString(data); + url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); + // SafeJsonParser is asynchronous. + base::RunLoop().RunUntilIdle(); + } + + OneGoogleBarFetcherImpl* one_google_bar_fetcher() { + return &one_google_bar_fetcher_; + } + + private: + // variations::AppendVariationHeaders and SafeJsonParser require a + // ThreadTaskRunnerHandle to be set. + base::MessageLoop message_loop_; + + safe_json::TestingJsonParser::ScopedFactoryOverride factory_override_; + + net::TestURLFetcherFactory url_fetcher_factory_; + sync_preferences::TestingPrefServiceSyncable pref_service_; + + TestSigninClient signin_client_; + AccountTrackerService account_tracker_; + FakeSigninManagerBase signin_manager_; + + scoped_refptr<base::TestSimpleTaskRunner> task_runner_; + scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; + FakeProfileOAuth2TokenService token_service_; + GoogleURLTracker google_url_tracker_; + + OneGoogleBarFetcherImpl one_google_bar_fetcher_; +}; + +TEST_F(OneGoogleBarFetcherImplTest, UnauthenticatedRequestReturns) { + base::MockCallback<OneGoogleBarFetcher::OneGoogleCallback> callback; + one_google_bar_fetcher()->Fetch(callback.Get()); + + base::Optional<OneGoogleBarData> data; + EXPECT_CALL(callback, Run(_)).WillOnce(SaveArg<0>(&data)); + RespondWithData(kMinimalValidResponse); + + EXPECT_TRUE(data.has_value()); +} + +TEST_F(OneGoogleBarFetcherImplTest, AuthenticatedRequestReturns) { + SignIn(); + + base::MockCallback<OneGoogleBarFetcher::OneGoogleCallback> callback; + one_google_bar_fetcher()->Fetch(callback.Get()); + + IssueAccessToken(); + + base::Optional<OneGoogleBarData> data; + EXPECT_CALL(callback, Run(_)).WillOnce(SaveArg<0>(&data)); + RespondWithData(kMinimalValidResponse); + + EXPECT_TRUE(data.has_value()); +} + +TEST_F(OneGoogleBarFetcherImplTest, UnauthenticatedRequestHasApiKey) { + base::MockCallback<OneGoogleBarFetcher::OneGoogleCallback> callback; + one_google_bar_fetcher()->Fetch(callback.Get()); + + // The request should have an API key (as a query param). + EXPECT_THAT(GetRunningURLFetcher()->GetOriginalURL().query(), + StartsWith("key=")); + + // But no "Authorization" header. + net::HttpRequestHeaders headers; + GetRunningURLFetcher()->GetExtraRequestHeaders(&headers); + EXPECT_FALSE(headers.HasHeader("Authorization")); +} + +TEST_F(OneGoogleBarFetcherImplTest, AuthenticatedRequestHasAuthHeader) { + SignIn(); + + base::MockCallback<OneGoogleBarFetcher::OneGoogleCallback> callback; + one_google_bar_fetcher()->Fetch(callback.Get()); + + IssueAccessToken(); + + // The request should *not* have an API key (as a query param). + EXPECT_THAT(GetRunningURLFetcher()->GetOriginalURL().query(), IsEmpty()); + + // It should have an "Authorization" header. + net::HttpRequestHeaders headers; + GetRunningURLFetcher()->GetExtraRequestHeaders(&headers); + EXPECT_TRUE(headers.HasHeader("Authorization")); +} + +TEST_F(OneGoogleBarFetcherImplTest, + AuthenticatedRequestFallsBackToUnauthenticated) { + SignIn(); + + base::MockCallback<OneGoogleBarFetcher::OneGoogleCallback> callback; + one_google_bar_fetcher()->Fetch(callback.Get()); + + IssueAccessTokenError(); + + // The request should have fallen back to unauthenticated mode with an API key + // (as a query param). + EXPECT_THAT(GetRunningURLFetcher()->GetOriginalURL().query(), + StartsWith("key=")); + + // But no "Authorization" header. + net::HttpRequestHeaders headers; + GetRunningURLFetcher()->GetExtraRequestHeaders(&headers); + EXPECT_FALSE(headers.HasHeader("Authorization")); +} + +TEST_F(OneGoogleBarFetcherImplTest, HandlesResponsePreamble) { + base::MockCallback<OneGoogleBarFetcher::OneGoogleCallback> callback; + one_google_bar_fetcher()->Fetch(callback.Get()); + + // The reponse may contain a ")]}'" prefix. The fetcher should ignore that + // during parsing. + base::Optional<OneGoogleBarData> data; + EXPECT_CALL(callback, Run(_)).WillOnce(SaveArg<0>(&data)); + RespondWithData(std::string(")]}'") + kMinimalValidResponse); + + EXPECT_TRUE(data.has_value()); +} + +TEST_F(OneGoogleBarFetcherImplTest, ParsesFullResponse) { + base::MockCallback<OneGoogleBarFetcher::OneGoogleCallback> callback; + one_google_bar_fetcher()->Fetch(callback.Get()); + + base::Optional<OneGoogleBarData> data; + EXPECT_CALL(callback, Run(_)).WillOnce(SaveArg<0>(&data)); + RespondWithData(R"json({"oneGoogleBar": { + "html": { "privateDoNotAccessOrElseSafeHtmlWrappedValue": "bar_html" }, + "pageHooks": { + "inHeadScript": { + "privateDoNotAccessOrElseSafeScriptWrappedValue": "in_head_script" + }, + "inHeadStyle": { + "privateDoNotAccessOrElseSafeStyleSheetWrappedValue": "in_head_style" + }, + "afterBarScript": { + "privateDoNotAccessOrElseSafeScriptWrappedValue": "after_bar_script" + }, + "endOfBodyHtml": { + "privateDoNotAccessOrElseSafeHtmlWrappedValue": "end_of_body_html" + }, + "endOfBodyScript": { + "privateDoNotAccessOrElseSafeScriptWrappedValue": "end_of_body_script" + } + } + }})json"); + + ASSERT_TRUE(data.has_value()); + EXPECT_THAT(data->bar_html, Eq("bar_html")); + EXPECT_THAT(data->in_head_script, Eq("in_head_script")); + EXPECT_THAT(data->in_head_style, Eq("in_head_style")); + EXPECT_THAT(data->after_bar_script, Eq("after_bar_script")); + EXPECT_THAT(data->end_of_body_html, Eq("end_of_body_html")); + EXPECT_THAT(data->end_of_body_script, Eq("end_of_body_script")); +} + +TEST_F(OneGoogleBarFetcherImplTest, CoalescesMultipleRequests) { + // Trigger two requests. + base::MockCallback<OneGoogleBarFetcher::OneGoogleCallback> first_callback; + one_google_bar_fetcher()->Fetch(first_callback.Get()); + net::URLFetcher* first_fetcher = GetRunningURLFetcher(); + base::MockCallback<OneGoogleBarFetcher::OneGoogleCallback> second_callback; + one_google_bar_fetcher()->Fetch(second_callback.Get()); + net::URLFetcher* second_fetcher = GetRunningURLFetcher(); + + // Expect that only one fetcher handles both requests. + EXPECT_THAT(first_fetcher, Eq(second_fetcher)); + + // But both callbacks should get called. + base::Optional<OneGoogleBarData> first_data; + base::Optional<OneGoogleBarData> second_data; + + EXPECT_CALL(first_callback, Run(_)).WillOnce(SaveArg<0>(&first_data)); + EXPECT_CALL(second_callback, Run(_)).WillOnce(SaveArg<0>(&second_data)); + + RespondWithData(kMinimalValidResponse); + + // Ensure that both requests received a response. + EXPECT_TRUE(first_data.has_value()); + EXPECT_TRUE(second_data.has_value()); +}
diff --git a/chrome/browser/ui/network_profile_bubble.cc b/chrome/browser/ui/network_profile_bubble.cc index e9d5997..5b02603 100644 --- a/chrome/browser/ui/network_profile_bubble.cc +++ b/chrome/browser/ui/network_profile_bubble.cc
@@ -90,7 +90,6 @@ // static void NetworkProfileBubble::CheckNetworkProfile( const base::FilePath& profile_folder) { - DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); // On Windows notify the users if their profiles are located on a network // share as we don't officially support this setup yet. // However we don't want to bother users on Cytrix setups as those have no
diff --git a/chrome/browser/win/jumplist.cc b/chrome/browser/win/jumplist.cc index 071087a..d9122ccf 100644 --- a/chrome/browser/win/jumplist.cc +++ b/chrome/browser/win/jumplist.cc
@@ -231,11 +231,10 @@ } // Updates the jumplist, once all the data has been fetched. -void RunUpdateJumpListUserVisiblePriority( - IncognitoModePrefs::Availability incognito_availability, - const std::wstring& app_id, - const base::FilePath& icon_dir, - base::RefCountedData<JumpListData>* ref_counted_data) { +void RunUpdateJumpList(IncognitoModePrefs::Availability incognito_availability, + const std::wstring& app_id, + const base::FilePath& icon_dir, + base::RefCountedData<JumpListData>* ref_counted_data) { JumpListData* data = &ref_counted_data->data; ShellLinkItemList local_most_visited_pages; ShellLinkItemList local_recently_closed_pages; @@ -508,7 +507,7 @@ if (!waiting_for_icons) { // No more favicons are needed by the application JumpList. Schedule a - // RunUpdateJumpListUserVisiblePriority call. + // RunUpdateJumpList call. PostRunUpdate(); return; } @@ -534,7 +533,7 @@ JumpListData* data = &jumplist_data_->data; base::AutoLock auto_lock(data->list_lock_); // Attach the received data to the ShellLinkItem object. - // This data will be decoded by the RunUpdateJumpListUserVisiblePriority + // This data will be decoded by the RunUpdateJumpList // method. if (!image_result.image.IsEmpty() && !data->icon_urls_.empty() && data->icon_urls_.front().second.get()) { @@ -596,15 +595,13 @@ // Post a task to delete the content in JumpListIcons folder and log the // results to UMA. update_jumplisticons_task_runner_->PostTask( - FROM_HERE, - base::Bind(&DeleteDirectoryContentAndLogResultsUserVisiblePriority, - icon_dir_, kFileDeleteLimit)); + FROM_HERE, base::Bind(&DeleteDirectoryContentAndLogResults, icon_dir_, + kFileDeleteLimit)); // Post a task to update the jumplist used by the shell. update_jumplisticons_task_runner_->PostTask( - FROM_HERE, - base::Bind(&RunUpdateJumpListUserVisiblePriority, incognito_availability, - app_id_, icon_dir_, base::RetainedRef(jumplist_data_))); + FROM_HERE, base::Bind(&RunUpdateJumpList, incognito_availability, app_id_, + icon_dir_, base::RetainedRef(jumplist_data_))); // Post a task to delete JumpListIconsOld folder and log the results to UMA. base::FilePath icon_dir_old = icon_dir_.DirName().Append(
diff --git a/chrome/browser/win/jumplist.h b/chrome/browser/win/jumplist.h index a66dbafd..0279af2 100644 --- a/chrome/browser/win/jumplist.h +++ b/chrome/browser/win/jumplist.h
@@ -152,7 +152,7 @@ // Helper for RunUpdate() that determines its parameters. void PostRunUpdate(); - // Called on a timer to invoke RunUpdateJumpListUserVisiblePriority() after + // Called on a timer to invoke RunUpdateJumpList() after // requests storms have subsided. void DeferredRunUpdate();
diff --git a/chrome/browser/win/jumplist_file_util.cc b/chrome/browser/win/jumplist_file_util.cc index 720896b..7c98704 100644 --- a/chrome/browser/win/jumplist_file_util.cc +++ b/chrome/browser/win/jumplist_file_util.cc
@@ -123,9 +123,8 @@ dir_status, DIRECTORY_STATUS_END); } -void DeleteDirectoryContentAndLogResultsUserVisiblePriority( - const base::FilePath& path, - int max_file_deleted) { +void DeleteDirectoryContentAndLogResults(const base::FilePath& path, + int max_file_deleted) { DirectoryStatus dir_status = NON_EXIST; // Delete the content in |path|. If |path| doesn't exist, create one.
diff --git a/chrome/browser/win/jumplist_file_util.h b/chrome/browser/win/jumplist_file_util.h index cd51de5..f9ab7a8 100644 --- a/chrome/browser/win/jumplist_file_util.h +++ b/chrome/browser/win/jumplist_file_util.h
@@ -79,8 +79,7 @@ int max_file_deleted); // Deletes the content in the directory at |path| and records the result to UMA. -void DeleteDirectoryContentAndLogResultsUserVisiblePriority( - const base::FilePath& path, - int max_file_deleted); +void DeleteDirectoryContentAndLogResults(const base::FilePath& path, + int max_file_deleted); #endif // CHROME_BROWSER_WIN_JUMPLIST_FILE_UTIL_H_
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 80abde9b..0448b032 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3671,6 +3671,7 @@ "../browser/search/instant_service_unittest.cc", "../browser/search/instant_unittest_base.cc", "../browser/search/instant_unittest_base.h", + "../browser/search/one_google_bar/one_google_bar_fetcher_impl_unittest.cc", "../browser/search/search_unittest.cc", "../browser/sessions/persistent_tab_restore_service_unittest.cc", "../browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc",
diff --git a/chrome/test/chromedriver/js/focus.js b/chrome/test/chromedriver/js/focus.js index 20b48db..7030796b 100644 --- a/chrome/test/chromedriver/js/focus.js +++ b/chrome/test/chromedriver/js/focus.js
@@ -44,7 +44,7 @@ // concerned, the shadow host is the active element. We need to go through the // tree of shadow DOMs to check that the element we gave focus to is now // active. - if (element != activeElement) { + if (element != activeElement && !element.contains(activeElement)) { var shadowRoot = activeElement.shadowRoot; while (shadowRoot) { var activeElement = shadowRoot.activeElement; @@ -57,6 +57,6 @@ shadowRoot = activeElement.shadowRoot; } } - if (element != activeElement) + if (element != activeElement && !element.contains(activeElement)) throw new Error('cannot focus element'); }
diff --git a/chrome/test/data/webui/settings/easy_unlock_browsertest_chromeos.js b/chrome/test/data/webui/settings/easy_unlock_browsertest_chromeos.js index b9b1a1ae..5e31e69 100644 --- a/chrome/test/data/webui/settings/easy_unlock_browsertest_chromeos.js +++ b/chrome/test/data/webui/settings/easy_unlock_browsertest_chromeos.js
@@ -30,15 +30,11 @@ // Times out on debug builders and may time out on memory bots because // the Settings page can take several seconds to load in a Release build -// and several times that in a Debug build. See https://crbug.com/558434. -GEN('#if defined(MEMORY_SANITIZER) || !defined(NDEBUG)'); -GEN('#define MAYBE_EasyUnlock DISABLED_EasyUnlock'); -GEN('#else'); -GEN('#define MAYBE_EasyUnlock EasyUnlock'); -GEN('#endif'); +// and several times that in a Debug build. See https://crbug.com/558434 +// and http://crbug.com/711256. // Runs easy unlock tests. -TEST_F('SettingsEasyUnlockBrowserTest', 'MAYBE_EasyUnlock', function() { +TEST_F('SettingsEasyUnlockBrowserTest', 'DISABLED_EasyUnlock', function() { /** * A test version of EasyUnlockBrowserProxy. Provides helper methods * for allowing tests to know when a method was called, as well as
diff --git a/chrome/test/data/webui/settings/settings_ui_browsertest.js b/chrome/test/data/webui/settings/settings_ui_browsertest.js index 849b4ac..be2201c 100644 --- a/chrome/test/data/webui/settings/settings_ui_browsertest.js +++ b/chrome/test/data/webui/settings/settings_ui_browsertest.js
@@ -18,14 +18,10 @@ // Times out on debug builders and may time out on memory bots because // the Settings page can take several seconds to load in a Release build -// and several times that in a Debug build. See https://crbug.com/558434. -GEN('#if defined(MEMORY_SANITIZER) || !defined(NDEBUG)'); -GEN('#define MAYBE_All DISABLED_All'); -GEN('#else'); -GEN('#define MAYBE_All All'); -GEN('#endif'); +// and several times that in a Debug build. See https://crbug.com/558434 +// and http://crbug.com/711256. -TEST_F('SettingsUIBrowserTest', 'MAYBE_All', function() { +TEST_F('SettingsUIBrowserTest', 'DISABLED_All', function() { suite('settings-ui', function() { var toolbar; var ui;
diff --git a/chrome/test/nacl/pnacl_header_test.cc b/chrome/test/nacl/pnacl_header_test.cc index c465bc51..f270f3c 100644 --- a/chrome/test/nacl/pnacl_header_test.cc +++ b/chrome/test/nacl/pnacl_header_test.cc
@@ -134,7 +134,8 @@ return std::move(http_response); } -IN_PROC_BROWSER_TEST_F(PnaclHeaderTest, TestHasPnaclHeader) { +// Flaky: http://crbug.com/711289 +IN_PROC_BROWSER_TEST_F(PnaclHeaderTest, DISABLED_TestHasPnaclHeader) { // Load 2 pexes, one same origin and one cross orgin. RunLoadTest("/nacl/pnacl_request_header/pnacl_request_header.html", 1, 1); }
diff --git a/components/ntp_snippets/BUILD.gn b/components/ntp_snippets/BUILD.gn index 257a1132..0cf1874a 100644 --- a/components/ntp_snippets/BUILD.gn +++ b/components/ntp_snippets/BUILD.gn
@@ -133,6 +133,7 @@ "category.h", "category_info.h", "category_status.h", + "content_suggestions_service.cc", ] } }
diff --git a/components/ntp_snippets/content_suggestions_service.cc b/components/ntp_snippets/content_suggestions_service.cc index d8220e04..861a08e 100644 --- a/components/ntp_snippets/content_suggestions_service.cc +++ b/components/ntp_snippets/content_suggestions_service.cc
@@ -12,6 +12,7 @@ #include "base/bind.h" #include "base/location.h" #include "base/memory/ptr_util.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/string_number_conversions.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/default_clock.h" @@ -26,6 +27,27 @@ namespace ntp_snippets { +namespace { + +// Enumeration listing all possible outcomes for fetch attempts of favicons for +// content suggestions. Used for UMA histograms, so do not change existing +// values. Insert new values at the end, and update the histogram definition. +// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.ntp.snippets +enum class FaviconFetchResult { + SUCCESS_CACHED = 0, + SUCCESS_FETCHED = 1, + FAILURE = 2, + COUNT = 3 +}; + +void RecordFaviconFetchResult(FaviconFetchResult result) { + UMA_HISTOGRAM_ENUMERATION( + "NewTabPage.ContentSuggestions.ArticleFaviconFetchResult", result, + FaviconFetchResult::COUNT); +} + +} // namespace + ContentSuggestionsService::ContentSuggestionsService( State state, SigninManagerBase* signin_manager, @@ -148,6 +170,7 @@ if (position == suggestions->end() || !large_icon_service_) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(callback, gfx::Image())); + RecordFaviconFetchResult(FaviconFetchResult::FAILURE); return; } @@ -175,6 +198,11 @@ const favicon_base::LargeIconImageResult& result) { if (!result.image.IsEmpty()) { callback.Run(result.image); + // The icon is from cache if we haven't gone to Google server yet. The icon + // is freshly fetched, otherwise. + RecordFaviconFetchResult(continue_to_google_server + ? FaviconFetchResult::SUCCESS_CACHED + : FaviconFetchResult::SUCCESS_FETCHED); return; } @@ -182,8 +210,10 @@ (result.fallback_icon_style && !result.fallback_icon_style->is_default_background_color)) { // We cannot download from the server if there is some small icon in the - // cache (resulting in non-default bakground color) or if we already did so. + // cache (resulting in non-default background color) or if we already did + // so. callback.Run(gfx::Image()); + RecordFaviconFetchResult(FaviconFetchResult::FAILURE); return; } @@ -205,6 +235,7 @@ bool success) { if (!success) { callback.Run(gfx::Image()); + RecordFaviconFetchResult(FaviconFetchResult::FAILURE); return; }
diff --git a/components/ntp_snippets/remote/remote_suggestions_scheduler_impl.cc b/components/ntp_snippets/remote/remote_suggestions_scheduler_impl.cc index e83531a6..82af8ed 100644 --- a/components/ntp_snippets/remote/remote_suggestions_scheduler_impl.cc +++ b/components/ntp_snippets/remote/remote_suggestions_scheduler_impl.cc
@@ -57,10 +57,10 @@ // The values of each array specify a default time interval for the intervals // defined by the enum FetchingInterval. The default time intervals defined in // the arrays can be overridden using different variation parameters. -const double kDefaultFetchingIntervalHoursRareNtpUser[] = {48.0, 24.0, 12.0, - 6.0}; -const double kDefaultFetchingIntervalHoursActiveNtpUser[] = {24.0, 6.0, 4.0, - 2.0}; +const double kDefaultFetchingIntervalHoursRareNtpUser[] = {48.0, 24.0, 8.0, + 4.0}; +const double kDefaultFetchingIntervalHoursActiveNtpUser[] = {24.0, 8.0, 6.0, + 3.0}; const double kDefaultFetchingIntervalHoursActiveSuggestionsConsumer[] = { 24.0, 6.0, 2.0, 1.0}; @@ -579,8 +579,7 @@ std::set<RemoteSuggestionsSchedulerImpl::TriggerType> RemoteSuggestionsSchedulerImpl::GetDefaultEnabledTriggerTypes() { - return {TriggerType::PERSISTENT_SCHEDULER_WAKE_UP, TriggerType::NTP_OPENED, - TriggerType::BROWSER_FOREGROUNDED}; + return {TriggerType::PERSISTENT_SCHEDULER_WAKE_UP, TriggerType::NTP_OPENED}; } } // namespace ntp_snippets
diff --git a/components/ntp_snippets/remote/remote_suggestions_scheduler_impl_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_scheduler_impl_unittest.cc index 220863e1..9e8b447 100644 --- a/components/ntp_snippets/remote/remote_suggestions_scheduler_impl_unittest.cc +++ b/components/ntp_snippets/remote/remote_suggestions_scheduler_impl_unittest.cc
@@ -632,7 +632,7 @@ // Pretend we are on WiFi (already done in ctor, we make it explicit here). EXPECT_CALL(*persistent_scheduler(), IsOnUnmeteredConnection()) .WillRepeatedly(Return(true)); - // UserClassifier defaults to UserClass::ACTIVE_NTP_USER which uses a 2h time + // UserClassifier defaults to UserClass::ACTIVE_NTP_USER which uses a 3h time // interval by default for soft background fetches on WiFi. // Initial scheduling after being enabled. @@ -649,11 +649,11 @@ signal_fetch_done.Run(Status::Success()); // Open NTP again after too short delay. This time no fetch is executed. - test_clock()->Advance(base::TimeDelta::FromMinutes(20)); + test_clock()->Advance(base::TimeDelta::FromMinutes(30)); scheduler()->OnNTPOpened(); // Open NTP after another delay, now together long enough to issue a fetch. - test_clock()->Advance(base::TimeDelta::FromMinutes(100)); + test_clock()->Advance(base::TimeDelta::FromMinutes(150)); EXPECT_CALL(*provider(), RefetchInTheBackground(_)); scheduler()->OnNTPOpened(); } @@ -696,7 +696,7 @@ // Pretend we are not on wifi -> fallback connection. EXPECT_CALL(*persistent_scheduler(), IsOnUnmeteredConnection()) .WillRepeatedly(Return(false)); - // UserClassifier defaults to UserClass::ACTIVE_NTP_USER which uses a 4h time + // UserClassifier defaults to UserClass::ACTIVE_NTP_USER which uses a 6h time // interval by default for soft background fetches not on WiFi. // Initial scheduling after being enabled. @@ -713,7 +713,7 @@ signal_fetch_done.Run(Status::Success()); // Open NTP again after too short delay. This time no fetch is executed. - test_clock()->Advance(base::TimeDelta::FromMinutes(180)); + test_clock()->Advance(base::TimeDelta::FromMinutes(300)); scheduler()->OnNTPOpened(); // Open NTP after another delay, now together long enough to issue a fetch.
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 4fe31eb..fc4f164 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -8145,11 +8145,11 @@ }, 'example_value': True, 'id': 276, - 'caption': '''Enable add person in profile manager''', + 'caption': '''Enable add person in user manager''', 'tags': [], 'desc': '''If this policy is set to true or not configured, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will allow Add Person from the user manager. - If this policy is set to false, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will not allow creation of new profiles from the profile manager.''', + If this policy is set to false, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will not allow creation of new profiles from the user manager.''', }, { 'name': 'ForceBrowserSignin',
diff --git a/content/browser/media/media_internals.cc b/content/browser/media/media_internals.cc index c8b7da3..a43f919 100644 --- a/content/browser/media/media_internals.cc +++ b/content/browser/media/media_internals.cc
@@ -29,7 +29,7 @@ #include "media/base/media_log_event.h" #include "media/filters/gpu_video_decoder.h" -#if !defined(OS_ANDROID) +#if !defined(DISABLE_FFMPEG_VIDEO_DECODERS) #include "media/filters/decrypting_video_decoder.h" #endif @@ -487,7 +487,7 @@ return uma_name + "Other"; } -#if !defined(OS_ANDROID) +#if !defined(DISABLE_FFMPEG_VIDEO_DECODERS) if (player_info.video_decoder == media::DecryptingVideoDecoder::kDecoderName) { return uma_name + "DVD";
diff --git a/content/public/browser/browser_thread.h b/content/public/browser/browser_thread.h index ad2db91..fe82220 100644 --- a/content/public/browser/browser_thread.h +++ b/content/public/browser/browser_thread.h
@@ -74,8 +74,11 @@ // DEPRECATED: prefer base/task_scheduler/post_task.h for new classes // requiring a background file I/O task runner, i.e.: // base::CreateSequencedTaskRunnerWithTraits( - // TaskTraits().MayBlock() - // .WithPriority(TaskPriority::BACKGROUND|USER_VISIBLE)...) + // base::TaskTraits().MayBlock() + // .WithPriority(base::TaskPriority::BACKGROUND)) + // Note: You can use base::TaskPriority::USER_VISIBLE instead of + // base::TaskPriority::BACKGROUND if the latency of this operation + // is visible but non-blocking to the user. FILE, // Used for file system operations that block user interactions. @@ -83,8 +86,8 @@ // DEPRECATED: prefer base/task_scheduler/post_task.h for new classes // requiring a user-blocking file I/O task runner, i.e.: // base::CreateSequencedTaskRunnerWithTraits( - // TaskTraits().MayBlock() - // .WithPriority(TaskPriority::USER_BLOCKING)...) + // base::TaskTraits().MayBlock() + // .WithPriority(base::TaskPriority::USER_BLOCKING)) FILE_USER_BLOCKING, // Used to launch and terminate Chrome processes. @@ -167,7 +170,7 @@ // DEPRECATED: use base/task_scheduler/post_task.h instead. // * BrowserThread::PostBlockingPoolTask(AndReply)(...) => // base::PostTaskWithTraits(AndReply)( - // FROM_HERE, TaskTraits().MayBlock()...) + // FROM_HERE, base::TaskTraits().MayBlock()...) // * BrowserThread::PostBlockingPoolSequencedTask => // Share a single SequencedTaskRunner created via // base::CreateSequencedTaskRunnerWithTraits() instead of sharing a @@ -223,7 +226,8 @@ // BrowserThread::GetBlockingPool()->GetSequencedTaskRunner( // base::SequencedWorkerPool::GetSequenceToken()) // => - // base::CreateSequencedTaskRunnerWithTraits(TaskTraits().MayBlock()...). + // base::CreateSequencedTaskRunnerWithTraits( + // base::TaskTraits().MayBlock()...). static base::SequencedWorkerPool* GetBlockingPool() WARN_UNUSED_RESULT; // Callable on any thread. Returns whether the given well-known thread is
diff --git a/content/test/gpu/gpu_tests/gpu_process_integration_test.py b/content/test/gpu/gpu_tests/gpu_process_integration_test.py index 207bbad..ccc6cea1 100644 --- a/content/test/gpu/gpu_tests/gpu_process_integration_test.py +++ b/content/test/gpu/gpu_tests/gpu_process_integration_test.py
@@ -299,12 +299,12 @@ # browser into a state where it won't launch. return elif sys.platform in ('cygwin', 'win32'): - # Hit id 34 from kSoftwareRenderingListJson. + # Hit id 34 from kSoftwareRenderingListEntries. self.RestartBrowserIfNecessaryWithArgs([ '--gpu-testing-vendor-id=0x5333', '--gpu-testing-device-id=0x8811']) elif sys.platform.startswith('linux'): - # Hit id 50 from kSoftwareRenderingListJson. + # Hit id 50 from kSoftwareRenderingListEntries. self.RestartBrowserIfNecessaryWithArgs([ '--gpu-no-complete-info-collection', '--gpu-testing-vendor-id=0x10de', @@ -313,7 +313,7 @@ '--gpu-testing-gl-renderer=softpipe', '--gpu-testing-gl-version="2.1 Mesa 10.1"']) elif sys.platform == 'darwin': - # Hit id 112 from kSoftwareRenderingListJson. + # Hit id 112 from kSoftwareRenderingListEntries. self.RestartBrowserIfNecessaryWithArgs([ '--gpu-testing-vendor-id=0x8086', '--gpu-testing-device-id=0x0116']) @@ -333,7 +333,7 @@ options = self.__class__._original_finder_options.browser_options is_platform_android = options.browser_type.startswith('android') if sys.platform.startswith('linux') and not is_platform_android: - # Hit id 110 from kSoftwareRenderingListJson. + # Hit id 110 from kSoftwareRenderingListEntries. self.RestartBrowserIfNecessaryWithArgs([ '--gpu-testing-vendor-id=0x10de', '--gpu-testing-device-id=0x0de1', @@ -362,13 +362,13 @@ def _GpuProcess_driver_bug_workarounds_upon_gl_renderer(self, test_path): is_platform_android = self._RunningOnAndroid() if is_platform_android: - # Hit id 108 from kGpuDriverBugListJson. + # Hit id 108 from kGpuDriverBugListEntries. self.RestartBrowserIfNecessaryWithArgs([ '--gpu-testing-gl-vendor=NVIDIA Corporation', '--gpu-testing-gl-renderer=NVIDIA Tegra', '--gpu-testing-gl-version=OpenGL ES 3.1 NVIDIA 343.00']) elif sys.platform in ('cygwin', 'win32'): - # Hit id 51 and 87 from kGpuDriverBugListJson. + # Hit id 51 and 87 from kGpuDriverBugListEntries. self.RestartBrowserIfNecessaryWithArgs([ '--gpu-testing-vendor-id=0x1002', '--gpu-testing-device-id=0x6779', @@ -378,7 +378,7 @@ '(AMD Radeon HD 6450 Direct3D11 vs_5_0 ps_5_0)', '--gpu-testing-gl-version=OpenGL ES 2.0 (ANGLE 2.1.0.0c0d8006a9dd)']) elif sys.platform.startswith('linux'): - # Hit id 40 from kGpuDriverBugListJson. + # Hit id 40 from kGpuDriverBugListEntries. self.RestartBrowserIfNecessaryWithArgs([ '--gpu-testing-vendor-id=0x0101', '--gpu-testing-device-id=0x0102', @@ -414,10 +414,10 @@ '--disable-gpu-driver-bug-workarounds'] # Inject some info to make sure the flags above are effective. if sys.platform == 'darwin': - # Hit id 33 from kGpuDriverBugListJson. + # Hit id 33 from kGpuDriverBugListEntries. browser_args.extend(['--gpu-testing-gl-vendor=Imagination']) else: - # Hit id 5 from kGpuDriverBugListJson. + # Hit id 5 from kGpuDriverBugListEntries. browser_args.extend(['--gpu-testing-vendor-id=0x10de', '--gpu-testing-device-id=0x0001']) # no multi gpu on Android. @@ -518,7 +518,7 @@ []) def _GpuProcess_disabling_workarounds_works(self, test_path): - # Hit exception from id 215 from kGpuDriverBugListJson. + # Hit exception from id 215 from kGpuDriverBugListEntries. self.RestartBrowserIfNecessaryWithArgs([ '--gpu-testing-vendor-id=0xbad9', '--gpu-testing-device-id=0xbad9', @@ -539,32 +539,38 @@ # process. On Windows, and eventually on other platforms where # SwiftShader is used, this test should pass. # - # TODO(kbr): figure out a better way than --disable-gpu to - # reliably trigger SwiftShader. - self.RestartBrowserIfNecessaryWithArgs(['--disable-gpu']) - self._NavigateAndWait(test_path) - # It looks like when SwiftShader is in use (via --disable-gpu), - # that GPU information collection doesn't yet contain what's - # expected (the system_info.gpu.aux_attributes['gl_renderer'] - # looks like it'll be null). Verified locally that we can fetch - # the desired information via WebGL. - renderer = self.tab.EvaluateJavaScript('gl_renderer') - if not renderer: - self.fail('getParameter(UNMASKED_RENDERER_WEBGL) was null') - if 'SwiftShader' not in renderer: - self.fail('Expected SwiftShader renderer; instead got ' + renderer) - if not self.browser.supports_system_info: - self.fail("Browser doesn't support GetSystemInfo") - gpu = self.browser.GetSystemInfo().gpu - if not gpu: - self.fail('Target machine must have a GPU') - if not gpu.aux_attributes: - self.fail('Browser must support GPU aux attributes') - if not gpu.aux_attributes['software_rendering']: - self.fail("Software rendering was disabled") - device = gpu.devices[0] - if not device: - self.fail("System Info doesn't have a device") + args_list = ([ + # Hit id 4 from kSoftwareRenderingListEntries. + '--gpu-testing-vendor-id=0x8086', + '--gpu-testing-device-id=0x27A2'], + # Explicitly disable GPU access. + ['--disable-gpu']) + for args in args_list: + self.RestartBrowserIfNecessaryWithArgs(args) + self._NavigateAndWait(test_path) + # Validate the WebGL unmasked renderer string. + renderer = self.tab.EvaluateJavaScript('gl_renderer') + if not renderer: + self.fail('getParameter(UNMASKED_RENDERER_WEBGL) was null') + if 'SwiftShader' not in renderer: + self.fail('Expected SwiftShader renderer; instead got ' + renderer) + # Validate GPU info. + if not self.browser.supports_system_info: + self.fail("Browser doesn't support GetSystemInfo") + gpu = self.browser.GetSystemInfo().gpu + if not gpu: + self.fail('Target machine must have a GPU') + if not gpu.aux_attributes: + self.fail('Browser must support GPU aux attributes') + if not gpu.aux_attributes['software_rendering']: + self.fail("Software rendering was disabled") + if 'SwiftShader' not in gpu.aux_attributes['gl_renderer']: + self.fail("Expected 'SwiftShader' in GPU info GL renderer string") + if 'Google' not in gpu.aux_attributes['gl_vendor']: + self.fail("Expected 'Google' in GPU info GL vendor string") + device = gpu.devices[0] + if not device: + self.fail("System Info doesn't have a device") def load_tests(loader, tests, pattern): del loader, tests, pattern # Unused.
diff --git a/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm b/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm index 5e81cc9..2c7e0f42 100644 --- a/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm +++ b/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm
@@ -555,6 +555,11 @@ @"correctly."); #endif + // TODO(crbug.com/711291): reenable this on tablets. + if (IsIPadIdiom()) { + EARL_GREY_TEST_DISABLED(@"Disabled for iPad."); + } + // Load the test page with a link to kOnLoadAlertURL and long tap on the link. [self loadPageWithLink]; id<GREYMatcher> webViewMatcher =
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn index efa90a0b..edbc096 100644 --- a/ios/chrome/browser/ui/settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -25,7 +25,8 @@ ] } -source_set("settings") { +source_set("settings_arc") { + configs += [ "//build/config/compiler:enable_arc" ] sources = [ "about_chrome_collection_view_controller.h", "about_chrome_collection_view_controller.mm", @@ -48,6 +49,106 @@ "block_popups_collection_view_controller.mm", "clear_browsing_data_collection_view_controller.h", "clear_browsing_data_collection_view_controller.mm", + ] + deps = [ + ":resources", + "//base", + "//base:i18n", + "//components/autofill/core/browser", + "//components/autofill/core/common", + "//components/autofill/ios/browser", + "//components/browser_sync", + "//components/browsing_data/core", + "//components/content_settings/core/browser", + "//components/content_settings/core/common", + "//components/google/core/browser", + "//components/handoff", + "//components/history/core/browser", + "//components/image_fetcher/ios", + "//components/keyed_service/core", + "//components/metrics", + "//components/password_manager/core/browser", + "//components/password_manager/core/common", + "//components/physical_web/data_source", + "//components/prefs", + "//components/resources", + "//components/search_engines", + "//components/signin/core/browser", + "//components/signin/core/common", + "//components/signin/ios/browser", + "//components/strings", + "//components/sync", + "//components/translate/core/browser", + "//components/translate/core/common", + "//components/url_formatter", + "//components/version_info", + "//ios/chrome/app/strings", + "//ios/chrome/browser", + "//ios/chrome/browser/autofill", + "//ios/chrome/browser/autofill:autofill_internal", + "//ios/chrome/browser/browser_state", + "//ios/chrome/browser/browser_state:browser_state_impl", + "//ios/chrome/browser/browsing_data", + "//ios/chrome/browser/content_settings", + "//ios/chrome/browser/history", + "//ios/chrome/browser/native_app_launcher:native_app_launcher_internal", + "//ios/chrome/browser/passwords", + "//ios/chrome/browser/payments/cells", + "//ios/chrome/browser/physical_web", + "//ios/chrome/browser/prefs", + "//ios/chrome/browser/search_engines", + "//ios/chrome/browser/signin", + "//ios/chrome/browser/store_kit", + "//ios/chrome/browser/sync", + "//ios/chrome/browser/translate", + "//ios/chrome/browser/ui", + "//ios/chrome/browser/ui/alert_coordinator", + "//ios/chrome/browser/ui/authentication", + "//ios/chrome/browser/ui/authentication:authentication_arc", + "//ios/chrome/browser/ui/authentication:authentication_ui", + "//ios/chrome/browser/ui/autofill", + "//ios/chrome/browser/ui/autofill:autofill_ui", + "//ios/chrome/browser/ui/autofill/cells", + "//ios/chrome/browser/ui/collection_view", + "//ios/chrome/browser/ui/colors", + "//ios/chrome/browser/ui/commands", + "//ios/chrome/browser/ui/content_suggestions/cells", + "//ios/chrome/browser/ui/contextual_search", + "//ios/chrome/browser/ui/icons", + "//ios/chrome/browser/ui/keyboard", + "//ios/chrome/browser/ui/material_components", + "//ios/chrome/browser/ui/settings/cells", + "//ios/chrome/browser/ui/settings/utils", + "//ios/chrome/browser/ui/sync", + "//ios/chrome/browser/voice", + "//ios/chrome/common", + "//ios/public/provider/chrome/browser", + "//ios/public/provider/chrome/browser/images", + "//ios/public/provider/chrome/browser/native_app_launcher", + "//ios/public/provider/chrome/browser/signin", + "//ios/public/provider/chrome/browser/user_feedback", + "//ios/public/provider/chrome/browser/voice", + "//ios/third_party/material_components_ios", + "//ios/third_party/material_roboto_font_loader_ios", + "//ios/web", + "//net", + "//ui/base", + "//url", + ] + public_deps = [ + "//ios/chrome/browser/ui/collection_view/cells", + ] + allow_circular_includes_from = [ "//ios/chrome/browser/ui/authentication" ] + libs = [ + "CoreLocation.framework", + "LocalAuthentication.framework", + "StoreKit.framework", + "UIKit.framework", + ] +} + +source_set("settings") { + sources = [ "content_settings_collection_view_controller.h", "content_settings_collection_view_controller.mm", "contextual_search_collection_view_controller.h", @@ -187,9 +288,13 @@ "//url", ] public_deps = [ + ":settings_arc", "//ios/chrome/browser/ui/collection_view/cells", ] - allow_circular_includes_from = [ "//ios/chrome/browser/ui/authentication" ] + allow_circular_includes_from = [ + "//ios/chrome/browser/ui/authentication", + ":settings_arc", + ] libs = [ "CoreLocation.framework", "LocalAuthentication.framework",
diff --git a/ios/chrome/browser/ui/settings/about_chrome_collection_view_controller.mm b/ios/chrome/browser/ui/settings/about_chrome_collection_view_controller.mm index 11b6ff8..740243f 100644 --- a/ios/chrome/browser/ui/settings/about_chrome_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/about_chrome_collection_view_controller.mm
@@ -7,7 +7,6 @@ #import "base/ios/block_types.h" #include "base/logging.h" #import "base/mac/foundation_util.h" -#import "base/mac/scoped_nsobject.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "components/version_info/version_info.h" @@ -27,6 +26,10 @@ #include "ui/base/l10n/l10n_util_mac.h" #include "url/gurl.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace { typedef NS_ENUM(NSInteger, SectionIdentifier) { @@ -64,35 +67,32 @@ [model addSectionWithIdentifier:SectionIdentifierLinks]; - base::scoped_nsobject<CollectionViewTextItem> credits( - [[CollectionViewTextItem alloc] initWithType:ItemTypeLinksCredits]); - credits.get().text = l10n_util::GetNSString(IDS_IOS_OPEN_SOURCE_LICENSES); - credits.get().accessoryType = - MDCCollectionViewCellAccessoryDisclosureIndicator; - credits.get().accessibilityTraits = UIAccessibilityTraitButton; + CollectionViewTextItem* credits = + [[CollectionViewTextItem alloc] initWithType:ItemTypeLinksCredits]; + credits.text = l10n_util::GetNSString(IDS_IOS_OPEN_SOURCE_LICENSES); + credits.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator; + credits.accessibilityTraits = UIAccessibilityTraitButton; [model addItem:credits toSectionWithIdentifier:SectionIdentifierLinks]; - base::scoped_nsobject<CollectionViewTextItem> terms( - [[CollectionViewTextItem alloc] initWithType:ItemTypeLinksTerms]); - terms.get().text = l10n_util::GetNSString(IDS_IOS_TERMS_OF_SERVICE); - terms.get().accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator; - terms.get().accessibilityTraits = UIAccessibilityTraitButton; + CollectionViewTextItem* terms = + [[CollectionViewTextItem alloc] initWithType:ItemTypeLinksTerms]; + terms.text = l10n_util::GetNSString(IDS_IOS_TERMS_OF_SERVICE); + terms.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator; + terms.accessibilityTraits = UIAccessibilityTraitButton; [model addItem:terms toSectionWithIdentifier:SectionIdentifierLinks]; - base::scoped_nsobject<CollectionViewTextItem> privacy( - [[CollectionViewTextItem alloc] initWithType:ItemTypeLinksPrivacy]); - privacy.get().text = l10n_util::GetNSString(IDS_IOS_PRIVACY_POLICY); - privacy.get().accessoryType = - MDCCollectionViewCellAccessoryDisclosureIndicator; - privacy.get().accessibilityTraits = UIAccessibilityTraitButton; + CollectionViewTextItem* privacy = + [[CollectionViewTextItem alloc] initWithType:ItemTypeLinksPrivacy]; + privacy.text = l10n_util::GetNSString(IDS_IOS_PRIVACY_POLICY); + privacy.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator; + privacy.accessibilityTraits = UIAccessibilityTraitButton; [model addItem:privacy toSectionWithIdentifier:SectionIdentifierLinks]; [model addSectionWithIdentifier:SectionIdentifierFooter]; - base::scoped_nsobject<VersionItem> version( - [[VersionItem alloc] initWithType:ItemTypeVersion]); - version.get().text = [self versionDescriptionString]; - version.get().accessibilityTraits = UIAccessibilityTraitButton; + VersionItem* version = [[VersionItem alloc] initWithType:ItemTypeVersion]; + version.text = [self versionDescriptionString]; + version.accessibilityTraits = UIAccessibilityTraitButton; [model addItem:version toSectionWithIdentifier:SectionIdentifierFooter]; }
diff --git a/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm b/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm index 6cc4d39..9e92d47 100644 --- a/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm
@@ -4,9 +4,7 @@ #import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h" -#import "base/ios/weak_nsobject.h" #import "base/mac/foundation_util.h" -#import "base/mac/scoped_nsobject.h" #include "base/metrics/user_metrics.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" @@ -54,6 +52,10 @@ #import "net/base/mac/url_conversions.h" #include "ui/base/l10n/l10n_util_mac.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + NSString* const kSettingsAccountsId = @"kSettingsAccountsId"; NSString* const kSettingsHeaderId = @"kSettingsHeaderId"; NSString* const kSettingsAccountsSignoutCellId = @@ -88,23 +90,21 @@ BOOL _closeSettingsOnAddAccount; std::unique_ptr<SyncObserverBridge> _syncObserver; std::unique_ptr<OAuth2TokenServiceObserverBridge> _tokenServiceObserver; - base::scoped_nsobject<SigninInteractionController> - _signinInteractionController; + SigninInteractionController* _signinInteractionController; // Modal alert for sign out. - base::scoped_nsobject<AlertCoordinator> _alertCoordinator; + AlertCoordinator* _alertCoordinator; // Whether an authentication operation is in progress (e.g switch accounts, // sign out). BOOL _authenticationOperationInProgress; // Whether the view controller is currently being dismissed and new dismiss // requests should be ignored. BOOL _isBeingDismissed; - base::WeakNSObject<UIViewController> _settingsDetails; - base::scoped_nsobject<ResizedAvatarCache> _avatarCache; + __weak UIViewController* _settingsDetails; + ResizedAvatarCache* _avatarCache; std::unique_ptr<ChromeIdentityServiceObserverBridge> _identityServiceObserver; // Enable lookup of item corresponding to a given identity GAIA ID string. - base::scoped_nsobject<NSDictionary<NSString*, CollectionViewItem*>> - _identityMap; + NSDictionary<NSString*, CollectionViewItem*>* _identityMap; } // Stops observing browser state services. This is required during the shutdown @@ -139,7 +139,7 @@ name:kSwitchAccountDidFinishNotification object:nil]; self.collectionViewAccessibilityIdentifier = kSettingsAccountsId; - _avatarCache.reset([[ResizedAvatarCache alloc] init]); + _avatarCache = [[ResizedAvatarCache alloc] init]; _identityServiceObserver.reset( new ChromeIdentityServiceObserverBridge(self)); [self loadModel]; @@ -150,7 +150,6 @@ - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - [super dealloc]; } - (void)stopBrowserStateServiceObservers { @@ -199,7 +198,7 @@ CollectionViewModel* model = self.collectionViewModel; NSMutableDictionary<NSString*, CollectionViewItem*>* mutableIdentityMap = - [[[NSMutableDictionary alloc] init] autorelease]; + [[NSMutableDictionary alloc] init]; // Account cells. ProfileOAuth2TokenService* oauth2_service = @@ -219,7 +218,7 @@ [mutableIdentityMap setObject:item forKey:identity.gaiaID]; } - _identityMap.reset([mutableIdentityMap retain]); + _identityMap = mutableIdentityMap; [model addItem:[self addAccountItem] toSectionWithIdentifier:SectionIdentifierAccounts]; @@ -239,8 +238,8 @@ #pragma mark - Model objects - (CollectionViewItem*)header { - CollectionViewTextItem* header = [ - [[CollectionViewTextItem alloc] initWithType:ItemTypeHeader] autorelease]; + CollectionViewTextItem* header = + [[CollectionViewTextItem alloc] initWithType:ItemTypeHeader]; header.text = l10n_util::GetNSString(IDS_IOS_OPTIONS_ACCOUNTS_DESCRIPTION); header.accessibilityIdentifier = kSettingsHeaderId; header.textColor = [[MDCPalette greyPalette] tint500]; @@ -248,8 +247,8 @@ } - (CollectionViewItem*)accountItem:(ChromeIdentity*)identity { - CollectionViewAccountItem* item = [[[CollectionViewAccountItem alloc] - initWithType:ItemTypeAccount] autorelease]; + CollectionViewAccountItem* item = + [[CollectionViewAccountItem alloc] initWithType:ItemTypeAccount]; [self updateAccountItem:item withIdentity:identity]; return item; } @@ -263,8 +262,8 @@ } - (CollectionViewItem*)addAccountItem { - CollectionViewAccountItem* item = [[[CollectionViewAccountItem alloc] - initWithType:ItemTypeAddAccount] autorelease]; + CollectionViewAccountItem* item = + [[CollectionViewAccountItem alloc] initWithType:ItemTypeAddAccount]; item.text = l10n_util::GetNSString(IDS_IOS_OPTIONS_ACCOUNTS_ADD_ACCOUNT_BUTTON); item.image = [UIImage imageNamed:@"settings_accounts_add_account"]; @@ -273,7 +272,7 @@ - (CollectionViewItem*)syncItem { AccountControlItem* item = - [[[AccountControlItem alloc] initWithType:ItemTypeSync] autorelease]; + [[AccountControlItem alloc] initWithType:ItemTypeSync]; item.text = l10n_util::GetNSString(IDS_IOS_OPTIONS_ACCOUNTS_SYNC_TITLE); item.accessibilityIdentifier = kSettingsAccountsSyncCellId; [self updateSyncItem:item]; @@ -315,8 +314,8 @@ } - (CollectionViewItem*)googleActivityControlsItem { - AccountControlItem* item = [[[AccountControlItem alloc] - initWithType:ItemTypeGoogleActivityControls] autorelease]; + AccountControlItem* item = + [[AccountControlItem alloc] initWithType:ItemTypeGoogleActivityControls]; item.text = l10n_util::GetNSString(IDS_IOS_OPTIONS_ACCOUNTS_GOOGLE_TITLE); item.detailText = l10n_util::GetNSString(IDS_IOS_OPTIONS_ACCOUNTS_GOOGLE_DESCRIPTION); @@ -328,8 +327,8 @@ } - (CollectionViewItem*)signOutItem { - CollectionViewTextItem* item = [[[CollectionViewTextItem alloc] - initWithType:ItemTypeSignOut] autorelease]; + CollectionViewTextItem* item = + [[CollectionViewTextItem alloc] initWithType:ItemTypeSignOut]; item.text = l10n_util::GetNSString(IDS_IOS_OPTIONS_ACCOUNTS_SIGNOUT); item.accessibilityTraits |= UIAccessibilityTraitButton; item.accessibilityIdentifier = kSettingsAccountsSignoutCellId; @@ -417,7 +416,7 @@ [self popViewIfSignedOut]; if (![self authService]->IsAuthenticated() && _settingsDetails) { [_settingsDetails dismissViewControllerAnimated:YES completion:nil]; - _settingsDetails.reset(); + _settingsDetails = nil; } } @@ -433,10 +432,10 @@ return; } - base::scoped_nsobject<UIViewController> controllerToPush( + UIViewController* controllerToPush = [[SyncSettingsCollectionViewController alloc] initWithBrowserState:_browserState - allowSwitchSyncAccount:YES]); + allowSwitchSyncAccount:YES]; [self.navigationController pushViewController:controllerToPush animated:YES]; } @@ -445,14 +444,14 @@ return; base::RecordAction(base::UserMetricsAction( "Signin_AccountSettings_GoogleActivityControlsClicked")); - base::scoped_nsobject<UINavigationController> settingsDetails( + UINavigationController* settingsDetails = ios::GetChromeBrowserProvider() ->GetChromeIdentityService() ->NewWebAndAppSettingDetails( - [self authService]->GetAuthenticatedIdentity(), self)); + [self authService]->GetAuthenticatedIdentity(), self); UIImage* closeIcon = [ChromeIcon closeIcon]; SEL action = @selector(closeGoogleActivitySettings:); - [settingsDetails.get().topViewController navigationItem].leftBarButtonItem = + [settingsDetails.topViewController navigationItem].leftBarButtonItem = [ChromeIcon templateBarButtonItemWithImage:closeIcon target:self action:action]; @@ -460,7 +459,7 @@ // Keep a weak reference on the settings details, to be able to dismiss it // when the primary account is removed. - _settingsDetails.reset(settingsDetails); + _settingsDetails = settingsDetails; } - (void)closeGoogleActivitySettings:(id)sender { @@ -478,17 +477,17 @@ // in-progress. return; } - _signinInteractionController.reset([[SigninInteractionController alloc] + _signinInteractionController = [[SigninInteractionController alloc] initWithBrowserState:_browserState presentingViewController:self.navigationController isPresentedOnSettings:YES signInAccessPoint:signin_metrics::AccessPoint:: - ACCESS_POINT_SETTINGS]); + ACCESS_POINT_SETTINGS]; // |_authenticationOperationInProgress| is reset when the signin interaction // controller is dismissed. _authenticationOperationInProgress = YES; - base::WeakNSObject<AccountsCollectionViewController> weakSelf(self); + __weak AccountsCollectionViewController* weakSelf = self; [_signinInteractionController addAccountWithCompletion:^(BOOL success) { [weakSelf handleDidAddAccount:success]; } @@ -496,11 +495,11 @@ } - (void)handleDidAddAccount:(BOOL)success { - _signinInteractionController.reset(); + _signinInteractionController = nil; [self handleAuthenticationOperationDidFinish]; if (success && _closeSettingsOnAddAccount) { - base::scoped_nsobject<GenericChromeCommand> closeSettingsCommand( - [[GenericChromeCommand alloc] initWithTag:IDC_CLOSE_SETTINGS]); + GenericChromeCommand* closeSettingsCommand = + [[GenericChromeCommand alloc] initWithTag:IDC_CLOSE_SETTINGS]; [self chromeExecuteCommand:closeSettingsCommand]; } } @@ -508,10 +507,9 @@ - (void)showAccountDetails:(ChromeIdentity*)identity { if ([_alertCoordinator isVisible]) return; - base::scoped_nsobject<UIViewController> accountDetails( - ios::GetChromeBrowserProvider() - ->GetChromeIdentityService() - ->NewAccountDetails(identity, self)); + UIViewController* accountDetails = ios::GetChromeBrowserProvider() + ->GetChromeIdentityService() + ->NewAccountDetails(identity, self); if (!accountDetails) { // Failed to create a new account details. Ignored. return; @@ -520,7 +518,7 @@ // Keep a weak reference on the account details, to be able to dismiss it // when the primary account is removed. - _settingsDetails.reset(accountDetails); + _settingsDetails = accountDetails; } - (void)showDisconnect { @@ -549,15 +547,15 @@ continueButtonTitle = l10n_util::GetNSString( IDS_IOS_DISCONNECT_DIALOG_CONTINUE_BUTTON_MOBILE); } - _alertCoordinator.reset([[AlertCoordinator alloc] - initWithBaseViewController:self - title:title - message:message]); + _alertCoordinator = + [[AlertCoordinator alloc] initWithBaseViewController:self + title:title + message:message]; [_alertCoordinator addItemWithTitle:l10n_util::GetNSString(IDS_CANCEL) action:nil style:UIAlertActionStyleCancel]; - base::WeakNSObject<AccountsCollectionViewController> weakSelf(self); + __weak AccountsCollectionViewController* weakSelf = self; [_alertCoordinator addItemWithTitle:continueButtonTitle action:^{ [weakSelf handleDisconnect]; @@ -635,8 +633,8 @@ - (void)openURL:(NSURL*)url view:(UIView*)view viewController:(UIViewController*)viewController { - base::scoped_nsobject<OpenUrlCommand> command( - [[OpenUrlCommand alloc] initWithURLFromChrome:net::GURLWithNSURL(url)]); + OpenUrlCommand* command = + [[OpenUrlCommand alloc] initWithURLFromChrome:net::GURLWithNSURL(url)]; [command setTag:IDC_CLOSE_SETTINGS_AND_OPEN_URL]; [self chromeExecuteCommand:command]; }
diff --git a/ios/chrome/browser/ui/settings/autofill_collection_view_controller.mm b/ios/chrome/browser/ui/settings/autofill_collection_view_controller.mm index 13c22d5..9f901101 100644 --- a/ios/chrome/browser/ui/settings/autofill_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/autofill_collection_view_controller.mm
@@ -4,10 +4,7 @@ #import "ios/chrome/browser/ui/settings/autofill_collection_view_controller.h" -#import "base/ios/weak_nsobject.h" #include "base/mac/foundation_util.h" -#import "base/mac/objc_property_releaser.h" -#import "base/mac/scoped_nsobject.h" #include "base/strings/sys_string_conversions.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/common/autofill_pref_names.h" @@ -28,6 +25,10 @@ #import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" #include "ui/base/l10n/l10n_util.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace { typedef NS_ENUM(NSInteger, SectionIdentifier) { @@ -52,8 +53,7 @@ PersonalDataManagerObserverBridgeDelegate> { std::string _locale; // User locale. autofill::PersonalDataManager* _personalDataManager; - base::mac::ObjCPropertyReleaser - _propertyReleaser_AutofillCollectionViewController; + ios::ChromeBrowserState* _browserState; std::unique_ptr<autofill::PersonalDataManagerObserverBridge> _observer; BOOL _deletionInProgress; @@ -86,16 +86,12 @@ [self updateEditButton]; [self loadModel]; - - _propertyReleaser_AutofillCollectionViewController.Init( - self, [AutofillCollectionViewController class]); } return self; } - (void)dealloc { _personalDataManager->RemoveObserver(_observer.get()); - [super dealloc]; } #pragma mark - CollectionViewController @@ -154,16 +150,16 @@ } - (CollectionViewItem*)autofillSwitchItem { - CollectionViewSwitchItem* switchItem = [[[CollectionViewSwitchItem alloc] - initWithType:ItemTypeAutofillSwitch] autorelease]; + CollectionViewSwitchItem* switchItem = + [[CollectionViewSwitchItem alloc] initWithType:ItemTypeAutofillSwitch]; switchItem.text = l10n_util::GetNSString(IDS_IOS_AUTOFILL); switchItem.on = [self isAutofillEnabled]; return switchItem; } - (CollectionViewItem*)walletSwitchItem { - CollectionViewSwitchItem* switchItem = [[[CollectionViewSwitchItem alloc] - initWithType:ItemTypeWalletSwitch] autorelease]; + CollectionViewSwitchItem* switchItem = + [[CollectionViewSwitchItem alloc] initWithType:ItemTypeWalletSwitch]; switchItem.text = l10n_util::GetNSString(IDS_IOS_AUTOFILL_USE_WALLET_DATA); switchItem.on = [self isWalletEnabled]; return switchItem; @@ -182,8 +178,8 @@ } - (CollectionViewTextItem*)genericHeader { - CollectionViewTextItem* header = [ - [[CollectionViewTextItem alloc] initWithType:ItemTypeHeader] autorelease]; + CollectionViewTextItem* header = + [[CollectionViewTextItem alloc] initWithType:ItemTypeHeader]; header.textColor = [[MDCPalette greyPalette] tint500]; return header; } @@ -199,7 +195,7 @@ autofill::AutofillProfile::SERVER_PROFILE; AutofillDataItem* item = - [[[AutofillDataItem alloc] initWithType:ItemTypeAddress] autorelease]; + [[AutofillDataItem alloc] initWithType:ItemTypeAddress]; item.text = title; item.leadingDetailText = subTitle; item.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator; @@ -218,8 +214,7 @@ std::string guid(creditCard.guid()); NSString* creditCardName = autofill::GetCreditCardName(creditCard, _locale); - AutofillDataItem* item = - [[[AutofillDataItem alloc] initWithType:ItemTypeCard] autorelease]; + AutofillDataItem* item = [[AutofillDataItem alloc] initWithType:ItemTypeCard]; item.text = creditCardName; item.leadingDetailText = autofill::GetCreditCardObfuscatedNumber(creditCard); item.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator; @@ -284,11 +279,10 @@ [self updateEditButton]; // Avoid reference cycle in block. - base::WeakNSObject<AutofillCollectionViewController> weakSelf(self); + __weak AutofillCollectionViewController* weakSelf = self; [self.collectionView performBatchUpdates:^{ // Obtain strong reference again. - base::scoped_nsobject<AutofillCollectionViewController> strongSelf( - [weakSelf retain]); + AutofillCollectionViewController* strongSelf = weakSelf; if (!strongSelf) { return; } @@ -380,7 +374,7 @@ } - (NSIndexSet*)indexSetForExistingProfileAndCardSections { - NSMutableIndexSet* sections = [[[NSMutableIndexSet alloc] init] autorelease]; + NSMutableIndexSet* sections = [[NSMutableIndexSet alloc] init]; if ([self.collectionViewModel hasSectionForSectionIdentifier:SectionIdentifierProfiles]) { [sections @@ -457,29 +451,29 @@ } CollectionViewModel* model = self.collectionViewModel; - base::scoped_nsobject<UIViewController> controller; + UIViewController* controller; switch ([model itemTypeForIndexPath:indexPath]) { case ItemTypeAddress: { const std::vector<autofill::AutofillProfile*> autofillProfiles = _personalDataManager->GetProfiles(); - controller.reset([[AutofillProfileEditCollectionViewController + controller = [AutofillProfileEditCollectionViewController controllerWithProfile:*autofillProfiles[indexPath.item] - personalDataManager:_personalDataManager] retain]); + personalDataManager:_personalDataManager]; break; } case ItemTypeCard: { const std::vector<autofill::CreditCard*>& creditCards = _personalDataManager->GetCreditCards(); - controller.reset([[AutofillCreditCardEditCollectionViewController alloc] + controller = [[AutofillCreditCardEditCollectionViewController alloc] initWithCreditCard:*creditCards[indexPath.item] - personalDataManager:_personalDataManager]); + personalDataManager:_personalDataManager]; break; } default: break; } - if (controller.get()) { + if (controller) { [self.navigationController pushViewController:controller animated:YES]; } } @@ -539,11 +533,10 @@ [self.collectionViewModel sectionForSectionIdentifier:sectionIdentifier]; if ([self.collectionView numberOfItemsInSection:section] == 0) { // Avoid reference cycle in block. - base::WeakNSObject<AutofillCollectionViewController> weakSelf(self); + __weak AutofillCollectionViewController* weakSelf = self; [self.collectionView performBatchUpdates:^{ // Obtain strong reference again. - base::scoped_nsobject<AutofillCollectionViewController> strongSelf( - [weakSelf retain]); + AutofillCollectionViewController* strongSelf = weakSelf; if (!strongSelf) { return; } @@ -556,8 +549,7 @@ } completion:^(BOOL finished) { // Obtain strong reference again. - base::scoped_nsobject<AutofillCollectionViewController> strongSelf( - [weakSelf retain]); + AutofillCollectionViewController* strongSelf = weakSelf; if (!strongSelf) { return; } @@ -567,7 +559,7 @@ [[strongSelf editor] setEditing:NO]; } [strongSelf updateEditButton]; - strongSelf.get()->_deletionInProgress = NO; + strongSelf->_deletionInProgress = NO; }]; } }
diff --git a/ios/chrome/browser/ui/settings/autofill_credit_card_edit_collection_view_controller.mm b/ios/chrome/browser/ui/settings/autofill_credit_card_edit_collection_view_controller.mm index f17c319..ce984d06 100644 --- a/ios/chrome/browser/ui/settings/autofill_credit_card_edit_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/autofill_credit_card_edit_collection_view_controller.mm
@@ -6,10 +6,8 @@ #include "base/format_macros.h" #import "base/ios/block_types.h" -#import "base/ios/weak_nsobject.h" #import "base/mac/foundation_util.h" #include "base/mac/scoped_block.h" -#import "base/mac/scoped_nsobject.h" #include "base/strings/sys_string_conversions.h" #include "components/autofill/core/browser/autofill_data_util.h" #include "components/autofill/core/browser/credit_card.h" @@ -31,9 +29,14 @@ #import "ios/chrome/browser/ui/uikit_ui_util.h" #include "ios/chrome/grit/ios_chromium_strings.h" #include "ios/chrome/grit/ios_strings.h" +#import "ios/third_party/material_components_ios/src/components/Buttons/src/MaterialButtons.h" #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace { using ::AutofillTypeFromAutofillUIType; @@ -89,8 +92,8 @@ if (_creditCard.record_type() == autofill::CreditCard::FULL_SERVER_CARD || _creditCard.record_type() == autofill::CreditCard::MASKED_SERVER_CARD) { GURL paymentsURL = autofill::payments::GetManageInstrumentsUrl(0); - base::scoped_nsobject<OpenUrlCommand> command( - [[OpenUrlCommand alloc] initWithURLFromChrome:paymentsURL]); + OpenUrlCommand* command = + [[OpenUrlCommand alloc] initWithURLFromChrome:paymentsURL]; [command setTag:IDC_CLOSE_SETTINGS_AND_OPEN_URL]; [self chromeExecuteCommand:command]; @@ -141,8 +144,8 @@ BOOL isEditing = self.editor.editing; [model addSectionWithIdentifier:SectionIdentifierFields]; - AutofillEditItem* cardholderNameitem = [[[AutofillEditItem alloc] - initWithType:ItemTypeCardholderName] autorelease]; + AutofillEditItem* cardholderNameitem = + [[AutofillEditItem alloc] initWithType:ItemTypeCardholderName]; cardholderNameitem.textFieldName = l10n_util::GetNSString(IDS_IOS_AUTOFILL_CARDHOLDER); cardholderNameitem.textFieldValue = autofill::GetCreditCardName( @@ -154,7 +157,7 @@ // Card number (PAN). AutofillEditItem* cardNumberitem = - [[[AutofillEditItem alloc] initWithType:ItemTypeCardNumber] autorelease]; + [[AutofillEditItem alloc] initWithType:ItemTypeCardNumber]; cardNumberitem.textFieldName = l10n_util::GetNSString(IDS_IOS_AUTOFILL_CARD_NUMBER); // Never show full card number for Wallet cards, even if copied locally. @@ -170,8 +173,8 @@ toSectionWithIdentifier:SectionIdentifierFields]; // Expiration month. - AutofillEditItem* expirationMonthItem = [[[AutofillEditItem alloc] - initWithType:ItemTypeExpirationMonth] autorelease]; + AutofillEditItem* expirationMonthItem = + [[AutofillEditItem alloc] initWithType:ItemTypeExpirationMonth]; expirationMonthItem.textFieldName = l10n_util::GetNSString(IDS_IOS_AUTOFILL_EXP_MONTH); expirationMonthItem.textFieldValue = @@ -182,8 +185,8 @@ toSectionWithIdentifier:SectionIdentifierFields]; // Expiration year. - AutofillEditItem* expirationYearItem = [[[AutofillEditItem alloc] - initWithType:ItemTypeExpirationYear] autorelease]; + AutofillEditItem* expirationYearItem = + [[AutofillEditItem alloc] initWithType:ItemTypeExpirationYear]; expirationYearItem.textFieldName = l10n_util::GetNSString(IDS_IOS_AUTOFILL_EXP_YEAR); expirationYearItem.textFieldValue = @@ -196,8 +199,8 @@ if (_creditCard.record_type() == autofill::CreditCard::FULL_SERVER_CARD) { // Add CopiedToChrome cell in its own section. [model addSectionWithIdentifier:SectionIdentifierCopiedToChrome]; - CopiedToChromeItem* copiedToChromeItem = [[[CopiedToChromeItem alloc] - initWithType:ItemTypeCopiedToChrome] autorelease]; + CopiedToChromeItem* copiedToChromeItem = + [[CopiedToChromeItem alloc] initWithType:ItemTypeCopiedToChrome]; [model addItem:copiedToChromeItem toSectionWithIdentifier:SectionIdentifierCopiedToChrome]; }
diff --git a/ios/chrome/browser/ui/settings/autofill_edit_collection_view_controller.mm b/ios/chrome/browser/ui/settings/autofill_edit_collection_view_controller.mm index 660cde5..00458527 100644 --- a/ios/chrome/browser/ui/settings/autofill_edit_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/autofill_edit_collection_view_controller.mm
@@ -6,12 +6,15 @@ #include "base/logging.h" #import "base/mac/foundation_util.h" -#import "base/mac/scoped_nsobject.h" #import "ios/chrome/browser/ui/autofill/autofill_edit_accessory_view.h" #import "ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h" #import "ios/chrome/browser/ui/settings/autofill_edit_collection_view_controller+protected.h" #import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace { AutofillEditCell* AutofillEditCellForTextField(UITextField* textField) { @@ -33,8 +36,8 @@ @interface AutofillEditCollectionViewController ()< AutofillEditAccessoryDelegate> { - base::scoped_nsobject<AutofillEditCell> _currentEditingCell; - base::scoped_nsobject<AutofillEditAccessoryView> _accessoryView; + AutofillEditCell* _currentEditingCell; + AutofillEditAccessoryView* _accessoryView; } @end @@ -46,8 +49,7 @@ return nil; } - _accessoryView.reset( - [[AutofillEditAccessoryView alloc] initWithDelegate:self]); + _accessoryView = [[AutofillEditAccessoryView alloc] initWithDelegate:self]; [self setShouldHideDoneButton:YES]; [self updateEditButton]; return self; @@ -72,7 +74,6 @@ - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - [super dealloc]; } #pragma mark - SettingsRootCollectionViewController @@ -109,7 +110,7 @@ - (void)textFieldDidBeginEditing:(UITextField*)textField { AutofillEditCell* cell = AutofillEditCellForTextField(textField); - _currentEditingCell.reset([cell retain]); + _currentEditingCell = cell; [textField setInputAccessoryView:_accessoryView]; [self updateAccessoryViewButtonState]; } @@ -118,7 +119,7 @@ AutofillEditCell* cell = AutofillEditCellForTextField(textField); DCHECK(_currentEditingCell == cell); [textField setInputAccessoryView:nil]; - _currentEditingCell.reset(nil); + _currentEditingCell = nil; } - (BOOL)textFieldShouldReturn:(UITextField*)textField {
diff --git a/ios/chrome/browser/ui/settings/autofill_profile_edit_collection_view_controller.mm b/ios/chrome/browser/ui/settings/autofill_profile_edit_collection_view_controller.mm index dc60aff..6f9cc2b 100644 --- a/ios/chrome/browser/ui/settings/autofill_profile_edit_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/autofill_profile_edit_collection_view_controller.mm
@@ -4,9 +4,7 @@ #import "ios/chrome/browser/ui/settings/autofill_profile_edit_collection_view_controller.h" -#import "base/ios/weak_nsobject.h" #include "base/mac/foundation_util.h" -#import "base/mac/scoped_nsobject.h" #include "base/strings/sys_string_conversions.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/field_types.h" @@ -24,6 +22,10 @@ #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + NSString* const kAutofillProfileEditCollectionViewId = @"kAutofillProfileEditCollectionViewId"; @@ -109,8 +111,7 @@ + (instancetype)controllerWithProfile:(const autofill::AutofillProfile&)profile personalDataManager: (autofill::PersonalDataManager*)dataManager { - return [[[self alloc] initWithProfile:profile personalDataManager:dataManager] - autorelease]; + return [[self alloc] initWithProfile:profile personalDataManager:dataManager]; } #pragma mark - SettingsRootCollectionViewController @@ -120,8 +121,8 @@ if (_autofillProfile.record_type() == autofill::AutofillProfile::SERVER_PROFILE) { GURL paymentsURL = autofill::payments::GetManageAddressesUrl(0); - base::scoped_nsobject<OpenUrlCommand> command( - [[OpenUrlCommand alloc] initWithURLFromChrome:paymentsURL]); + OpenUrlCommand* command = + [[OpenUrlCommand alloc] initWithURLFromChrome:paymentsURL]; [command setTag:IDC_CLOSE_SETTINGS_AND_OPEN_URL]; [self chromeExecuteCommand:command]; @@ -181,7 +182,7 @@ for (size_t i = 0; i < arraysize(kFieldsToDisplay); ++i) { const AutofillFieldDisplayInfo& field = kFieldsToDisplay[i]; AutofillEditItem* item = - [[[AutofillEditItem alloc] initWithType:ItemTypeField] autorelease]; + [[AutofillEditItem alloc] initWithType:ItemTypeField]; item.textFieldName = l10n_util::GetNSString(field.displayStringID); item.textFieldValue = base::SysUTF16ToNSString(_autofillProfile.GetInfo( autofill::AutofillType(field.autofillType), locale));
diff --git a/ios/chrome/browser/ui/settings/bandwidth_management_collection_view_controller.mm b/ios/chrome/browser/ui/settings/bandwidth_management_collection_view_controller.mm index 18eefc1..26e8487c 100644 --- a/ios/chrome/browser/ui/settings/bandwidth_management_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/bandwidth_management_collection_view_controller.mm
@@ -5,7 +5,6 @@ #import "ios/chrome/browser/ui/settings/bandwidth_management_collection_view_controller.h" #include "base/mac/foundation_util.h" -#import "base/mac/scoped_nsobject.h" #include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_service.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" @@ -25,6 +24,10 @@ #include "ui/base/l10n/l10n_util_mac.h" #include "url/gurl.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace { typedef NS_ENUM(NSInteger, SectionIdentifier) { @@ -49,7 +52,7 @@ PrefChangeRegistrar _prefChangeRegistrarApplicationContext; // Updatable Items - base::scoped_nsobject<CollectionViewDetailItem> _preloadWebpagesDetailItem; + CollectionViewDetailItem* _preloadWebpagesDetailItem; } // Helpers to create collection view items. @@ -102,22 +105,21 @@ currentLabelForPreference:_browserState->GetPrefs() basePref:prefs::kNetworkPredictionEnabled wifiPref:prefs::kNetworkPredictionWifiOnly]; - _preloadWebpagesDetailItem.reset( - [[CollectionViewDetailItem alloc] initWithType:ItemTypePreload]); + _preloadWebpagesDetailItem = + [[CollectionViewDetailItem alloc] initWithType:ItemTypePreload]; - _preloadWebpagesDetailItem.get().text = + _preloadWebpagesDetailItem.text = l10n_util::GetNSString(IDS_IOS_OPTIONS_PRELOAD_WEBPAGES); - _preloadWebpagesDetailItem.get().detailText = detailText; - _preloadWebpagesDetailItem.get().accessoryType = + _preloadWebpagesDetailItem.detailText = detailText; + _preloadWebpagesDetailItem.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator; - _preloadWebpagesDetailItem.get().accessibilityTraits |= - UIAccessibilityTraitButton; + _preloadWebpagesDetailItem.accessibilityTraits |= UIAccessibilityTraitButton; return _preloadWebpagesDetailItem; } - (CollectionViewItem*)footerItem { - CollectionViewFooterItem* item = [[[CollectionViewFooterItem alloc] - initWithType:ItemTypeFooter] autorelease]; + CollectionViewFooterItem* item = + [[CollectionViewFooterItem alloc] initWithType:ItemTypeFooter]; item.text = l10n_util::GetNSString( IDS_IOS_BANDWIDTH_MANAGEMENT_DESCRIPTION_LEARN_MORE); @@ -148,12 +150,12 @@ if (type == ItemTypePreload) { NSString* preloadTitle = l10n_util::GetNSString(IDS_IOS_OPTIONS_PRELOAD_WEBPAGES); - base::scoped_nsobject<UIViewController> controller( + UIViewController* controller = [[DataplanUsageCollectionViewController alloc] initWithPrefs:_browserState->GetPrefs() basePref:prefs::kNetworkPredictionEnabled wifiPref:prefs::kNetworkPredictionWifiOnly - title:preloadTitle]); + title:preloadTitle]; [self.navigationController pushViewController:controller animated:YES]; } } @@ -210,7 +212,7 @@ basePref:prefs::kNetworkPredictionEnabled wifiPref:prefs::kNetworkPredictionWifiOnly]; - _preloadWebpagesDetailItem.get().detailText = detailText; + _preloadWebpagesDetailItem.detailText = detailText; [self reconfigureCellsForItems:@[ _preloadWebpagesDetailItem ] inSectionWithIdentifier:SectionIdentifierActions];
diff --git a/ios/chrome/browser/ui/settings/bar_button_activity_indicator.mm b/ios/chrome/browser/ui/settings/bar_button_activity_indicator.mm index 5586ac5..0f4734d7 100644 --- a/ios/chrome/browser/ui/settings/bar_button_activity_indicator.mm +++ b/ios/chrome/browser/ui/settings/bar_button_activity_indicator.mm
@@ -4,18 +4,21 @@ #import "ios/chrome/browser/ui/settings/bar_button_activity_indicator.h" -#import "base/mac/scoped_nsobject.h" #include "ios/chrome/browser/ui/ui_util.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + @implementation BarButtonActivityIndicator { - base::scoped_nsobject<UIActivityIndicatorView> activityIndicator_; + UIActivityIndicatorView* activityIndicator_; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { - activityIndicator_.reset([[UIActivityIndicatorView alloc] - initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]); + activityIndicator_ = [[UIActivityIndicatorView alloc] + initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; [activityIndicator_ setBackgroundColor:[UIColor clearColor]]; [activityIndicator_ setHidesWhenStopped:YES]; [activityIndicator_ startAnimating]; @@ -26,7 +29,6 @@ - (void)dealloc { [activityIndicator_ stopAnimating]; - [super dealloc]; } - (void)layoutSubviews {
diff --git a/ios/chrome/browser/ui/settings/block_popups_collection_view_controller.mm b/ios/chrome/browser/ui/settings/block_popups_collection_view_controller.mm index db548f6..c562d60 100644 --- a/ios/chrome/browser/ui/settings/block_popups_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/block_popups_collection_view_controller.mm
@@ -4,10 +4,8 @@ #import "ios/chrome/browser/ui/settings/block_popups_collection_view_controller.h" -#import "base/ios/weak_nsobject.h" #include "base/logging.h" #import "base/mac/foundation_util.h" -#import "base/mac/scoped_nsobject.h" #include "base/strings/sys_string_conversions.h" #include "base/values.h" #include "components/content_settings/core/browser/host_content_settings_map.h" @@ -24,6 +22,10 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util_mac.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace { typedef NS_ENUM(NSInteger, SectionIdentifier) { @@ -46,10 +48,10 @@ base::ListValue _exceptions; // The observable boolean that binds to the "Disable Popups" setting state. - base::scoped_nsobject<ContentSettingBackedBoolean> _disablePopupsSetting; + ContentSettingBackedBoolean* _disablePopupsSetting; // The item related to the switch for the "Disable Popups" setting. - base::scoped_nsobject<CollectionViewSwitchItem> _blockPopupsItem; + CollectionViewSwitchItem* _blockPopupsItem; } // Fetch the urls that can display popups and add them to |_exceptions|. @@ -69,10 +71,10 @@ _browserState = browserState; HostContentSettingsMap* settingsMap = ios::HostContentSettingsMapFactory::GetForBrowserState(_browserState); - _disablePopupsSetting.reset([[ContentSettingBackedBoolean alloc] + _disablePopupsSetting = [[ContentSettingBackedBoolean alloc] initWithHostContentSettingsMap:settingsMap settingID:CONTENT_SETTINGS_TYPE_POPUPS - inverted:YES]); + inverted:YES]; [_disablePopupsSetting setObserver:self]; self.title = l10n_util::GetNSString(IDS_IOS_BLOCK_POPUPS); self.collectionViewAccessibilityIdentifier = @@ -87,7 +89,6 @@ - (void)dealloc { [_disablePopupsSetting setObserver:nil]; - [super dealloc]; } #pragma mark - SettingsRootCollectionViewController @@ -100,12 +101,11 @@ // Block popups switch. [model addSectionWithIdentifier:SectionIdentifierMainSwitch]; - _blockPopupsItem.reset( - [[CollectionViewSwitchItem alloc] initWithType:ItemTypeMainSwitch]); - _blockPopupsItem.get().text = l10n_util::GetNSString(IDS_IOS_BLOCK_POPUPS); - _blockPopupsItem.get().on = [_disablePopupsSetting value]; - _blockPopupsItem.get().accessibilityIdentifier = - @"blockPopupsContentView_switch"; + _blockPopupsItem = + [[CollectionViewSwitchItem alloc] initWithType:ItemTypeMainSwitch]; + _blockPopupsItem.text = l10n_util::GetNSString(IDS_IOS_BLOCK_POPUPS); + _blockPopupsItem.on = [_disablePopupsSetting value]; + _blockPopupsItem.accessibilityIdentifier = @"blockPopupsContentView_switch"; [model addItem:_blockPopupsItem toSectionWithIdentifier:SectionIdentifierMainSwitch]; @@ -187,18 +187,17 @@ NSInteger exceptionsSectionIndex = [self.collectionViewModel sectionForSectionIdentifier:SectionIdentifierExceptions]; if ([collectionView numberOfItemsInSection:exceptionsSectionIndex] == 0) { - base::WeakNSObject<BlockPopupsCollectionViewController> weakSelf(self); + __weak BlockPopupsCollectionViewController* weakSelf = self; [self.collectionView performBatchUpdates:^{ - base::scoped_nsobject<BlockPopupsCollectionViewController> strongSelf( - [weakSelf retain]); + BlockPopupsCollectionViewController* strongSelf = weakSelf; if (!strongSelf) { return; } - NSInteger section = [strongSelf.get().collectionViewModel + NSInteger section = [strongSelf.collectionViewModel sectionForSectionIdentifier:SectionIdentifierExceptions]; - [strongSelf.get().collectionViewModel + [strongSelf.collectionViewModel removeSectionWithIdentifier:SectionIdentifierExceptions]; - [strongSelf.get().collectionView + [strongSelf.collectionView deleteSections:[NSIndexSet indexSetWithIndex:section]]; } completion:nil]; @@ -222,10 +221,10 @@ #pragma mark - BooleanObserver - (void)booleanDidChange:(id<ObservableBoolean>)observableBoolean { - DCHECK_EQ(observableBoolean, _disablePopupsSetting.get()); + DCHECK_EQ(observableBoolean, _disablePopupsSetting); // Update the item. - _blockPopupsItem.get().on = [_disablePopupsSetting value]; + _blockPopupsItem.on = [_disablePopupsSetting value]; // Update the cell. [self reconfigureCellsForItems:@[ _blockPopupsItem ] @@ -244,7 +243,7 @@ [_disablePopupsSetting setValue:switchView.on]; // Update the item. - _blockPopupsItem.get().on = [_disablePopupsSetting value]; + _blockPopupsItem.on = [_disablePopupsSetting value]; // Update the rest of the UI. [self.editor setEditing:NO]; @@ -294,8 +293,8 @@ CollectionViewModel* model = self.collectionViewModel; [model addSectionWithIdentifier:SectionIdentifierExceptions]; - CollectionViewTextItem* header = [ - [[CollectionViewTextItem alloc] initWithType:ItemTypeHeader] autorelease]; + CollectionViewTextItem* header = + [[CollectionViewTextItem alloc] initWithType:ItemTypeHeader]; header.text = l10n_util::GetNSString(IDS_IOS_POPUPS_ALLOWED); header.textColor = [[MDCPalette greyPalette] tint500]; [model setHeader:header forSectionWithIdentifier:SectionIdentifierExceptions]; @@ -303,8 +302,8 @@ for (size_t i = 0; i < _exceptions.GetSize(); ++i) { std::string allowed_url; _exceptions.GetString(i, &allowed_url); - CollectionViewTextItem* item = [[[CollectionViewTextItem alloc] - initWithType:ItemTypeException] autorelease]; + CollectionViewTextItem* item = + [[CollectionViewTextItem alloc] initWithType:ItemTypeException]; item.text = base::SysUTF8ToNSString(allowed_url); [model addItem:item toSectionWithIdentifier:SectionIdentifierExceptions]; } @@ -318,10 +317,9 @@ if (blockPopupsIsOn && !exceptionsListShown && hasExceptions) { // Animate in the list of exceptions. Animation looks much better if the // section is added at once, rather than row-by-row as each object is added. - base::WeakNSObject<BlockPopupsCollectionViewController> weakSelf(self); + __weak BlockPopupsCollectionViewController* weakSelf = self; [self.collectionView performBatchUpdates:^{ - base::scoped_nsobject<BlockPopupsCollectionViewController> strongSelf( - [weakSelf retain]); + BlockPopupsCollectionViewController* strongSelf = weakSelf; if (!strongSelf) return; [strongSelf populateExceptionsItems]; @@ -333,10 +331,9 @@ completion:nil]; } else if (!blockPopupsIsOn && exceptionsListShown) { // Make sure the exception section is not shown. - base::WeakNSObject<BlockPopupsCollectionViewController> weakSelf(self); + __weak BlockPopupsCollectionViewController* weakSelf = self; [self.collectionView performBatchUpdates:^{ - base::scoped_nsobject<BlockPopupsCollectionViewController> strongSelf( - [weakSelf retain]); + BlockPopupsCollectionViewController* strongSelf = weakSelf; if (!strongSelf) return; NSUInteger index = [[strongSelf collectionViewModel]
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller.mm b/ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller.mm index 5e65e4f..1a128bd 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller.mm
@@ -8,11 +8,9 @@ #include <string> #include "base/ios/ios_util.h" -#import "base/ios/weak_nsobject.h" #include "base/logging.h" #import "base/mac/bind_objc_block.h" #include "base/mac/foundation_util.h" -#import "base/mac/scoped_nsobject.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/strings/string_piece.h" @@ -61,6 +59,10 @@ #include "ui/base/l10n/l10n_util_mac.h" #include "url/gurl.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + NSString* const kClearBrowsingDataCollectionViewId = @"kClearBrowsingDataCollectionViewId"; NSString* const kClearBrowsingHistoryCellId = @"kClearBrowsingHistoryCellId"; @@ -207,18 +209,16 @@ kClearBrowsingDataCollectionViewId; if (experimental_flags::IsNewClearBrowsingDataUIEnabled()) { - base::WeakNSObject<ClearBrowsingDataCollectionViewController> weakSelf( - self); + __weak ClearBrowsingDataCollectionViewController* weakSelf = self; void (^dataClearedCallback)( const IOSChromeBrowsingDataRemover::NotificationDetails&) = ^(const IOSChromeBrowsingDataRemover::NotificationDetails& details) { - base::scoped_nsobject<ClearBrowsingDataCollectionViewController> - strongSelf([weakSelf retain]); + ClearBrowsingDataCollectionViewController* strongSelf = weakSelf; [strongSelf restartCounters:details.removal_mask]; }; _callbackSubscription = IOSChromeBrowsingDataRemover::RegisterOnBrowsingDataRemovedCallback( - base::BindBlock(dataClearedCallback)); + base::BindBlockArc(dataClearedCallback)); } [self loadModel]; @@ -241,20 +241,18 @@ history::WebHistoryService* historyService = ios::WebHistoryServiceFactory::GetForBrowserState(_browserState); - base::WeakNSObject<ClearBrowsingDataCollectionViewController> weakSelf(self); + __weak ClearBrowsingDataCollectionViewController* weakSelf = self; browsing_data::ShouldShowNoticeAboutOtherFormsOfBrowsingHistory( - syncService, historyService, base::BindBlock(^(bool shouldShowNotice) { - base::scoped_nsobject<ClearBrowsingDataCollectionViewController> - strongSelf([weakSelf retain]); + syncService, historyService, base::BindBlockArc(^(bool shouldShowNotice) { + ClearBrowsingDataCollectionViewController* strongSelf = weakSelf; [strongSelf setShouldShowNoticeAboutOtherFormsOfBrowsingHistory: shouldShowNotice]; })); browsing_data::ShouldPopupDialogAboutOtherFormsOfBrowsingHistory( syncService, historyService, GetChannel(), - base::BindBlock(^(bool shouldShowPopup) { - base::scoped_nsobject<ClearBrowsingDataCollectionViewController> - strongSelf([weakSelf retain]); + base::BindBlockArc(^(bool shouldShowPopup) { + ClearBrowsingDataCollectionViewController* strongSelf = weakSelf; [strongSelf setShouldPopupDialogAboutOtherFormsOfBrowsingHistory: shouldShowPopup]; })); @@ -328,8 +326,8 @@ // Clear Browsing Data button. [model addSectionWithIdentifier:SectionIdentifierClearBrowsingDataButton]; - CollectionViewTextItem* clearButtonItem = [[[CollectionViewTextItem alloc] - initWithType:ItemTypeClearBrowsingDataButton] autorelease]; + CollectionViewTextItem* clearButtonItem = [[CollectionViewTextItem alloc] + initWithType:ItemTypeClearBrowsingDataButton]; clearButtonItem.text = l10n_util::GetNSString(IDS_IOS_CLEAR_BUTTON); clearButtonItem.accessibilityTraits |= UIAccessibilityTraitButton; clearButtonItem.textColor = [[MDCPalette cr_redPalette] tint500]; @@ -371,8 +369,7 @@ mask:(int)mask prefName:(const char*)prefName { PrefService* prefs = _browserState->GetPrefs(); - ClearDataItem* clearDataItem = - [[[ClearDataItem alloc] initWithType:itemType] autorelease]; + ClearDataItem* clearDataItem = [[ClearDataItem alloc] initWithType:itemType]; clearDataItem.text = l10n_util::GetNSString(titleMessageID); if (prefs->GetBoolean(prefName)) { clearDataItem.accessoryType = MDCCollectionViewCellAccessoryCheckmark; @@ -382,18 +379,17 @@ clearDataItem.accessibilityIdentifier = [self getAccessibilityIdentifierFromItemType:itemType]; - base::WeakNSObject<ClearBrowsingDataCollectionViewController> weakSelf(self); + __weak ClearBrowsingDataCollectionViewController* weakSelf = self; void (^updateUICallback)(const browsing_data::BrowsingDataCounter::Result&) = ^(const browsing_data::BrowsingDataCounter::Result& result) { - base::scoped_nsobject<ClearBrowsingDataCollectionViewController> - strongSelf([weakSelf retain]); + ClearBrowsingDataCollectionViewController* strongSelf = weakSelf; NSString* counterText = [strongSelf getCounterTextFromResult:result]; [strongSelf updateCounter:itemType detailText:counterText]; }; [clearDataItem setCounter:BrowsingDataCounterWrapper::CreateCounterWrapper( prefName, _browserState, prefs, - base::BindBlock(updateUICallback))]; + base::BindBlockArc(updateUICallback))]; return clearDataItem; } @@ -426,8 +422,8 @@ } - (CollectionViewItem*)footerGoogleAccountItem { - CollectionViewFooterItem* footerItem = [[[CollectionViewFooterItem alloc] - initWithType:ItemTypeFooterGoogleAccount] autorelease]; + CollectionViewFooterItem* footerItem = [[CollectionViewFooterItem alloc] + initWithType:ItemTypeFooterGoogleAccount]; footerItem.text = l10n_util::GetNSString(IDS_IOS_CLEAR_BROWSING_DATA_FOOTER_ACCOUNT); UIImage* image = ios::GetChromeBrowserProvider() @@ -475,7 +471,7 @@ URL:(const char[])URL image:(UIImage*)image { CollectionViewFooterItem* footerItem = - [[[CollectionViewFooterItem alloc] initWithType:itemType] autorelease]; + [[CollectionViewFooterItem alloc] initWithType:itemType]; footerItem.text = l10n_util::GetNSString(titleMessageID); footerItem.linkURL = google_util::AppendGoogleLocaleParam( GURL(URL), GetApplicationContext()->GetApplicationLocale()); @@ -485,8 +481,8 @@ } - (CollectionViewItem*)timeRangeItem { - CollectionViewDetailItem* timeRangeItem = [[[CollectionViewDetailItem alloc] - initWithType:ItemTypeTimeRange] autorelease]; + CollectionViewDetailItem* timeRangeItem = + [[CollectionViewDetailItem alloc] initWithType:ItemTypeTimeRange]; timeRangeItem.text = l10n_util::GetNSString( IDS_IOS_CLEAR_BROWSING_DATA_TIME_RANGE_SELECTOR_TITLE); NSString* detailText = [TimeRangeSelectorCollectionViewController @@ -509,10 +505,10 @@ switch (itemType) { case ItemTypeTimeRange: { - base::scoped_nsobject<UIViewController> controller( + UIViewController* controller = [[TimeRangeSelectorCollectionViewController alloc] initWithPrefs:_browserState->GetPrefs() - delegate:self]); + delegate:self]; [self.navigationController pushViewController:controller animated:YES]; break; } @@ -612,7 +608,7 @@ // Nothing to clear (no data types selected). return YES; } - base::WeakNSObject<ClearBrowsingDataCollectionViewController> weakSelf(self); + __weak ClearBrowsingDataCollectionViewController* weakSelf = self; UIAlertController* alertController = [UIAlertController alertControllerWithTitle:nil message:nil @@ -638,10 +634,10 @@ - (void)clearDataForDataTypes:(int)dataTypeMask { DCHECK(dataTypeMask); - base::scoped_nsobject<ClearBrowsingDataCommand> command( + ClearBrowsingDataCommand* command = [[ClearBrowsingDataCommand alloc] initWithBrowserState:_browserState mask:dataTypeMask - timePeriod:_timePeriod]); + timePeriod:_timePeriod]; [self chromeExecuteCommand:command]; if (!!(dataTypeMask && IOSChromeBrowsingDataRemover::REMOVE_HISTORY)) { @@ -682,7 +678,7 @@ message:message preferredStyle:UIAlertControllerStyleAlert]; - base::WeakNSObject<ClearBrowsingDataCollectionViewController> weakSelf(self); + __weak ClearBrowsingDataCollectionViewController* weakSelf = self; UIAlertAction* openMyActivityAction = [UIAlertAction actionWithTitle: l10n_util::GetNSString( @@ -703,9 +699,9 @@ } - (void)openMyActivityLink { - base::scoped_nsobject<OpenUrlCommand> openMyActivityCommand( - [[OpenUrlCommand alloc] initWithURLFromChrome:GURL(kGoogleMyAccountURL)]); - openMyActivityCommand.get().tag = IDC_CLOSE_SETTINGS_AND_OPEN_URL; + OpenUrlCommand* openMyActivityCommand = + [[OpenUrlCommand alloc] initWithURLFromChrome:GURL(kGoogleMyAccountURL)]; + openMyActivityCommand.tag = IDC_CLOSE_SETTINGS_AND_OPEN_URL; [self chromeExecuteCommand:openMyActivityCommand]; } @@ -784,12 +780,11 @@ // Because of this, the lowest unit that can be used is MB. static const int kBytesInAMegabyte = 1 << 20; if (cacheSizeBytes >= kBytesInAMegabyte) { - base::scoped_nsobject<NSByteCountFormatter> formatter( - [[NSByteCountFormatter alloc] init]); - formatter.get().allowedUnits = NSByteCountFormatterUseAll & - (~NSByteCountFormatterUseBytes) & - (~NSByteCountFormatterUseKB); - formatter.get().countStyle = NSByteCountFormatterCountStyleMemory; + NSByteCountFormatter* formatter = [[NSByteCountFormatter alloc] init]; + formatter.allowedUnits = NSByteCountFormatterUseAll & + (~NSByteCountFormatterUseBytes) & + (~NSByteCountFormatterUseKB); + formatter.countStyle = NSByteCountFormatterCountStyleMemory; NSString* formattedSize = [formatter stringFromByteCount:cacheSizeBytes]; return (_timePeriod == browsing_data::TimePeriod::ALL_TIME) ? formattedSize
diff --git a/ios/clean/chrome/app/app_delegate.mm b/ios/clean/chrome/app/app_delegate.mm index 5a3293b..fe81355 100644 --- a/ios/clean/chrome/app/app_delegate.mm +++ b/ios/clean/chrome/app/app_delegate.mm
@@ -8,7 +8,7 @@ #import "ios/clean/chrome/app/steps/launch_to_background.h" #import "ios/clean/chrome/app/steps/launch_to_basic.h" #import "ios/clean/chrome/app/steps/launch_to_foreground.h" -#import "ios/clean/chrome/app/steps/tab_grid_coordinator+application_step.h" +#import "ios/clean/chrome/app/steps/root_coordinator+application_step.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -109,7 +109,7 @@ [[BeginForegrounding alloc] init], [[PrepareForUI alloc] init], [[CompleteForegrounding alloc] init], - [[TabGridCoordinator alloc] init], + [[RootCoordinator alloc] init], ]]; }
diff --git a/ios/clean/chrome/app/steps/BUILD.gn b/ios/clean/chrome/app/steps/BUILD.gn index 7da46f0..e87ff249 100644 --- a/ios/clean/chrome/app/steps/BUILD.gn +++ b/ios/clean/chrome/app/steps/BUILD.gn
@@ -10,8 +10,8 @@ "launch_to_basic.mm", "launch_to_foreground.h", "launch_to_foreground.mm", - "tab_grid_coordinator+application_step.h", - "tab_grid_coordinator+application_step.mm", + "root_coordinator+application_step.h", + "root_coordinator+application_step.mm", ] configs += [ "//build/config/compiler:enable_arc" ] @@ -28,10 +28,28 @@ "//ios/chrome/browser/content_settings", "//ios/chrome/browser/web:web_internal", "//ios/clean/chrome/app:application_state", - "//ios/clean/chrome/browser/ui/tab_grid", + "//ios/clean/chrome/browser/ui/root", "//ios/net", "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/coordinators", "//ios/web:web_arc", ] } + +source_set("unit_tests") { + testonly = true + + sources = [ + "root_coordinator+application_step_unittest.mm", + ] + + configs += [ "//build/config/compiler:enable_arc" ] + + deps = [ + ":steps", + "//base", + "//ios/clean/chrome/app:application_state", + "//testing/gtest", + "//third_party/ocmock", + ] +}
diff --git a/ios/clean/chrome/app/steps/root_coordinator+application_step.h b/ios/clean/chrome/app/steps/root_coordinator+application_step.h new file mode 100644 index 0000000..4558831 --- /dev/null +++ b/ios/clean/chrome/app/steps/root_coordinator+application_step.h
@@ -0,0 +1,21 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CLEAN_CHROME_APP_STEPS_ROOT_COORDINATOR_APPLICATION_STEP_H_ +#define IOS_CLEAN_CHROME_APP_STEPS_ROOT_COORDINATOR_APPLICATION_STEP_H_ + +#import "ios/clean/chrome/app/application_step.h" +#import "ios/clean/chrome/browser/ui/root/root_coordinator.h" + +// Category on RootCoordinator to allow it to act as an application +// step and control the root UI for the application when is starts. +// Creates the main window and makes it key, but doesn't make it visible yet. +// Pre: Application phase is APPLICATION_FOREGROUNDED and the main window is +// key. +// Post: Application phase is (still) APPLICATION_FOREGROUNDED, the main window +// is visible and has a root view controller set. +@interface RootCoordinator (ApplicationStep)<ApplicationStep> +@end + +#endif // IOS_CLEAN_CHROME_APP_STEPS_ROOT_COORDINATOR_APPLICATION_STEP_H_
diff --git a/ios/clean/chrome/app/steps/tab_grid_coordinator+application_step.mm b/ios/clean/chrome/app/steps/root_coordinator+application_step.mm similarity index 85% rename from ios/clean/chrome/app/steps/tab_grid_coordinator+application_step.mm rename to ios/clean/chrome/app/steps/root_coordinator+application_step.mm index 5e6ebbe..73da4e99 100644 --- a/ios/clean/chrome/app/steps/tab_grid_coordinator+application_step.mm +++ b/ios/clean/chrome/app/steps/root_coordinator+application_step.mm
@@ -1,8 +1,8 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. +// Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/clean/chrome/app/steps/tab_grid_coordinator+application_step.h" +#import "ios/clean/chrome/app/steps/root_coordinator+application_step.h" #import "base/supports_user_data.h" #import "ios/clean/chrome/app/application_state.h" @@ -31,10 +31,10 @@ const char kRootCoordinatorContainerKey[] = "root_coordinator"; } // namespace -@interface StopTabGridCoordinator : NSObject<ApplicationStep> +@interface StopRootCoordinator : NSObject<ApplicationStep> @end -@implementation TabGridCoordinator (ApplicationStep) +@implementation RootCoordinator (ApplicationStep) - (BOOL)canRunInState:(ApplicationState*)state { return [state.window isKeyWindow] && state.phase == APPLICATION_FOREGROUNDED; @@ -61,12 +61,12 @@ new RootCoordinatorContainer(self)); // Add a termination step to remove this object. - [[state terminationSteps] addObject:[[StopTabGridCoordinator alloc] init]]; + [[state terminationSteps] addObject:[[StopRootCoordinator alloc] init]]; } @end -@implementation StopTabGridCoordinator +@implementation StopRootCoordinator - (BOOL)canRunInState:(ApplicationState*)state { return state.phase = APPLICATION_TERMINATING;
diff --git a/ios/clean/chrome/app/steps/root_coordinator+application_step_unittest.mm b/ios/clean/chrome/app/steps/root_coordinator+application_step_unittest.mm new file mode 100644 index 0000000..00a84ca --- /dev/null +++ b/ios/clean/chrome/app/steps/root_coordinator+application_step_unittest.mm
@@ -0,0 +1,61 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/clean/chrome/app/steps/root_coordinator+application_step.h" + +#include "base/macros.h" +#import "ios/clean/chrome/app/application_state.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" +#import "third_party/ocmock/OCMock/OCMock.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { + +class RootCoordinatorApplicationStepTest : public PlatformTest { + public: + RootCoordinatorApplicationStepTest() { + coordinator_ = [[RootCoordinator alloc] init]; + state_ = [[ApplicationState alloc] init]; + window_ = OCMClassMock([UIWindow class]); + } + + protected: + RootCoordinator* coordinator_; + ApplicationState* state_; + id window_; + + private: + DISALLOW_COPY_AND_ASSIGN(RootCoordinatorApplicationStepTest); +}; + +// Tests that the coordinator can run if the window is key and application is +// foregrounded. +TEST_F(RootCoordinatorApplicationStepTest, TestRunsInKeyWindow) { + state_.phase = APPLICATION_FOREGROUNDED; + state_.window = window_; + OCMStub([window_ isKeyWindow]).andReturn(YES); + EXPECT_TRUE([coordinator_ canRunInState:state_]); +} + +// Tests that the coordinator cannot run if the window is not key. +TEST_F(RootCoordinatorApplicationStepTest, TestCannotRunWithoutKeyWindow) { + state_.phase = APPLICATION_FOREGROUNDED; + state_.window = window_; + OCMStub([window_ isKeyWindow]).andReturn(NO); + EXPECT_FALSE([coordinator_ canRunInState:state_]); +} + +// Tests that the coordinator cannot run if application is not foregrounded. +TEST_F(RootCoordinatorApplicationStepTest, TestCannotRunIfNotForegrounded) { + state_.phase = APPLICATION_COLD; + state_.window = window_; + OCMStub([window_ isKeyWindow]).andReturn(YES); + EXPECT_FALSE([coordinator_ canRunInState:state_]); +} + +} // namespace
diff --git a/ios/clean/chrome/app/steps/tab_grid_coordinator+application_step.h b/ios/clean/chrome/app/steps/tab_grid_coordinator+application_step.h deleted file mode 100644 index 341bb37f..0000000 --- a/ios/clean/chrome/app/steps/tab_grid_coordinator+application_step.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CLEAN_CHROME_APP_STEPS_TAB_GRID_COORDINATOR_APPLICATION_STEP_H_ -#define IOS_CLEAN_CHROME_APP_STEPS_TAB_GRID_COORDINATOR_APPLICATION_STEP_H_ - -#import <UIKit/UIKit.h> - -#import "ios/clean/chrome/app/application_step.h" -#import "ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.h" - -// Category on TabGridCoordinator to allow it to act as an application step -// and control the root UI for the application when is starts. -// Creates the main window and makes it key, but doesn't make it visible yet. -// Pre: Application phase is APPLICATION_FOREGROUNDED and the main window is -// key. -// Post: Application phase is (still) APPLICATION_FOREGROUNDED, the main window -// is visible and has a root view controller set. -@interface TabGridCoordinator (ApplicationStep)<ApplicationStep> -@end - -#endif // IOS_CLEAN_CHROME_APP_STEPS_TAB_GRID_COORDINATOR_APPLICATION_STEP_H_
diff --git a/ios/clean/chrome/browser/ui/find_in_page/BUILD.gn b/ios/clean/chrome/browser/ui/find_in_page/BUILD.gn index 1274e30a..a53b364 100644 --- a/ios/clean/chrome/browser/ui/find_in_page/BUILD.gn +++ b/ios/clean/chrome/browser/ui/find_in_page/BUILD.gn
@@ -48,3 +48,20 @@ libs = [ "UIKit.framework" ] configs += [ "//build/config/compiler:enable_arc" ] } + +source_set("unit_tests") { + sources = [ + "find_in_page_mediator_unittest.mm", + ] + deps = [ + ":find_in_page", + ":find_in_page_ui", + "//base", + "//ios/chrome/browser/web_state_list", + "//ios/chrome/browser/web_state_list:test_support", + "//testing/gtest", + "//third_party/ocmock", + ] + configs += [ "//build/config/compiler:enable_arc" ] + testonly = true +}
diff --git a/ios/clean/chrome/browser/ui/find_in_page/find_in_page_mediator.mm b/ios/clean/chrome/browser/ui/find_in_page/find_in_page_mediator.mm index c3a269a..c5f7900 100644 --- a/ios/clean/chrome/browser/ui/find_in_page/find_in_page_mediator.mm +++ b/ios/clean/chrome/browser/ui/find_in_page/find_in_page_mediator.mm
@@ -60,6 +60,10 @@ return self; } +- (void)dealloc { + _webStateList->RemoveObserver(_webStateListObserver.get()); +} + - (void)stopFinding { web::WebState* webState = self.webStateList->GetActiveWebState(); FindTabHelper* helper = FindTabHelper::FromWebState(webState);
diff --git a/ios/clean/chrome/browser/ui/find_in_page/find_in_page_mediator_unittest.mm b/ios/clean/chrome/browser/ui/find_in_page/find_in_page_mediator_unittest.mm new file mode 100644 index 0000000..a147a2b --- /dev/null +++ b/ios/clean/chrome/browser/ui/find_in_page/find_in_page_mediator_unittest.mm
@@ -0,0 +1,42 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/clean/chrome/browser/ui/find_in_page/find_in_page_mediator.h" + +#include "base/memory/ptr_util.h" +#include "ios/chrome/browser/web_state_list/fake_web_state_list_delegate.h" +#include "ios/chrome/browser/web_state_list/web_state_list.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" +#import "third_party/ocmock/OCMock/OCMock.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { + +class FindInPageMediatorTest : public PlatformTest { + public: + FindInPageMediatorTest() { + web_state_list_ = base::MakeUnique<WebStateList>(&web_state_list_delegate_); + provider_ = [OCMockObject + niceMockForProtocol:@protocol(FindInPageConsumerProvider)]; + } + + protected: + std::unique_ptr<WebStateList> web_state_list_; + FakeWebStateListDelegate web_state_list_delegate_; + id provider_; +}; + +} // namespace + +TEST_F(FindInPageMediatorTest, Init) { + FindInPageMediator* mediator = + [[FindInPageMediator alloc] initWithWebStateList:web_state_list_.get() + provider:provider_ + dispatcher:nil]; + [mediator self]; +}
diff --git a/ios/clean/chrome/browser/ui/root/BUILD.gn b/ios/clean/chrome/browser/ui/root/BUILD.gn new file mode 100644 index 0000000..1eaadd7d --- /dev/null +++ b/ios/clean/chrome/browser/ui/root/BUILD.gn
@@ -0,0 +1,50 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("root") { + sources = [ + "root_coordinator.h", + "root_coordinator.mm", + ] + deps = [ + ":root_ui", + "//ios/clean/chrome/browser", + "//ios/clean/chrome/browser/ui/commands", + "//ios/clean/chrome/browser/ui/tab_grid", + "//ios/shared/chrome/browser/ui/browser_list", + "//ios/shared/chrome/browser/ui/commands", + "//ios/shared/chrome/browser/ui/coordinators", + ] + configs += [ "//build/config/compiler:enable_arc" ] +} + +source_set("root_ui") { + sources = [ + "root_container_view_controller.h", + "root_container_view_controller.mm", + ] + deps = [ + "//base", + "//ios/clean/chrome/browser/ui/animators", + ] + configs += [ "//build/config/compiler:enable_arc" ] +} + +source_set("unit_tests") { + sources = [ + "root_container_view_controller_unittest.mm", + "root_coordinator_unittest.mm", + ] + deps = [ + ":root", + ":root_ui", + "//base", + "//ios/clean/chrome/browser", + "//ios/clean/chrome/browser/ui/animators", + "//testing/gtest", + "//third_party/ocmock", + ] + configs += [ "//build/config/compiler:enable_arc" ] + testonly = true +}
diff --git a/ios/clean/chrome/browser/ui/root/root_container_view_controller.h b/ios/clean/chrome/browser/ui/root/root_container_view_controller.h new file mode 100644 index 0000000..f0693941 --- /dev/null +++ b/ios/clean/chrome/browser/ui/root/root_container_view_controller.h
@@ -0,0 +1,21 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CLEAN_CHROME_BROWSER_UI_ROOT_ROOT_CONTAINER_VIEW_CONTROLLER_H_ +#define IOS_CLEAN_CHROME_BROWSER_UI_ROOT_ROOT_CONTAINER_VIEW_CONTROLLER_H_ + +#import <UIKit/UIKit.h> + +#import "ios/clean/chrome/browser/ui/animators/zoom_transition_delegate.h" + +// View controller that wholly contains a content view controller. +@interface RootContainerViewController + : UIViewController<ZoomTransitionDelegate> + +// View controller showing the main content. +@property(nonatomic, strong) UIViewController* contentViewController; + +@end + +#endif // IOS_CLEAN_CHROME_BROWSER_UI_ROOT_ROOT_CONTAINER_VIEW_CONTROLLER_H_
diff --git a/ios/clean/chrome/browser/ui/root/root_container_view_controller.mm b/ios/clean/chrome/browser/ui/root/root_container_view_controller.mm new file mode 100644 index 0000000..8a7467b --- /dev/null +++ b/ios/clean/chrome/browser/ui/root/root_container_view_controller.mm
@@ -0,0 +1,72 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/clean/chrome/browser/ui/root/root_container_view_controller.h" + +#include "base/logging.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@implementation RootContainerViewController +@synthesize contentViewController = _contentViewController; + +#pragma mark - UIViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor blackColor]; + [self attachChildViewController:self.contentViewController]; +} + +#pragma mark - Public properties + +- (void)setContentViewController:(UIViewController*)contentViewController { + if (self.contentViewController == contentViewController) + return; + if ([self isViewLoaded]) { + [self detachChildViewController:self.contentViewController]; + [self attachChildViewController:contentViewController]; + } + _contentViewController = contentViewController; +} + +#pragma mark - ChildViewController helper methods + +- (void)attachChildViewController:(UIViewController*)viewController { + if (!viewController) { + return; + } + [self addChildViewController:viewController]; + viewController.view.autoresizingMask = + UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + viewController.view.frame = self.view.bounds; + [self.view addSubview:viewController.view]; + [viewController didMoveToParentViewController:self]; +} + +- (void)detachChildViewController:(UIViewController*)viewController { + if (!viewController) { + return; + } + DCHECK_EQ(self, viewController.parentViewController); + [viewController willMoveToParentViewController:nil]; + [viewController.view removeFromSuperview]; + [viewController removeFromParentViewController]; +} + +#pragma mark - ZoomTransitionDelegate + +- (CGRect)rectForZoomWithKey:(NSObject*)key inView:(UIView*)view { + if ([self.contentViewController + conformsToProtocol:@protocol(ZoomTransitionDelegate)]) { + return [static_cast<id<ZoomTransitionDelegate>>(self.contentViewController) + rectForZoomWithKey:key + inView:view]; + } + return CGRectNull; +} + +@end
diff --git a/ios/clean/chrome/browser/ui/root/root_container_view_controller_unittest.mm b/ios/clean/chrome/browser/ui/root/root_container_view_controller_unittest.mm new file mode 100644 index 0000000..ddb39002 --- /dev/null +++ b/ios/clean/chrome/browser/ui/root/root_container_view_controller_unittest.mm
@@ -0,0 +1,88 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/clean/chrome/browser/ui/root/root_container_view_controller.h" + +#include "base/macros.h" +#import "ios/clean/chrome/browser/ui/animators/zoom_transition_delegate.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" +#import "third_party/ocmock/OCMock/OCMock.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { + +class RootContainerViewControllerTest : public PlatformTest { + public: + RootContainerViewControllerTest() { + rootViewController_ = [[RootContainerViewController alloc] init]; + contentViewController_ = [[UIViewController alloc] init]; + } + + protected: + RootContainerViewController* rootViewController_; + UIViewController* contentViewController_; + + private: + DISALLOW_COPY_AND_ASSIGN(RootContainerViewControllerTest); +}; + +// Tests that RootContainerViewController conforms to ZoomTransitionDelegate. +TEST_F(RootContainerViewControllerTest, TestConformsToZoomTransitionDelegate) { + EXPECT_TRUE([RootContainerViewController + conformsToProtocol:@protocol(ZoomTransitionDelegate)]); +} + +// Tests that calls to |rectForZoomWithKey| are forwarded to the +// contentViewController. +TEST_F(RootContainerViewControllerTest, TestForwardingMethod) { + id contentViewController = OCMProtocolMock(@protocol(ZoomTransitionDelegate)); + rootViewController_.contentViewController = contentViewController; + [rootViewController_ rectForZoomWithKey:nil inView:nil]; + [[contentViewController verify] rectForZoomWithKey:[OCMArg any] + inView:[OCMArg any]]; +} + +// Tests that there are no child view controllers before loading the view. +TEST_F(RootContainerViewControllerTest, TestNotLoadingView) { + EXPECT_EQ(0u, rootViewController_.childViewControllers.count); + rootViewController_.contentViewController = contentViewController_; + EXPECT_EQ(0u, rootViewController_.childViewControllers.count); +} + +// Tests setting the content view before loading the view controller. +TEST_F(RootContainerViewControllerTest, TestSettingContentBeforeLoadingView) { + rootViewController_.contentViewController = contentViewController_; + EXPECT_EQ(0u, rootViewController_.childViewControllers.count); + [rootViewController_ loadViewIfNeeded]; + EXPECT_EQ(1u, rootViewController_.childViewControllers.count); + EXPECT_EQ([rootViewController_.childViewControllers lastObject], + contentViewController_); +} + +// Tests setting the content view after loading the view controller. +TEST_F(RootContainerViewControllerTest, TestSettingContentAfterLoadingView) { + [rootViewController_ loadViewIfNeeded]; + EXPECT_EQ(0u, rootViewController_.childViewControllers.count); + rootViewController_.contentViewController = contentViewController_; + EXPECT_EQ(1u, rootViewController_.childViewControllers.count); + EXPECT_EQ([rootViewController_.childViewControllers lastObject], + contentViewController_); +} + +// Tests that content has changed properly. +TEST_F(RootContainerViewControllerTest, TestChangingContent) { + rootViewController_.contentViewController = contentViewController_; + [rootViewController_ loadViewIfNeeded]; + UIViewController* differentViewController = [[UIViewController alloc] init]; + rootViewController_.contentViewController = differentViewController; + EXPECT_EQ(1u, rootViewController_.childViewControllers.count); + EXPECT_EQ([rootViewController_.childViewControllers lastObject], + differentViewController); +} + +} // namespace
diff --git a/ios/clean/chrome/browser/ui/root/root_coordinator.h b/ios/clean/chrome/browser/ui/root/root_coordinator.h new file mode 100644 index 0000000..bbd8821 --- /dev/null +++ b/ios/clean/chrome/browser/ui/root/root_coordinator.h
@@ -0,0 +1,15 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CLEAN_CHROME_BROWSER_UI_ROOT_ROOT_COORDINATOR_H_ +#define IOS_CLEAN_CHROME_BROWSER_UI_ROOT_ROOT_COORDINATOR_H_ + +#import "ios/clean/chrome/browser/url_opening.h" +#import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator.h" + +// Coordinator that runs the root container. +@interface RootCoordinator : BrowserCoordinator<URLOpening> +@end + +#endif // IOS_CLEAN_CHROME_BROWSER_UI_ROOT_ROOT_COORDINATOR_H_
diff --git a/ios/clean/chrome/browser/ui/root/root_coordinator.mm b/ios/clean/chrome/browser/ui/root/root_coordinator.mm new file mode 100644 index 0000000..af9bb884 --- /dev/null +++ b/ios/clean/chrome/browser/ui/root/root_coordinator.mm
@@ -0,0 +1,70 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/clean/chrome/browser/ui/root/root_coordinator.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#import "ios/clean/chrome/browser/ui/root/root_container_view_controller.h" +#import "ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.h" +#import "ios/shared/chrome/browser/ui/browser_list/browser.h" +#import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface RootCoordinator () +@property(nonatomic, strong) RootContainerViewController* viewController; +@property(nonatomic, weak) TabGridCoordinator* tabGridCoordinator; +@end + +@implementation RootCoordinator +@synthesize viewController = _viewController; +@synthesize tabGridCoordinator = _tabGridCoordinator; + +#pragma mark - BrowserCoordinator + +- (void)start { + self.viewController = [[RootContainerViewController alloc] init]; + + TabGridCoordinator* tabGridCoordinator = [[TabGridCoordinator alloc] init]; + [self addChildCoordinator:tabGridCoordinator]; + [tabGridCoordinator start]; + self.tabGridCoordinator = tabGridCoordinator; + + [super start]; +} + +- (void)stop { + [super stop]; + // PLACEHOLDER: Stop child coordinators here for now. We might deal with this + // differently later on. + for (BrowserCoordinator* child in self.children) { + [child stop]; + [self removeChildCoordinator:child]; + } +} + +- (void)childCoordinatorDidStart:(BrowserCoordinator*)childCoordinator { + self.viewController.contentViewController = childCoordinator.viewController; +} + +- (void)childCoordinatorWillStop:(BrowserCoordinator*)childCoordinator { + self.viewController.contentViewController = nil; +} + +- (BOOL)canAddOverlayCoordinator:(BrowserCoordinator*)overlayCoordinator { + return YES; +} + +#pragma mark - URLOpening + +- (void)openURL:(NSURL*)URL { + [self.tabGridCoordinator openURL:URL]; +} + +@end
diff --git a/ios/clean/chrome/browser/ui/root/root_coordinator_unittest.mm b/ios/clean/chrome/browser/ui/root/root_coordinator_unittest.mm new file mode 100644 index 0000000..db6a92a3 --- /dev/null +++ b/ios/clean/chrome/browser/ui/root/root_coordinator_unittest.mm
@@ -0,0 +1,21 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/clean/chrome/browser/ui/root/root_coordinator.h" + +#import "ios/clean/chrome/browser/url_opening.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { + +// Tests that RootCoordinator conforms to the URLOpening protocol. +TEST(RootCoordinatorTest, TestConformsToURLOpening) { + EXPECT_TRUE([RootCoordinator conformsToProtocol:@protocol(URLOpening)]); +} + +} // namespace
diff --git a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm index 29f2180..60e799e5 100644 --- a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm +++ b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -88,6 +88,11 @@ - (void)stop { [super stop]; [self.browser->dispatcher() stopDispatchingToTarget:self]; + [self.mediator disconnect]; + for (BrowserCoordinator* child in self.children) { + [child stop]; + [self removeChildCoordinator:child]; + } } - (void)childCoordinatorDidStart:(BrowserCoordinator*)childCoordinator {
diff --git a/ios/clean/chrome/test/BUILD.gn b/ios/clean/chrome/test/BUILD.gn index 904904a..9c6b6d5 100644 --- a/ios/clean/chrome/test/BUILD.gn +++ b/ios/clean/chrome/test/BUILD.gn
@@ -19,11 +19,14 @@ ios_packed_resources_target, # Add unit_tests target here. + "//ios/clean/chrome/app/steps:unit_tests", "//ios/clean/chrome/browser/ui/bookmarks:unit_tests", "//ios/clean/chrome/browser/ui/context_menu:unit_tests", + "//ios/clean/chrome/browser/ui/find_in_page:unit_tests", "//ios/clean/chrome/browser/ui/ntp:unit_tests", "//ios/clean/chrome/browser/ui/omnibox:unit_tests", "//ios/clean/chrome/browser/ui/recent_tabs:unit_tests", + "//ios/clean/chrome/browser/ui/root:unit_tests", "//ios/clean/chrome/browser/ui/tab_collection:unit_tests", "//ios/clean/chrome/browser/ui/tab_grid:unit_tests", "//ios/clean/chrome/browser/ui/toolbar:unit_tests",
diff --git a/ios/showcase/BUILD.gn b/ios/showcase/BUILD.gn index 3dd7d51c..307589671 100644 --- a/ios/showcase/BUILD.gn +++ b/ios/showcase/BUILD.gn
@@ -28,6 +28,7 @@ "//ios/clean/chrome/browser/ui/tools:tools_ui", "//ios/showcase/content_suggestions", "//ios/showcase/payments", + "//ios/showcase/root", "//ios/showcase/settings", "//ios/showcase/tab", "//ios/showcase/tab_grid", @@ -54,6 +55,7 @@ "//ios/showcase/content_suggestions:eg_tests", "//ios/showcase/core:eg_tests", "//ios/showcase/payments:eg_tests", + "//ios/showcase/root:eg_tests", "//ios/showcase/tab:eg_tests", "//ios/showcase/tab_grid:eg_tests",
diff --git a/ios/showcase/common/coordinator.h b/ios/showcase/common/coordinator.h index d044a03..335038c 100644 --- a/ios/showcase/common/coordinator.h +++ b/ios/showcase/common/coordinator.h
@@ -5,7 +5,7 @@ #ifndef IOS_SHOWCASE_COMMON_COORDINATOR_H_ #define IOS_SHOWCASE_COMMON_COORDINATOR_H_ -#import <Foundation/Foundation.h> +#import <UIKit/UIKit.h> // This protocol is the common interface to the simple non-production // coordinators that will initialize, set up and present production view
diff --git a/ios/showcase/core/showcase_model.mm b/ios/showcase/core/showcase_model.mm index a4ddad547..83a4d18b 100644 --- a/ios/showcase/core/showcase_model.mm +++ b/ios/showcase/core/showcase_model.mm
@@ -37,6 +37,11 @@ showcase::kUseCaseKey : @"Payment request picker view", }, @{ + showcase::kClassForDisplayKey : @"RootContainerViewController", + showcase::kClassForInstantiationKey : @"SCRootCoordinator", + showcase::kUseCaseKey : @"Root container", + }, + @{ showcase::kClassForDisplayKey : @"SettingsViewController", showcase::kClassForInstantiationKey : @"SCSettingsCoordinator", showcase::kUseCaseKey : @"Main settings screen",
diff --git a/ios/showcase/root/BUILD.gn b/ios/showcase/root/BUILD.gn new file mode 100644 index 0000000..64f5f25 --- /dev/null +++ b/ios/showcase/root/BUILD.gn
@@ -0,0 +1,30 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("root") { + sources = [ + "sc_root_coordinator.h", + "sc_root_coordinator.mm", + ] + deps = [ + "//base", + "//ios/clean/chrome/browser/ui/root:root_ui", + "//ios/showcase/common", + ] + libs = [ "UIKit.framework" ] + configs += [ "//build/config/compiler:enable_arc" ] +} + +source_set("eg_tests") { + testonly = true + sources = [ + "sc_root_egtest.mm", + ] + deps = [ + "//ios/showcase/test", + "//ios/third_party/earl_grey", + ] + libs = [ "XCTest.framework" ] + configs += [ "//build/config/compiler:enable_arc" ] +}
diff --git a/ios/showcase/root/sc_root_coordinator.h b/ios/showcase/root/sc_root_coordinator.h new file mode 100644 index 0000000..bbabf7d --- /dev/null +++ b/ios/showcase/root/sc_root_coordinator.h
@@ -0,0 +1,15 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_SHOWCASE_ROOT_SC_ROOT_COORDINATOR_H_ +#define IOS_SHOWCASE_ROOT_SC_ROOT_COORDINATOR_H_ + +#import <Foundation/Foundation.h> + +#import "ios/showcase/common/navigation_coordinator.h" + +@interface SCRootCoordinator : NSObject<NavigationCoordinator> +@end + +#endif // IOS_SHOWCASE_ROOT_SC_ROOT_COORDINATOR_H_
diff --git a/ios/showcase/root/sc_root_coordinator.mm b/ios/showcase/root/sc_root_coordinator.mm new file mode 100644 index 0000000..a837771 --- /dev/null +++ b/ios/showcase/root/sc_root_coordinator.mm
@@ -0,0 +1,27 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/showcase/root/sc_root_coordinator.h" + +#import "ios/clean/chrome/browser/ui/root/root_container_view_controller.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@implementation SCRootCoordinator + +@synthesize baseViewController; + +- (void)start { + RootContainerViewController* viewController = + [[RootContainerViewController alloc] init]; + UIViewController* contentViewController = [[UIViewController alloc] init]; + contentViewController.view.backgroundColor = [UIColor greenColor]; + viewController.contentViewController = contentViewController; + viewController.title = @"Root container"; + [self.baseViewController pushViewController:viewController animated:YES]; +} + +@end
diff --git a/ios/showcase/root/sc_root_egtest.mm b/ios/showcase/root/sc_root_egtest.mm new file mode 100644 index 0000000..4b3c26e --- /dev/null +++ b/ios/showcase/root/sc_root_egtest.mm
@@ -0,0 +1,26 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import <EarlGrey/EarlGrey.h> + +#import "ios/showcase/test/showcase_eg_utils.h" +#import "ios/showcase/test/showcase_test_case.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +// Tests for the root container view controller. +@interface SCRootTestCase : ShowcaseTestCase +@end + +@implementation SCRootTestCase + +// Tests launching RootContainerViewController. +- (void)testLaunch { + showcase_utils::Open(@"RootContainerViewController"); + showcase_utils::Close(); +} + +@end
diff --git a/media/BUILD.gn b/media/BUILD.gn index 71cfeb4..8d97ec5 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn
@@ -324,11 +324,15 @@ "filters/ffmpeg_demuxer.cc", "filters/ffmpeg_demuxer.h", "filters/ffmpeg_glue.cc", - "filters/ffmpeg_video_decoder.cc", - "filters/ffmpeg_video_decoder.h", "filters/in_memory_url_protocol.cc", "filters/in_memory_url_protocol.h", ] + if (!disable_ffmpeg_video_decoders) { + sources += [ + "filters/ffmpeg_video_decoder.cc", + "filters/ffmpeg_video_decoder.h", + ] + } if (proprietary_codecs) { sources += [ "filters/ffmpeg_aac_bitstream_converter.cc", @@ -372,24 +376,21 @@ deps += [ "//third_party/libvpx" ] } - if (is_android) { - # On Android, FFmpeg is built without video decoders. We only - # support hardware video decoding. - if (disable_ffmpeg_video_decoders) { + if (disable_ffmpeg_video_decoders) { sources -= [ - "filters/ffmpeg_video_decoder.cc", - "filters/ffmpeg_video_decoder.h", + "filters/decrypting_video_decoder.cc", + "filters/decrypting_video_decoder.h", ] - } - sources += [ - "filters/android/media_codec_audio_decoder.cc", - "filters/android/media_codec_audio_decoder.h", - ] + } + + if (is_android) { sources -= [ "filters/decrypting_audio_decoder.cc", "filters/decrypting_audio_decoder.h", - "filters/decrypting_video_decoder.cc", - "filters/decrypting_video_decoder.h", + ] + sources += [ + "filters/android/media_codec_audio_decoder.cc", + "filters/android/media_codec_audio_decoder.h", ] } @@ -624,7 +625,7 @@ data_deps = [] - if (is_android) { + if (disable_ffmpeg_video_decoders) { sources -= [ "filters/decrypting_audio_decoder_unittest.cc", "filters/decrypting_video_decoder_unittest.cc", @@ -657,9 +658,8 @@ "//third_party/opus", ] - if (!is_android) { + if (!disable_ffmpeg_video_decoders) { sources += [ - # FFmpeg on Android does not include video decoders. "filters/ffmpeg_video_decoder_unittest.cc", ] }
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc index 85ff96e..a1d059e 100644 --- a/media/audio/cras/audio_manager_cras.cc +++ b/media/audio/cras/audio_manager_cras.cc
@@ -16,6 +16,7 @@ #include "base/nix/xdg_util.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" +#include "base/sys_info.h" #include "chromeos/audio/audio_device.h" #include "chromeos/audio/cras_audio_handler.h" #include "media/audio/audio_device_description.h" @@ -295,12 +296,23 @@ return MakeInputStream(params, device_id); } +int AudioManagerCras::GetMinimumOutputBufferSizePerBoard() { + // On faster boards we can use smaller buffer size for lower latency. + // On slower boards we should use larger buffer size to prevent underrun. + std::string board = base::SysInfo::GetLsbReleaseBoard(); + if (board == "kevin") + return 768; + else if (board == "samus") + return 256; + return kMinimumOutputBufferSize; +} + AudioParameters AudioManagerCras::GetPreferredOutputStreamParameters( const std::string& output_device_id, const AudioParameters& input_params) { ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO; int sample_rate = kDefaultSampleRate; - int buffer_size = kMinimumOutputBufferSize; + int buffer_size = GetMinimumOutputBufferSizePerBoard(); int bits_per_sample = 16; if (input_params.IsValid()) { sample_rate = input_params.sample_rate();
diff --git a/media/audio/cras/audio_manager_cras.h b/media/audio/cras/audio_manager_cras.h index e5a4b5b..e50ad24 100644 --- a/media/audio/cras/audio_manager_cras.h +++ b/media/audio/cras/audio_manager_cras.h
@@ -72,6 +72,9 @@ AudioInputStream* MakeInputStream(const AudioParameters& params, const std::string& device_id); + // Get minimum output buffer size for this board. + int GetMinimumOutputBufferSizePerBoard(); + void GetAudioDeviceNamesImpl(bool is_input, AudioDeviceNames* device_names); void AddBeamformingDevices(AudioDeviceNames* device_names);
diff --git a/media/filters/decoder_selector.cc b/media/filters/decoder_selector.cc index 3d6854f..c4271060 100644 --- a/media/filters/decoder_selector.cc +++ b/media/filters/decoder_selector.cc
@@ -20,7 +20,7 @@ #include "media/filters/decoder_stream_traits.h" #include "media/filters/decrypting_demuxer_stream.h" -#if !defined(OS_ANDROID) +#if !defined(DISABLE_FFMPEG_VIDEO_DECODERS) #include "media/filters/decrypting_audio_decoder.h" #include "media/filters/decrypting_video_decoder.h" #endif @@ -96,7 +96,7 @@ // When there is a CDM attached, always try the decrypting decoder or // demuxer-stream first. if (cdm_context_) { -#if !defined(OS_ANDROID) +#if !defined(DISABLE_FFMPEG_VIDEO_DECODERS) InitializeDecryptingDecoder(); #else InitializeDecryptingDemuxerStream(); @@ -112,7 +112,7 @@ InitializeDecoder(); } -#if !defined(OS_ANDROID) +#if !defined(DISABLE_FFMPEG_VIDEO_DECODERS) template <DemuxerStream::Type StreamType> void DecoderSelector<StreamType>::InitializeDecryptingDecoder() { DVLOG(2) << __func__; @@ -145,7 +145,7 @@ // DecryptingDemuxerStream to do decrypt-only. InitializeDecryptingDemuxerStream(); } -#endif // !defined(OS_ANDROID) +#endif // !defined(DISABLE_FFMPEG_VIDEO_DECODERS) template <DemuxerStream::Type StreamType> void DecoderSelector<StreamType>::InitializeDecryptingDemuxerStream() {
diff --git a/net/test/android/javatests/AndroidManifest.xml b/net/test/android/javatests/AndroidManifest.xml index c2a2652..341949bc 100644 --- a/net/test/android/javatests/AndroidManifest.xml +++ b/net/test/android/javatests/AndroidManifest.xml
@@ -19,7 +19,9 @@ <service android:name="org.chromium.net.test.EmbeddedTestServerService" android:exported="true" tools:ignore="ExportedService"> - <intent-filter android:action="org.chromium.net.test.EMBEDDED_TEST_SERVER_SERVICE" /> + <intent-filter> + <action android:name="org.chromium.net.test.EMBEDDED_TEST_SERVER_SERVICE" /> + </intent-filter> </service> </application>
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index 820fe5b9..9a2c463 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -220,6 +220,10 @@ #define SK_DISABLE_DEFERRED_PROXIES #endif +#ifndef SK_LEGACY_SWEEP_GRADIENT +#define SK_LEGACY_SWEEP_GRADIENT +#endif + ///////////////////////// Imported from BUILD.gn and skia_common.gypi /* In some places Skia can use static initializers for global initialization,
diff --git a/third_party/WebKit/LayoutTests/SlowTests b/third_party/WebKit/LayoutTests/SlowTests index dca50cc5..54c968a 100644 --- a/third_party/WebKit/LayoutTests/SlowTests +++ b/third_party/WebKit/LayoutTests/SlowTests
@@ -392,3 +392,6 @@ # which can be very slow. crbug.com/678498 external/wpt/service-workers/service-worker/foreign-fetch-cors.https.html [ Slow ] crbug.com/678496 external/wpt/service-workers/service-worker/foreign-fetch-basics.https.html [ Slow ] + +# Slow on Debug +crbug.com/710864 [ Debug ] editing/execCommand/delete-non-editable-range-crash.html [ Slow ]
diff --git a/third_party/WebKit/LayoutTests/svg/animations/target-move-relative-length-invalidation-crash-expected.txt b/third_party/WebKit/LayoutTests/svg/animations/target-move-relative-length-invalidation-crash-expected.txt new file mode 100644 index 0000000..ddad5eaf --- /dev/null +++ b/third_party/WebKit/LayoutTests/svg/animations/target-move-relative-length-invalidation-crash-expected.txt
@@ -0,0 +1 @@ +PASS if no crash
diff --git a/third_party/WebKit/LayoutTests/svg/animations/target-move-relative-length-invalidation-crash.html b/third_party/WebKit/LayoutTests/svg/animations/target-move-relative-length-invalidation-crash.html new file mode 100644 index 0000000..7118f1f --- /dev/null +++ b/third_party/WebKit/LayoutTests/svg/animations/target-move-relative-length-invalidation-crash.html
@@ -0,0 +1,30 @@ +<!DOCTYPE html> +<svg> + <g id="g1"> + <text id="text1"/> + </g> + <g id="g2"> + <text id="text2"/> + <animate values="100" href="#text2" attributeName="x" dur="4s"/> + </g> +</svg> +<p>PASS if no crash</p> +<script> +if (window.testRunner) { + testRunner.dumpAsText(); + testRunner.waitUntilDone(); +} +var g1 = document.getElementById("g1"); +var g2 = document.getElementById("g2"); +var text1 = document.getElementById("text1"); + +window.onload = function() { + requestAnimationFrame(function() { + g1.remove(); + text1.appendChild(document.querySelector("svg")); + g1.appendChild(g2); + if (window.testRunner) + testRunner.notifyDone(); + }); +}; +</script>
diff --git a/third_party/WebKit/Source/core/svg/SVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGElement.cpp index e99a7e4..bf80cca 100644 --- a/third_party/WebKit/Source/core/svg/SVGElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGElement.cpp
@@ -535,10 +535,17 @@ SVGElement* client_element) { DCHECK(client_element); + // Through an unfortunate chain of events, we can end up calling this while a + // subtree is being removed, and before the subtree has been properly + // "disconnected". Hence check the entire ancestor chain to avoid propagating + // relative length clients up into ancestors that have already been + // disconnected. // If we're not yet in a document, this function will be called again from // insertedInto(). Do nothing now. - if (!isConnected()) - return; + for (Node& current_node : NodeTraversal::InclusiveAncestorsOf(*this)) { + if (!current_node.isConnected()) + return; + } // An element wants to notify us that its own relative lengths state changed. // Register it in the relative length map, and register us in the parent
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc index 52fa223..8befec1 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc
@@ -1730,26 +1730,30 @@ TEST_F(TaskQueueManagerTest, TaskQueueObserver_DelayedTask) { Initialize(1u); + base::TimeTicks start_time = manager_->Delegate()->NowTicks(); + base::TimeDelta delay10s(base::TimeDelta::FromSeconds(10)); + base::TimeDelta delay100s(base::TimeDelta::FromSeconds(100)); + base::TimeDelta delay1s(base::TimeDelta::FromSeconds(1)); + MockTaskQueueObserver observer; runners_[0]->SetObserver(&observer); // We should get a notification when a delayed task is posted on an empty // queue. - EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[0].get(), _)); - runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), - base::TimeDelta::FromSeconds(10)); + EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[0].get(), + start_time + delay10s)); + runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), delay10s); Mock::VerifyAndClearExpectations(&observer); // We should not get a notification for a longer delay. EXPECT_CALL(observer, OnQueueNextWakeUpChanged(_, _)).Times(0); - runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), - base::TimeDelta::FromSeconds(100)); + runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), delay100s); Mock::VerifyAndClearExpectations(&observer); // We should get a notification for a shorter delay. - EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[0].get(), _)); - runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), - base::TimeDelta::FromSeconds(1)); + EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[0].get(), + start_time + delay1s)); + runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), delay1s); Mock::VerifyAndClearExpectations(&observer); std::unique_ptr<TaskQueue::QueueEnabledVoter> voter = @@ -1758,7 +1762,8 @@ // When a queue has been enabled, we may get a notification if the // TimeDomain's next scheduled wake-up has changed. - EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[0].get(), _)); + EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[0].get(), + start_time + delay1s)); voter->SetQueueEnabled(true); // Tidy up. @@ -1772,14 +1777,18 @@ runners_[0]->SetObserver(&observer); runners_[1]->SetObserver(&observer); - EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[0].get(), _)) + base::TimeTicks start_time = manager_->Delegate()->NowTicks(); + base::TimeDelta delay1s(base::TimeDelta::FromSeconds(1)); + base::TimeDelta delay10s(base::TimeDelta::FromSeconds(10)); + + EXPECT_CALL(observer, + OnQueueNextWakeUpChanged(runners_[0].get(), start_time + delay1s)) .Times(1); - EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[1].get(), _)) + EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[1].get(), + start_time + delay10s)) .Times(1); - runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), - base::TimeDelta::FromSeconds(1)); - runners_[1]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), - base::TimeDelta::FromSeconds(10)); + runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), delay1s); + runners_[1]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), delay10s); testing::Mock::VerifyAndClearExpectations(&observer); std::unique_ptr<TaskQueue::QueueEnabledVoter> voter0 = @@ -1793,7 +1802,8 @@ Mock::VerifyAndClearExpectations(&observer); // Re-enabling it should should also trigger a notification. - EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[0].get(), _)); + EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[0].get(), + start_time + delay1s)); voter0->SetQueueEnabled(true); Mock::VerifyAndClearExpectations(&observer); @@ -1803,7 +1813,8 @@ Mock::VerifyAndClearExpectations(&observer); // Re-enabling it should should trigger a notification. - EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[1].get(), _)); + EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[1].get(), + start_time + delay10s)); voter1->SetQueueEnabled(true); Mock::VerifyAndClearExpectations(&observer); @@ -1813,6 +1824,56 @@ runners_[1]->UnregisterTaskQueue(); } +class CancelableTask { + public: + explicit CancelableTask(base::TickClock* clock) + : clock_(clock), weak_factory_(this) {} + + void RecordTimeTask(std::vector<base::TimeTicks>* run_times) { + run_times->push_back(clock_->NowTicks()); + } + + base::TickClock* clock_; + base::WeakPtrFactory<CancelableTask> weak_factory_; +}; + +TEST_F(TaskQueueManagerTest, TaskQueueObserver_SweepCanceledDelayedTasks) { + Initialize(1u); + + MockTaskQueueObserver observer; + runners_[0]->SetObserver(&observer); + + base::TimeTicks start_time = manager_->Delegate()->NowTicks(); + base::TimeDelta delay1(base::TimeDelta::FromSeconds(5)); + base::TimeDelta delay2(base::TimeDelta::FromSeconds(10)); + + EXPECT_CALL(observer, + OnQueueNextWakeUpChanged(runners_[0].get(), start_time + delay1)) + .Times(1); + + CancelableTask task1(now_src_.get()); + CancelableTask task2(now_src_.get()); + std::vector<base::TimeTicks> run_times; + runners_[0]->PostDelayedTask( + FROM_HERE, + base::Bind(&CancelableTask::RecordTimeTask, + task1.weak_factory_.GetWeakPtr(), &run_times), + delay1); + runners_[0]->PostDelayedTask( + FROM_HERE, + base::Bind(&CancelableTask::RecordTimeTask, + task2.weak_factory_.GetWeakPtr(), &run_times), + delay2); + + task1.weak_factory_.InvalidateWeakPtrs(); + + // Sweeping away canceled delayed tasks should trigger a notification. + EXPECT_CALL(observer, + OnQueueNextWakeUpChanged(runners_[0].get(), start_time + delay2)) + .Times(1); + manager_->SweepCanceledDelayedTasks(); +} + namespace { void ChromiumRunloopInspectionTask( scoped_refptr<cc::OrderedSimpleTaskRunner> test_task_runner) { @@ -2167,19 +2228,6 @@ EXPECT_EQ(2u, events.size()); } -class CancelableTask { - public: - explicit CancelableTask(base::TickClock* clock) - : clock_(clock), weak_factory_(this) {} - - void RecordTimeTask(std::vector<base::TimeTicks>* run_times) { - run_times->push_back(clock_->NowTicks()); - } - - base::TickClock* clock_; - base::WeakPtrFactory<CancelableTask> weak_factory_; -}; - TEST_F(TaskQueueManagerTest, NoWakeUpsForCanceledDelayedTasks) { Initialize(1u);
diff --git a/third_party/qcms/BUILD.gn b/third_party/qcms/BUILD.gn index 1183569b..183ae43 100644 --- a/third_party/qcms/BUILD.gn +++ b/third_party/qcms/BUILD.gn
@@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//testing/libfuzzer/fuzzer_test.gni") + config("qcms_config") { include_dirs = [ "src" ] } @@ -48,6 +50,23 @@ } } +# fuzzers BUILD depends on this target. Needed for package discovery +group("fuzzers") { +} + +fuzzer_test("qcms_color_space_fuzzer") { + sources = [ + "//testing/libfuzzer/fuzzers/color_space_data.h", + "qcms_color_space_fuzzer.cc", + ] + deps = [ + ":qcms", + "//base", + ] + dict = "//testing/libfuzzer/fuzzers/dicts/icc.dict" + libfuzzer_options = [ "max_len=4194304" ] +} + if (!disable_qcms) { executable("qcms_tests") { if (current_cpu == "x86" || current_cpu == "x64") {
diff --git a/third_party/qcms/DEPS b/third_party/qcms/DEPS new file mode 100644 index 0000000..9fedf4a --- /dev/null +++ b/third_party/qcms/DEPS
@@ -0,0 +1,6 @@ +specific_include_rules = { + "qcms_color_space_fuzzer\.cc": [ + "+base", + "+testing/libfuzzer/fuzzers", + ], +}
diff --git a/third_party/qcms/qcms_color_space_fuzzer.cc b/third_party/qcms/qcms_color_space_fuzzer.cc new file mode 100644 index 0000000..be08c88 --- /dev/null +++ b/third_party/qcms/qcms_color_space_fuzzer.cc
@@ -0,0 +1,85 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <cstddef> +#include <cstdint> +#include <random> + +#include "base/logging.h" +#include "testing/libfuzzer/fuzzers/color_space_data.h" +#include "third_party/qcms/src/qcms.h" + +static constexpr size_t kPixels = 2048 / 4; + +static uint32_t pixels[kPixels]; + +static void GeneratePixels(size_t hash) { + static std::uniform_int_distribution<uint32_t> uniform(0u, ~0u); + + std::mt19937_64 random(hash); + for (size_t i = 0; i < arraysize(pixels); ++i) + pixels[i] = uniform(random); +} + +static qcms_profile* test; +static qcms_profile* srgb; + +static void ColorTransform(bool input) { + if (!test) + return; + + const qcms_intent intent = QCMS_INTENT_DEFAULT; + const qcms_data_type format = QCMS_DATA_RGBA_8; + + auto* transform = + input ? qcms_transform_create(test, format, srgb, format, intent) + : qcms_transform_create(srgb, format, test, format, intent); + if (!transform) + return; + + static uint32_t output[kPixels]; + + qcms_transform_data(transform, pixels, output, kPixels); + qcms_transform_release(transform); +} + +static qcms_profile* SelectProfile(size_t hash) { + static qcms_profile* profiles[4] = { + qcms_profile_from_memory(kSRGBData, arraysize(kSRGBData)), + qcms_profile_from_memory(kSRGBPara, arraysize(kSRGBPara)), + qcms_profile_from_memory(kAdobeData, arraysize(kAdobeData)), + qcms_profile_sRGB(), + }; + + return profiles[hash & 3]; +} + +inline size_t Hash(const char* data, size_t size, size_t hash = ~0) { + for (size_t i = 0; i < size; ++i) + hash = hash * 131 + *data++; + return hash; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + constexpr size_t kSizeLimit = 4 * 1024 * 1024; + if (size < 128 || size > kSizeLimit) + return 0; + + test = qcms_profile_from_memory(data, size); + if (!test) + return 0; + + const size_t hash = Hash(reinterpret_cast<const char*>(data), size); + srgb = SelectProfile(hash); + GeneratePixels(hash); + + qcms_profile_precache_output_transform(srgb); + ColorTransform(true); + + qcms_profile_precache_output_transform(test); + ColorTransform(false); + + qcms_profile_release(test); + return 0; +}
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 2a960f1..9ea9c3b 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -41455,6 +41455,24 @@ </summary> </histogram> +<histogram name="NewTabPage.ContentSuggestions.ArticleFaviconFetchResult" + enum="FaviconFetchResult"> + <owner>jkrcal@chromium.org</owner> + <summary> + Android: Result of fetching a favicon for an article suggestion on the New + Tab Page. + </summary> +</histogram> + +<histogram name="NewTabPage.ContentSuggestions.ArticleFaviconFetchTime" + units="ms"> + <owner>jkrcal@chromium.org</owner> + <summary> + Android: Time it takes to fetch a favicon for an article suggestion on the + New Tab Page. + </summary> +</histogram> + <histogram name="NewTabPage.ContentSuggestions.BackgroundFetchTrigger" enum="BackgroundFetchTrigger"> <owner>jkrcal@chromium.org</owner> @@ -83362,6 +83380,9 @@ <int value="22" label="User joined maximum number of machines to the domain"/> <int value="23" label="kinit or smbclient failed to contact Key Distribution Center"/> + <int value="24" label="Kerberos credentials cache not found"/> + <int value="25" label="Kerberos ticket expired while renewing credentials"/> + <int value="26" label="klist exited with unspecified error"/> </enum> <enum name="AutocheckoutBubble" type="int"> @@ -93448,6 +93469,16 @@ </int> </enum> +<enum name="FaviconFetchResult" type="int"> + <int value="0" label="SUCCESS_CACHED"> + Success - favicon found in local cache + </int> + <int value="1" label="SUCCESS_FETCHED"> + Success - favicon fetched from the server + </int> + <int value="2" label="FAILURE">Failure - favicon not available</int> +</enum> + <enum name="FeatureObserver" type="int"> <!-- Generated from third_party/WebKit/Source/core/frame/UseCounter.h -->
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index 442155d..f6856dd 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -876,6 +876,7 @@ "controls/native/native_view_host_unittest.cc", "controls/prefix_selector_unittest.cc", "controls/progress_bar_unittest.cc", + "controls/resize_area_unittest.cc", "controls/scroll_view_unittest.cc", "controls/scrollbar/scrollbar_unittest.cc", "controls/slider_unittest.cc",
diff --git a/ui/views/controls/resize_area.cc b/ui/views/controls/resize_area.cc index 3698078..06c0325 100644 --- a/ui/views/controls/resize_area.cc +++ b/ui/views/controls/resize_area.cc
@@ -14,9 +14,6 @@ const char ResizeArea::kViewClassName[] = "ResizeArea"; -//////////////////////////////////////////////////////////////////////////////// -// ResizeArea - ResizeArea::ResizeArea(ResizeAreaDelegate* delegate) : delegate_(delegate), initial_position_(0) { @@ -34,17 +31,25 @@ : gfx::kNullCursor; } +void ResizeArea::OnGestureEvent(ui::GestureEvent* event) { + if (event->type() == ui::ET_GESTURE_TAP_DOWN) { + SetInitialPosition(event->x()); + event->SetHandled(); + } else if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN || + event->type() == ui::ET_GESTURE_SCROLL_UPDATE) { + ReportResizeAmount(event->x(), false); + event->SetHandled(); + } else if (event->type() == ui::ET_GESTURE_END) { + ReportResizeAmount(event->x(), true); + event->SetHandled(); + } +} + bool ResizeArea::OnMousePressed(const ui::MouseEvent& event) { if (!event.IsOnlyLeftMouseButton()) return false; - // The resize area obviously will move once you start dragging so we need to - // convert coordinates to screen coordinates so that we don't lose our - // bearings. - gfx::Point point(event.x(), 0); - View::ConvertPointToScreen(this, &point); - initial_position_ = point.x(); - + SetInitialPosition(event.x()); return true; } @@ -76,4 +81,10 @@ last_update); } +void ResizeArea::SetInitialPosition(int event_x) { + gfx::Point point(event_x, 0); + View::ConvertPointToScreen(this, &point); + initial_position_ = point.x(); +} + } // namespace views
diff --git a/ui/views/controls/resize_area.h b/ui/views/controls/resize_area.h index 171c80565..31dc6e3 100644 --- a/ui/views/controls/resize_area.h +++ b/ui/views/controls/resize_area.h
@@ -14,11 +14,7 @@ class ResizeAreaDelegate; -//////////////////////////////////////////////////////////////////////////////// -// // An invisible area that acts like a horizontal resizer. -// -//////////////////////////////////////////////////////////////////////////////// class VIEWS_EXPORT ResizeArea : public View { public: static const char kViewClassName[]; @@ -26,9 +22,10 @@ explicit ResizeArea(ResizeAreaDelegate* delegate); ~ResizeArea() override; - // Overridden from views::View: + // views::View: const char* GetClassName() const override; gfx::NativeCursor GetCursor(const ui::MouseEvent& event) override; + void OnGestureEvent(ui::GestureEvent* event) override; bool OnMousePressed(const ui::MouseEvent& event) override; bool OnMouseDragged(const ui::MouseEvent& event) override; void OnMouseReleased(const ui::MouseEvent& event) override; @@ -40,10 +37,16 @@ // directionality. void ReportResizeAmount(int resize_amount, bool last_update); + // Converts |event_x| to screen coordinates and sets |initial_position_| to + // this value. + void SetInitialPosition(int event_x); + // The delegate to notify when we have updates. ResizeAreaDelegate* delegate_; - // The mouse position at start (in screen coordinates). + // The event's x-position at the start of the resize operation. The resize + // area will move while being dragged, so |initial_position_| is represented + // in screen coordinates so that we don't lose our bearings. int initial_position_; DISALLOW_COPY_AND_ASSIGN(ResizeArea);
diff --git a/ui/views/controls/resize_area_delegate.h b/ui/views/controls/resize_area_delegate.h index cc5e133d..ee5e57b 100644 --- a/ui/views/controls/resize_area_delegate.h +++ b/ui/views/controls/resize_area_delegate.h
@@ -16,7 +16,7 @@ // positive (depending on direction of dragging and flips according to // locale directionality: dragging to the left in LTR locales gives negative // |resize_amount| but positive amount for RTL). |done_resizing| is true if - // the user has released the mouse. + // the user has released the pointer (mouse, stylus, touch, etc.). virtual void OnResize(int resize_amount, bool done_resizing) = 0; protected:
diff --git a/ui/views/controls/resize_area_unittest.cc b/ui/views/controls/resize_area_unittest.cc new file mode 100644 index 0000000..8d11df5e --- /dev/null +++ b/ui/views/controls/resize_area_unittest.cc
@@ -0,0 +1,200 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/views/controls/resize_area.h" + +#include <memory> + +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/aura/window.h" +#include "ui/events/test/event_generator.h" +#include "ui/views/controls/resize_area_delegate.h" +#include "ui/views/test/views_test_base.h" +#include "ui/views/view.h" +#include "ui/views/widget/widget.h" + +namespace { +// Constants used by the ResizeAreaTest.SuccessfulGestureDrag test to simulate +// a gesture drag by |kGestureScrollDistance| resulting from +// |kGestureScrollSteps| ui::ET_GESTURE_SCROLL_UPDATE events being delivered. +const int kGestureScrollDistance = 100; +const int kGestureScrollSteps = 4; +const int kDistancePerGestureScrollUpdate = + kGestureScrollDistance / kGestureScrollSteps; +} + +namespace views { + +// Testing delegate used by ResizeAreaTest. +class TestResizeAreaDelegate : public ResizeAreaDelegate { + public: + TestResizeAreaDelegate(); + ~TestResizeAreaDelegate() override; + + // ResizeAreaDelegate: + void OnResize(int resize_amount, bool done_resizing) override; + + int resize_amount() { return resize_amount_; } + bool done_resizing() { return done_resizing_; } + bool on_resize_called() { return on_resize_called_; } + + private: + int resize_amount_; + bool done_resizing_; + bool on_resize_called_; + + DISALLOW_COPY_AND_ASSIGN(TestResizeAreaDelegate); +}; + +TestResizeAreaDelegate::TestResizeAreaDelegate() + : resize_amount_(0), done_resizing_(false), on_resize_called_(false) {} + +TestResizeAreaDelegate::~TestResizeAreaDelegate() {} + +void TestResizeAreaDelegate::OnResize(int resize_amount, bool done_resizing) { + resize_amount_ = resize_amount; + done_resizing_ = done_resizing; + on_resize_called_ = true; +} + +// Test fixture for testing the ResizeArea class. +class ResizeAreaTest : public ViewsTestBase { + public: + ResizeAreaTest(); + ~ResizeAreaTest() override; + + // Callback used by the SuccessfulGestureDrag test. + void ProcessGesture(ui::EventType type, const gfx::Vector2dF& delta); + + protected: + // testing::Test: + void SetUp() override; + void TearDown() override; + + ui::test::EventGenerator* event_generator() { return event_generator_.get(); } + + int resize_amount() { return delegate_->resize_amount(); } + bool done_resizing() { return delegate_->done_resizing(); } + bool on_resize_called() { return delegate_->on_resize_called(); } + views::Widget* widget() { return widget_; } + + private: + std::unique_ptr<TestResizeAreaDelegate> delegate_; + ResizeArea* resize_area_ = nullptr; + views::Widget* widget_ = nullptr; + std::unique_ptr<ui::test::EventGenerator> event_generator_; + + // The number of ui::ET_GESTURE_SCROLL_UPDATE events seen by + // ProcessGesture(). + int gesture_scroll_updates_seen_ = 0; + + DISALLOW_COPY_AND_ASSIGN(ResizeAreaTest); +}; + +ResizeAreaTest::ResizeAreaTest() {} + +ResizeAreaTest::~ResizeAreaTest() {} + +void ResizeAreaTest::ProcessGesture(ui::EventType type, + const gfx::Vector2dF& delta) { + if (type == ui::ET_GESTURE_SCROLL_BEGIN) { + EXPECT_FALSE(done_resizing()); + EXPECT_FALSE(on_resize_called()); + } else if (type == ui::ET_GESTURE_SCROLL_UPDATE) { + gesture_scroll_updates_seen_++; + EXPECT_EQ(kDistancePerGestureScrollUpdate * gesture_scroll_updates_seen_, + resize_amount()); + EXPECT_FALSE(done_resizing()); + EXPECT_TRUE(on_resize_called()); + } else if (type == ui::ET_GESTURE_SCROLL_END) { + EXPECT_TRUE(done_resizing()); + } +} + +void ResizeAreaTest::SetUp() { + views::ViewsTestBase::SetUp(); + + delegate_.reset(new TestResizeAreaDelegate); + resize_area_ = new ResizeArea(delegate_.get()); + + gfx::Size size(10, 10); + resize_area_->SetBounds(0, 0, size.width(), size.height()); + + views::Widget::InitParams init_params( + CreateParams(views::Widget::InitParams::TYPE_WINDOW_FRAMELESS)); + init_params.bounds = gfx::Rect(size); + + widget_ = new views::Widget(); + widget_->Init(init_params); + widget_->SetContentsView(resize_area_); + widget_->Show(); + + event_generator_.reset( + new ui::test::EventGenerator(widget_->GetNativeWindow())); +} + +void ResizeAreaTest::TearDown() { + if (widget_ && !widget_->IsClosed()) + widget_->Close(); + + views::ViewsTestBase::TearDown(); +} + +// TODO(tdanderson): Enable these tests on OSX. See crbug.com/710475. +#if !defined(OS_MACOSX) +// Verifies the correct calls have been made to +// TestResizeAreaDelegate::OnResize() for a sequence of mouse events +// corresponding to a successful resize operation. +TEST_F(ResizeAreaTest, SuccessfulMouseDrag) { + event_generator()->MoveMouseToCenterOf(widget()->GetNativeView()); + event_generator()->PressLeftButton(); + + const int kFirstDragAmount = -5; + event_generator()->MoveMouseBy(kFirstDragAmount, 0); + EXPECT_EQ(kFirstDragAmount, resize_amount()); + EXPECT_FALSE(done_resizing()); + EXPECT_TRUE(on_resize_called()); + + const int kSecondDragAmount = 17; + event_generator()->MoveMouseBy(kSecondDragAmount, 0); + EXPECT_EQ(kFirstDragAmount + kSecondDragAmount, resize_amount()); + EXPECT_FALSE(done_resizing()); + + event_generator()->ReleaseLeftButton(); + EXPECT_EQ(kFirstDragAmount + kSecondDragAmount, resize_amount()); + EXPECT_TRUE(done_resizing()); +} + +// Verifies that no resize is performed when attempting to resize using the +// right mouse button. +TEST_F(ResizeAreaTest, FailedMouseDrag) { + event_generator()->MoveMouseToCenterOf(widget()->GetNativeView()); + event_generator()->PressRightButton(); + + const int kDragAmount = 18; + event_generator()->MoveMouseBy(kDragAmount, 0); + EXPECT_EQ(0, resize_amount()); +} + +// Verifies the correct calls have been made to +// TestResizeAreaDelegate::OnResize() for a sequence of gesture events +// corresponding to a successful resize operation. +TEST_F(ResizeAreaTest, SuccessfulGestureDrag) { + gfx::Point start = widget()->GetNativeView()->bounds().CenterPoint(); + event_generator()->GestureScrollSequenceWithCallback( + start, gfx::Point(start.x() + kGestureScrollDistance, start.y()), + base::TimeDelta::FromMilliseconds(200), kGestureScrollSteps, + base::Bind(&ResizeAreaTest::ProcessGesture, base::Unretained(this))); +} + +// Verifies that no resize is performed on a gesture tap. +TEST_F(ResizeAreaTest, NoDragOnGestureTap) { + event_generator()->GestureTapAt( + widget()->GetNativeView()->bounds().CenterPoint()); + + EXPECT_EQ(0, resize_amount()); +} +#endif // !defined(OS_MACOSX) + +} // namespace views