diff --git a/DEPS b/DEPS index 15e6b53..6bcec07 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'c61abeed8958a757c6b49937f28b63066148dd67', + 'skia_revision': '7928e768728fe7eef9345345c74e810435dd3eac', # 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': '03d03326a57b940fc386775d3efe1f33525c4f2d', + 'v8_revision': '0096d40434210d7c3a0f42eb63f93fd196bb4d36', # 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.
diff --git a/base/security_unittest.cc b/base/security_unittest.cc index 24fbbd7..519c997eb 100644 --- a/base/security_unittest.cc +++ b/base/security_unittest.cc
@@ -87,7 +87,8 @@ } } -#if defined(OS_IOS) || defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) +#if defined(OS_IOS) || defined(ADDRESS_SANITIZER) || \ + defined(THREAD_SANITIZER) || defined(MEMORY_SANITIZER) #define MAYBE_NewOverflow DISABLED_NewOverflow #else #define MAYBE_NewOverflow NewOverflow
diff --git a/build/install-build-deps-android.sh b/build/install-build-deps-android.sh index 37f4244..6ae6e90 100755 --- a/build/install-build-deps-android.sh +++ b/build/install-build-deps-android.sh
@@ -67,6 +67,9 @@ sudo apt-get -y install ant +# Required for apk-patch-size-estimator +sudo apt-get -y install bsdiff + # Install openjdk and openjre stuff sudo apt-get -y install $java_pkgs
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java index 5cfed32..5f492485 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
@@ -36,6 +36,8 @@ import org.chromium.base.VisibleForTesting; import org.chromium.blink.mojom.MediaSessionAction; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeApplication; +import org.chromium.chrome.browser.notifications.ChromeNotificationBuilder; import org.chromium.chrome.browser.notifications.NotificationConstants; import org.chromium.content_public.common.MediaMetadata; @@ -84,7 +86,7 @@ private SparseArray<MediaButtonInfo> mActionToButtonInfo; - private NotificationCompat.Builder mNotificationBuilder; + private ChromeNotificationBuilder mNotificationBuilder; private Bitmap mDefaultNotificationLargeIcon; @@ -539,8 +541,7 @@ @VisibleForTesting @Nullable - static NotificationCompat.Builder getNotificationBuilderForTesting( - int notificationId) { + static ChromeNotificationBuilder getNotificationBuilderForTesting(int notificationId) { MediaNotificationManager manager = getManager(notificationId); if (manager == null) return null; @@ -721,7 +722,15 @@ updateMediaSession(); - mNotificationBuilder = new NotificationCompat.Builder(mContext); + mNotificationBuilder = + ((ChromeApplication) mContext.getApplicationContext()) + .createChromeNotificationBuilder(true, + NotificationConstants.CATEGORY_ID_BROWSER, + mContext.getString( + org.chromium.chrome.R.string.notification_category_browser), + NotificationConstants.CATEGORY_GROUP_ID_GENERAL, + mContext.getString(org.chromium.chrome.R.string + .notification_category_group_general)); setMediaStyleLayoutForNotificationBuilder(mNotificationBuilder); mNotificationBuilder.setSmallIcon(mMediaNotificationInfo.notificationSmallIcon); @@ -853,7 +862,7 @@ mMediaSession.setActive(true); } - private void setMediaStyleLayoutForNotificationBuilder(NotificationCompat.Builder builder) { + private void setMediaStyleLayoutForNotificationBuilder(ChromeNotificationBuilder builder) { setMediaStyleNotificationText(builder); if (!mMediaNotificationInfo.supportsPlayPause()) { builder.setLargeIcon(null); @@ -876,7 +885,7 @@ addNotificationButtons(builder); } - private void addNotificationButtons(NotificationCompat.Builder builder) { + private void addNotificationButtons(ChromeNotificationBuilder builder) { Set<Integer> actions = new HashSet<>(); // TODO(zqzhang): handle other actions when play/pause is not supported? See @@ -907,15 +916,8 @@ // Only apply MediaStyle when NotificationInfo supports play/pause. if (mMediaNotificationInfo.supportsPlayPause()) { - NotificationCompat.MediaStyle style = new NotificationCompat.MediaStyle(); - style.setMediaSession(mMediaSession.getSessionToken()); - - int[] compactViewActionIndices = computeCompactViewActionIndices(bigViewActions); - - style.setShowActionsInCompactView(compactViewActionIndices); - style.setCancelButtonIntent(createPendingIntent(ListenerService.ACTION_CANCEL)); - style.setShowCancelButton(true); - builder.setStyle(style); + builder.setMediaStyle(mMediaSession, computeCompactViewActionIndices(bigViewActions), + createPendingIntent(ListenerService.ACTION_CANCEL), true); } } @@ -926,7 +928,7 @@ return bitmapDrawable.getBitmap(); } - private void setMediaStyleNotificationText(NotificationCompat.Builder builder) { + private void setMediaStyleNotificationText(ChromeNotificationBuilder builder) { builder.setContentTitle(mMediaNotificationInfo.metadata.getTitle()); String artistAndAlbumText = getArtistAndAlbumText(mMediaNotificationInfo.metadata); if (isRunningN() || !artistAndAlbumText.isEmpty()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChromeNotificationBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChromeNotificationBuilder.java index d28cf02..05dea24 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChromeNotificationBuilder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChromeNotificationBuilder.java
@@ -8,6 +8,7 @@ import android.app.PendingIntent; import android.graphics.Bitmap; import android.graphics.drawable.Icon; +import android.support.v4.media.session.MediaSessionCompat; import android.widget.RemoteViews; /** @@ -74,6 +75,9 @@ ChromeNotificationBuilder setStyle(Notification.BigTextStyle bigTextStyle); + ChromeNotificationBuilder setMediaStyle(MediaSessionCompat session, int[] actions, + PendingIntent intent, boolean showCancelButton); + Notification buildWithBigContentView(RemoteViews bigView); Notification buildWithBigTextStyle(String bigText);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilder.java index 5597085..13c19bcc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilder.java
@@ -9,7 +9,9 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.drawable.Icon; +import android.media.session.MediaSession; import android.os.Build; +import android.support.v4.media.session.MediaSessionCompat; import android.widget.RemoteViews; /** @@ -221,6 +223,18 @@ } @Override + public ChromeNotificationBuilder setMediaStyle(MediaSessionCompat session, int[] actions, + PendingIntent intent, boolean showCancelButton) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + Notification.MediaStyle style = new Notification.MediaStyle(); + style.setMediaSession(((MediaSession) session.getMediaSession()).getSessionToken()); + style.setShowActionsInCompactView(actions); + mBuilder.setStyle(style); + } + return this; + } + + @Override public Notification buildWithBigContentView(RemoteViews view) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return mBuilder.setCustomBigContentView(view).build();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationCompatBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationCompatBuilder.java index 78034fd..14b4950 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationCompatBuilder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationCompatBuilder.java
@@ -9,7 +9,8 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.drawable.Icon; -import android.support.v4.app.NotificationCompat; +import android.support.v4.media.session.MediaSessionCompat; +import android.support.v7.app.NotificationCompat; import android.widget.RemoteViews; /** @@ -195,6 +196,18 @@ } @Override + public ChromeNotificationBuilder setMediaStyle(MediaSessionCompat session, int[] actions, + PendingIntent intent, boolean showCancelButton) { + NotificationCompat.MediaStyle style = new NotificationCompat.MediaStyle(); + style.setMediaSession(session.getSessionToken()); + style.setShowActionsInCompactView(actions); + style.setCancelButtonIntent(intent); + style.setShowCancelButton(showCancelButton); + mBuilder.setStyle(style); + return this; + } + + @Override public Notification buildWithBigContentView(RemoteViews view) { return mBuilder.setCustomBigContentView(view).build(); }
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 89a7db5..3ffb8b5 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -14937,6 +14937,14 @@ <message name="IDS_FLAGS_ENABLE_ADJUSTABLE_LARGE_CURSOR_DESCRIPTION" desc="Description of the flag that enables adjustable large cursor."> Make size of accessibility large cursor adjustable. </message> + <if expr="chromeos or is_linux or is_macosx or is_win"> + <message name="IDS_FLAGS_OMNIBOX_ENTITY_SUGGESTIONS_NAME" desc="Name of the flag that enables receiving entity suggestions."> + Omnibox entity suggestions + </message> + <message name="IDS_FLAGS_OMNIBOX_ENTITY_SUGGESTIONS_DESCRIPTION" desc="Description of the flag that enables entity suggestions."> + Enable receiving entity suggestions in Omnibox. + </message> + </if> </messages> </release> </grit>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index ea4ad48..18dd9c4 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2321,6 +2321,14 @@ IDS_FLAGS_NEW_OMNIBOX_ANSWER_TYPES_DESCRIPTION, kOsAll, FEATURE_VALUE_TYPE(omnibox::kNewOmniboxAnswerTypes)}, +#if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_MACOSX) || \ + defined(OS_WIN) + {"omnibox-entity-suggestions", IDS_FLAGS_OMNIBOX_ENTITY_SUGGESTIONS_NAME, + IDS_FLAGS_OMNIBOX_ENTITY_SUGGESTIONS_DESCRIPTION, kOsDesktop, + FEATURE_VALUE_TYPE(omnibox::kOmniboxEntitySuggestions)}, +#endif // defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_MACOSX) || + // defined(OS_WIN) + // NOTE: Adding new command-line switches requires adding corresponding // entries to enum "LoginCustomFlags" in histograms.xml. See note in // histograms.xml and don't forget to run AboutFlagsHistogramTest unit test.
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc index 295fdfb..6430bae 100644 --- a/chrome/browser/sync/chrome_sync_client.cc +++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -9,6 +9,8 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/memory/ptr_util.h" +#include "base/path_service.h" +#include "base/syslog_logging.h" #include "build/build_config.h" #include "chrome/browser/autofill/personal_data_manager_factory.h" #include "chrome/browser/bookmarks/bookmark_model_factory.h" @@ -34,6 +36,7 @@ #include "chrome/browser/undo/bookmark_undo_service_factory.h" #include "chrome/browser/web_data_service_factory.h" #include "chrome/common/channel_info.h" +#include "chrome/common/chrome_paths.h" #include "chrome/common/features.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" @@ -55,6 +58,7 @@ #include "components/search_engines/search_engine_data_type_controller.h" #include "components/signin/core/browser/profile_oauth2_token_service.h" #include "components/spellcheck/spellcheck_build_features.h" +#include "components/sync/base/pref_names.h" #include "components/sync/base/report_unrecoverable_error.h" #include "components/sync/driver/async_directory_type_controller.h" #include "components/sync/driver/sync_api_component_factory.h" @@ -123,6 +127,13 @@ namespace browser_sync { +namespace { +#if defined(OS_WIN) +const base::FilePath::CharType kLoopbackServerBackendFilename[] = + FILE_PATH_LITERAL("profile.pb"); +#endif +} // namespace + // Chrome implementation of SyncSessionsClient. Needs to be in a separate class // due to possible multiple inheritance issues, wherein ChromeSyncClient might // inherit from other interfaces with same methods. @@ -235,6 +246,35 @@ return profile_->GetPrefs(); } +base::FilePath ChromeSyncClient::GetLocalSyncBackendFolder() { + base::FilePath local_sync_backend_folder = + GetPrefService()->GetFilePath(syncer::prefs::kLocalSyncBackendDir); + +#if defined(OS_WIN) + if (local_sync_backend_folder.empty()) { + if (!base::PathService::Get(chrome::DIR_ROAMING_USER_DATA, + &local_sync_backend_folder)) { + SYSLOG(WARNING) << "Local sync can not get the roaming profile folder."; + return base::FilePath(); + } + } + + // This code as it is now will assume the same profile order is present on + // all machines, which is not a given. It is to be defined if only the + // Default profile should get this treatment or all profile as is the case + // now. + // TODO(pastarmovj): http://crbug.com/674928 Decide if only the Default one + // should be considered roamed. For now the code assumes all profiles are + // created in the same order on all machines. + local_sync_backend_folder = + local_sync_backend_folder.Append(profile_->GetPath().BaseName()); + local_sync_backend_folder = + local_sync_backend_folder.Append(kLoopbackServerBackendFilename); +#endif // defined(OS_WIN) + + return local_sync_backend_folder; +} + bookmarks::BookmarkModel* ChromeSyncClient::GetBookmarkModel() { DCHECK_CURRENTLY_ON(BrowserThread::UI); return BookmarkModelFactory::GetForBrowserContext(profile_);
diff --git a/chrome/browser/sync/chrome_sync_client.h b/chrome/browser/sync/chrome_sync_client.h index 4004061..7ad51302 100644 --- a/chrome/browser/sync/chrome_sync_client.h +++ b/chrome/browser/sync/chrome_sync_client.h
@@ -39,6 +39,7 @@ void Initialize() override; syncer::SyncService* GetSyncService() override; PrefService* GetPrefService() override; + base::FilePath GetLocalSyncBackendFolder() override; bookmarks::BookmarkModel* GetBookmarkModel() override; favicon::FaviconService* GetFaviconService() override; history::HistoryService* GetHistoryService() override;
diff --git a/chrome/browser/sync/profile_sync_service_factory.cc b/chrome/browser/sync/profile_sync_service_factory.cc index 468c41ea..57d9f22 100644 --- a/chrome/browser/sync/profile_sync_service_factory.cc +++ b/chrome/browser/sync/profile_sync_service_factory.cc
@@ -8,6 +8,7 @@ #include "base/memory/ptr_util.h" #include "base/memory/singleton.h" +#include "base/metrics/histogram_macros.h" #include "base/threading/sequenced_worker_pool.h" #include "base/time/time.h" #include "build/build_config.h" @@ -75,11 +76,6 @@ latency, base::TimeTicks::Now())); } -#if defined(OS_WIN) -static const base::FilePath::CharType kLoopbackServerBackendFilename[] = - FILE_PATH_LITERAL("profile.pb"); -#endif - } // anonymous namespace // static @@ -160,27 +156,31 @@ blocking_pool->GetSequenceToken(), base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); - bool local_sync_backend_enabled = false; + if (!client_factory_) { + init_params.sync_client = + base::MakeUnique<browser_sync::ChromeSyncClient>(profile); + } else { + init_params.sync_client = client_factory_->Run(profile); + } + bool local_sync_backend_enabled = false; // Since the local sync backend is currently only supported on Windows don't // even check the pref on other os-es. #if defined(OS_WIN) syncer::SyncPrefs prefs(profile->GetPrefs()); local_sync_backend_enabled = prefs.IsLocalSyncEnabled(); + UMA_HISTOGRAM_BOOLEAN("Sync.Local.Enabled", local_sync_backend_enabled); + if (local_sync_backend_enabled) { - // This code as it is now will assume the same profile order is present on - // all machines, which is not a given. It is to be defined if only the - // Default profile should get this treatment or all profile as is the case - // now. The solution for now will be to assume profiles are created in the - // same order on all machines and in the future decide if only the Default - // one should be considered roamed. - init_params.local_sync_backend_folder = prefs.GetLocalSyncBackendDir(); - init_params.local_sync_backend_folder = - init_params.local_sync_backend_folder.Append( - init_params.base_directory.BaseName()); - init_params.local_sync_backend_folder = - init_params.local_sync_backend_folder.Append( - kLoopbackServerBackendFilename); + base::FilePath local_sync_backend_folder = + init_params.sync_client->GetLocalSyncBackendFolder(); + + // If the user has not specified a folder and we can't get the default + // roaming profile location the sync service will not be created. + UMA_HISTOGRAM_BOOLEAN("Sync.Local.RoamingProfileUnavailable", + local_sync_backend_folder.empty()); + if (local_sync_backend_folder.empty()) + return nullptr; init_params.start_behavior = ProfileSyncService::AUTO_START; } @@ -216,13 +216,6 @@ : ProfileSyncService::MANUAL_START; } - if (!client_factory_) { - init_params.sync_client = - base::MakeUnique<browser_sync::ChromeSyncClient>(profile); - } else { - init_params.sync_client = client_factory_->Run(profile); - } - auto pss = base::MakeUnique<ProfileSyncService>(std::move(init_params)); // Will also initialize the sync client.
diff --git a/chrome/browser/ui/cocoa/passwords/confirmation_password_saved_view_controller.mm b/chrome/browser/ui/cocoa/passwords/confirmation_password_saved_view_controller.mm index fe02247..b736557 100644 --- a/chrome/browser/ui/cocoa/passwords/confirmation_password_saved_view_controller.mm +++ b/chrome/browser/ui/cocoa/passwords/confirmation_password_saved_view_controller.mm
@@ -43,7 +43,7 @@ clickedOnLink:(id)link atIndex:(NSUInteger)charIndex { if (self.model) - self.model->OnManageLinkClicked(); + self.model->OnNavigateToPasswordManagerAccountDashboardLinkClicked(); [self.delegate viewShouldDismiss]; return YES; }
diff --git a/chrome/browser/ui/cocoa/passwords/confirmation_password_saved_view_controller_unittest.mm b/chrome/browser/ui/cocoa/passwords/confirmation_password_saved_view_controller_unittest.mm index e9ff521..79f0d32 100644 --- a/chrome/browser/ui/cocoa/passwords/confirmation_password_saved_view_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/passwords/confirmation_password_saved_view_controller_unittest.mm
@@ -44,7 +44,7 @@ TEST_F(ConfirmationPasswordSavedViewControllerTest, ShouldOpenPasswordsAndDismissWhenLinkClicked) { - EXPECT_CALL(*ui_controller(), NavigateToPasswordManagerSettingsPage()); + EXPECT_CALL(*ui_controller(), NavigateToPasswordManagerAccountDashboard()); [controller().confirmationText clickedOnLink:@"about:blank" atIndex:0]; EXPECT_TRUE([delegate() dismissed]); } @@ -52,7 +52,7 @@ TEST_F(ConfirmationPasswordSavedViewControllerTest, CloseBubbleAndHandleClick) { // A user may press mouse down, some navigation closes the bubble, mouse up // still sends the action. - EXPECT_CALL(*ui_controller(), NavigateToPasswordManagerSettingsPage()) + EXPECT_CALL(*ui_controller(), NavigateToPasswordManagerAccountDashboard()) .Times(0); [delegate() setModel:nil]; [controller().confirmationText clickedOnLink:@"about:blank" atIndex:0];
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc index 25210a4..6ae15530 100644 --- a/chromecast/browser/cast_browser_main_parts.cc +++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -251,6 +251,8 @@ // Enable navigator.connection API. // TODO(derekjchow): Remove this switch when enabled by default. { switches::kEnableNetworkInformation, "" }, + // TODO(halliwell): Remove after fixing b/35422666. + { switches::kEnableUseZoomForDSF, "false" }, { NULL, NULL }, // Termination };
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc index 7280c42..34924acf 100644 --- a/components/browser_sync/profile_sync_service.cc +++ b/components/browser_sync/profile_sync_service.cc
@@ -176,7 +176,6 @@ engine_initialized_(false), sync_disabled_by_admin_(false), is_auth_in_progress_(false), - local_sync_backend_folder_(init_params.local_sync_backend_folder), unrecoverable_error_reason_(ERROR_REASON_UNSET), expect_sync_configuration_aborted_(false), configure_status_(DataTypeManager::UNKNOWN),
diff --git a/components/browser_sync/profile_sync_service.h b/components/browser_sync/profile_sync_service.h index ee7fa2f9..7048a48 100644 --- a/components/browser_sync/profile_sync_service.h +++ b/components/browser_sync/profile_sync_service.h
@@ -241,7 +241,6 @@ std::string debug_identifier; version_info::Channel channel = version_info::Channel::UNKNOWN; scoped_refptr<base::SequencedTaskRunner> blocking_task_runner; - base::FilePath local_sync_backend_folder; private: DISALLOW_COPY_AND_ASSIGN(InitParams); @@ -786,9 +785,6 @@ // engine to refresh its credentials. bool is_auth_in_progress_; - // The location where the local sync backend stores its data. - base::FilePath local_sync_backend_folder_; - // Information describing an unrecoverable error. UnrecoverableErrorReason unrecoverable_error_reason_; std::string unrecoverable_error_message_;
diff --git a/components/browser_sync/profile_sync_service_unittest.cc b/components/browser_sync/profile_sync_service_unittest.cc index a7044ffe..935d62f 100644 --- a/components/browser_sync/profile_sync_service_unittest.cc +++ b/components/browser_sync/profile_sync_service_unittest.cc
@@ -222,8 +222,6 @@ ProfileSyncService::AUTO_START, builder.Build()); prefs()->SetBoolean(syncer::prefs::kEnableLocalSyncBackend, true); - init_params.local_sync_backend_folder = - base::FilePath(FILE_PATH_LITERAL("dummyPath")); init_params.oauth2_token_service = nullptr; init_params.gaia_cookie_manager_service = nullptr;
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc index 935e2b1..26321ea 100644 --- a/components/omnibox/browser/omnibox_field_trial.cc +++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -37,6 +37,11 @@ const base::Feature kNewOmniboxAnswerTypes{"NewOmniboxAnswerTypes", base::FEATURE_DISABLED_BY_DEFAULT}; +// Feature used to enable the transmission of entity suggestions from GWS +// to this client. +const base::Feature kOmniboxEntitySuggestions{ + "OmniboxEntitySuggestions", base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace omnibox namespace {
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h index 6c7ca25..7db2d031 100644 --- a/components/omnibox/browser/omnibox_field_trial.h +++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -25,6 +25,7 @@ namespace omnibox { extern const base::Feature kNewOmniboxAnswerTypes; +extern const base::Feature kOmniboxEntitySuggestions; }
diff --git a/components/sync/base/sync_prefs.cc b/components/sync/base/sync_prefs.cc index 3063f7c8..d9038963 100644 --- a/components/sync/base/sync_prefs.cc +++ b/components/sync/base/sync_prefs.cc
@@ -560,23 +560,7 @@ } base::FilePath SyncPrefs::GetLocalSyncBackendDir() const { - base::FilePath local_sync_backend_folder = - pref_service_->GetFilePath(prefs::kLocalSyncBackendDir); - -#if defined(OS_WIN) - if (local_sync_backend_folder.empty()) { - // TODO(pastarmovj): Add DIR_ROAMING_USER_DATA to PathService to simplify - // this code and move the logic in its right place. See crbug/657810. - CHECK( - base::PathService::Get(base::DIR_APP_DATA, &local_sync_backend_folder)); - - // TODO(pastarmovj): Quick and dirty solution for stage 1 of crbug/694464 - // for merging back into Chrome 57. - local_sync_backend_folder = local_sync_backend_folder.Append( - FILE_PATH_LITERAL("Google/Chrome/User Data")); - } -#endif // defined(OS_WIN) - return local_sync_backend_folder; + return pref_service_->GetFilePath(prefs::kLocalSyncBackendDir); } } // namespace syncer
diff --git a/components/sync/driver/fake_sync_client.cc b/components/sync/driver/fake_sync_client.cc index 16a46df..698c01f 100644 --- a/components/sync/driver/fake_sync_client.cc +++ b/components/sync/driver/fake_sync_client.cc
@@ -48,6 +48,10 @@ return &pref_service_; } +base::FilePath FakeSyncClient::GetLocalSyncBackendFolder() { + return base::FilePath(); +} + bookmarks::BookmarkModel* FakeSyncClient::GetBookmarkModel() { return nullptr; }
diff --git a/components/sync/driver/fake_sync_client.h b/components/sync/driver/fake_sync_client.h index 8a8928d..a5e8b48 100644 --- a/components/sync/driver/fake_sync_client.h +++ b/components/sync/driver/fake_sync_client.h
@@ -7,6 +7,7 @@ #include <memory> +#include "base/files/file_path.h" #include "base/macros.h" #include "components/sync/driver/sync_client.h" #include "components/sync_preferences/testing_pref_service_syncable.h" @@ -26,6 +27,7 @@ SyncService* GetSyncService() override; PrefService* GetPrefService() override; + base::FilePath GetLocalSyncBackendFolder() override; bookmarks::BookmarkModel* GetBookmarkModel() override; favicon::FaviconService* GetFaviconService() override; history::HistoryService* GetHistoryService() override;
diff --git a/components/sync/driver/sync_client.h b/components/sync/driver/sync_client.h index bf9ab4c..77d8f33e 100644 --- a/components/sync/driver/sync_client.h +++ b/components/sync/driver/sync_client.h
@@ -67,6 +67,10 @@ // Returns the current profile's preference service. virtual PrefService* GetPrefService() = 0; + // Returns the path to the folder used for storing the local sync database. + // It is only used when sync is running against a local backend. + virtual base::FilePath GetLocalSyncBackendFolder() = 0; + // DataType specific service getters. virtual bookmarks::BookmarkModel* GetBookmarkModel() = 0; virtual favicon::FaviconService* GetFaviconService() = 0;
diff --git a/components/sync/driver/sync_service_base.cc b/components/sync/driver/sync_service_base.cc index ae7467a2..8da8c4b 100644 --- a/components/sync/driver/sync_service_base.cc +++ b/components/sync/driver/sync_service_base.cc
@@ -26,11 +26,6 @@ const base::FilePath::CharType kSyncDataFolderName[] = FILE_PATH_LITERAL("Sync Data"); -#if defined(OS_WIN) -const base::FilePath::CharType kLoopbackServerBackendFilename[] = - FILE_PATH_LITERAL("profile.pb"); -#endif - EngineComponentsFactory::Switches EngineSwitchesFromCommandLine() { EngineComponentsFactory::Switches factory_switches = { EngineComponentsFactory::ENCRYPTION_KEYSTORE, @@ -124,8 +119,8 @@ // The first time we start up the engine we want to ensure we have a clean // directory, so delete any old one that might be there. params.delete_sync_data_folder = !IsFirstSetupComplete(); - params.enable_local_sync_backend = - GetLocalSyncConfig(¶ms.local_sync_backend_folder); + params.enable_local_sync_backend = sync_prefs_.IsLocalSyncEnabled(); + params.local_sync_backend_folder = sync_client_->GetLocalSyncBackendFolder(); params.restored_key_for_bootstrapping = sync_prefs_.GetEncryptionBootstrapToken(); params.restored_keystore_key_for_bootstrapping = @@ -142,40 +137,6 @@ engine_->Initialize(std::move(params)); } -bool SyncServiceBase::GetLocalSyncConfig( - base::FilePath* local_sync_backend_folder) const { - bool enable_local_sync_backend = false; - *local_sync_backend_folder = sync_prefs_.GetLocalSyncBackendDir(); -#if defined(OS_WIN) - enable_local_sync_backend = sync_prefs_.IsLocalSyncEnabled(); - UMA_HISTOGRAM_BOOLEAN("Sync.Local.Enabled", enable_local_sync_backend); - if (local_sync_backend_folder->empty()) { - // TODO(pastarmovj): Add DIR_ROAMING_USER_DATA to PathService to simplify - // this code and move the logic in its right place. See crbug/657810. - if (!base::PathService::Get(base::DIR_APP_DATA, - local_sync_backend_folder)) { - SYSLOG(WARNING) << "Local sync can not get the roaming profile folder."; - UMA_HISTOGRAM_BOOLEAN("Sync.Local.RoamingProfileUnavailable", false); - return false; - } - *local_sync_backend_folder = local_sync_backend_folder->Append( - FILE_PATH_LITERAL("Chrome/User Data")); - } - // This code as it is now will assume the same profile order is present on all - // machines, which is not a given. It is to be defined if only the Default - // profile should get this treatment or all profile as is the case now. The - // solution for now will be to assume profiles are created in the same order - // on all machines and in the future decide if only the Default one should be - // considered roamed. - // See http://crbug.com/674928. - *local_sync_backend_folder = - local_sync_backend_folder->Append(base_directory_.BaseName()); - *local_sync_backend_folder = - local_sync_backend_folder->Append(kLoopbackServerBackendFilename); -#endif // defined(OS_WIN) - return enable_local_sync_backend; -} - void SyncServiceBase::ResetCryptoState() { crypto_ = base::MakeUnique<SyncServiceCrypto>( base::BindRepeating(&SyncServiceBase::NotifyObservers,
diff --git a/components/sync/driver/sync_service_base.h b/components/sync/driver/sync_service_base.h index 96a6305..8b6d1f8 100644 --- a/components/sync/driver/sync_service_base.h +++ b/components/sync/driver/sync_service_base.h
@@ -121,8 +121,6 @@ base::ThreadChecker thread_checker_; private: - bool GetLocalSyncConfig(base::FilePath* local_sync_backend_folder) const; - DISALLOW_COPY_AND_ASSIGN(SyncServiceBase); };
diff --git a/ios/chrome/browser/sync/ios_chrome_sync_client.h b/ios/chrome/browser/sync/ios_chrome_sync_client.h index 48c5f6e..6f6a8ba5 100644 --- a/ios/chrome/browser/sync/ios_chrome_sync_client.h +++ b/ios/chrome/browser/sync/ios_chrome_sync_client.h
@@ -8,6 +8,7 @@ #include <memory> #include <vector> +#include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "components/sync/driver/sync_client.h" @@ -39,6 +40,7 @@ void Initialize() override; syncer::SyncService* GetSyncService() override; PrefService* GetPrefService() override; + base::FilePath GetLocalSyncBackendFolder() override; bookmarks::BookmarkModel* GetBookmarkModel() override; favicon::FaviconService* GetFaviconService() override; history::HistoryService* GetHistoryService() override;
diff --git a/ios/chrome/browser/sync/ios_chrome_sync_client.mm b/ios/chrome/browser/sync/ios_chrome_sync_client.mm index 8d7d4a5..92250fdf 100644 --- a/ios/chrome/browser/sync/ios_chrome_sync_client.mm +++ b/ios/chrome/browser/sync/ios_chrome_sync_client.mm
@@ -186,6 +186,10 @@ return browser_state_->GetPrefs(); } +base::FilePath IOSChromeSyncClient::GetLocalSyncBackendFolder() { + return base::FilePath(); +} + bookmarks::BookmarkModel* IOSChromeSyncClient::GetBookmarkModel() { DCHECK_CURRENTLY_ON(web::WebThread::UI); return ios::BookmarkModelFactory::GetForBrowserState(browser_state_);
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index ce801b2..435b2c7 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -625,7 +625,7 @@ // Shows the source of the current page. - (void)viewSource; #endif -// Whether the given tab's url begins with the chrome prefix. +// Whether the given tab's URL is an application specific URL. - (BOOL)isTabNativePage:(Tab*)tab; // Returns the view to use when animating a page in or out, positioning it to // fill the content area but not actually adding it to the view hierarchy. @@ -2051,9 +2051,18 @@ return tab; } -// Whether the given tab's url begins with the chrome prefix. +// Whether the given tab's URL is an application specific URL. - (BOOL)isTabNativePage:(Tab*)tab { - return tab && tab.url.SchemeIs(kChromeUIScheme); + web::WebState* webState = tab.webState; + if (!webState) + return NO; + web::NavigationManager* navigationManager = webState->GetNavigationManager(); + if (!navigationManager) + return NO; + web::NavigationItem* visibleItem = navigationManager->GetVisibleItem(); + if (!visibleItem) + return NO; + return web::GetWebClient()->IsAppSpecificURL(visibleItem->GetURL()); } - (void)expectNewForegroundTab {
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn index 7582e36..6e3ab09 100644 --- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn +++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -39,6 +39,7 @@ "//base", "//ios/chrome/browser/ui", "//ios/chrome/browser/ui/collection_view", + "//ios/chrome/browser/ui/colors", "//ios/third_party/material_roboto_font_loader_ios", "//ui/base", "//url",
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_article_item.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_article_item.h index 029790e6..8a81bc65 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_article_item.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_article_item.h
@@ -43,9 +43,7 @@ @property(nonatomic, readonly, assign) GURL articleURL; @property(nonatomic, copy) NSString* publisher; @property(nonatomic, assign) base::Time publishDate; - -// Whether the image is being fetched. This property is set by the delegate. -@property(nonatomic, assign) BOOL imageBeingFetched; +@property(nonatomic, weak) id<ContentSuggestionsArticleItemDelegate> delegate; @end
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_article_item.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_article_item.mm index 4749f4f..6ba227f7 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_article_item.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_article_item.mm
@@ -5,21 +5,27 @@ #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_article_item.h" #include "base/time/time.h" +#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" #import "ios/chrome/browser/ui/uikit_ui_util.h" +#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif namespace { -const CGFloat kImageSize = 100; +const CGFloat kImageSize = 72; +// When updating this, make sure to update |layoutSubviews|. const CGFloat kStandardSpacing = 8; } @interface ContentSuggestionsArticleItem () @property(nonatomic, copy) NSString* subtitle; -@property(nonatomic, weak) id<ContentSuggestionsArticleItemDelegate> delegate; +// Used to check if the image has already been fetched. There is no way to +// discriminate between failed image download and nonexitent image. The article +// tries to download the image only once. +@property(nonatomic, assign) BOOL imageFetched; @end @@ -35,7 +41,7 @@ @synthesize publishDate = _publishDate; @synthesize suggestionIdentifier = _suggestionIdentifier; @synthesize delegate = _delegate; -@synthesize imageBeingFetched = _imageBeingFetched; +@synthesize imageFetched = _imageFetched; - (instancetype)initWithType:(NSInteger)type title:(NSString*)title @@ -55,12 +61,15 @@ - (void)configureCell:(ContentSuggestionsArticleCell*)cell { [super configureCell:cell]; - if (!self.image && !self.imageBeingFetched) { + if (!self.image && !self.imageFetched) { + self.imageFetched = YES; + // Fetch the image. During the fetch the cell's image should still be set to + // nil. [self.delegate loadImageForArticleItem:self]; } - cell.titleLabel.text = _title; - cell.subtitleLabel.text = _subtitle; - cell.imageView.image = _image; + cell.titleLabel.text = self.title; + cell.subtitleLabel.text = self.subtitle; + cell.imageView.image = self.image; [cell setPublisherName:self.publisher date:self.publishDate]; } @@ -72,6 +81,9 @@ @property(nonatomic, strong) UILabel* publisherLabel; +// Applies the constraints on the elements. Called in the init. +- (void)applyConstraints; + @end @implementation ContentSuggestionsArticleCell @@ -89,12 +101,14 @@ _imageView = [[UIImageView alloc] initWithFrame:CGRectZero]; _publisherLabel = [[UILabel alloc] initWithFrame:CGRectZero]; + _titleLabel.numberOfLines = 2; _subtitleLabel.numberOfLines = 0; [_subtitleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisVertical]; [_titleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisVertical]; - _imageView.contentMode = UIViewContentModeScaleAspectFit; + _imageView.contentMode = UIViewContentModeScaleAspectFill; + _imageView.clipsToBounds = YES; _imageView.translatesAutoresizingMaskIntoConstraints = NO; _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; @@ -106,32 +120,14 @@ [self.contentView addSubview:_subtitleLabel]; [self.contentView addSubview:_publisherLabel]; - [NSLayoutConstraint activateConstraints:@[ - [_imageView.widthAnchor constraintLessThanOrEqualToConstant:kImageSize], - [_imageView.heightAnchor constraintLessThanOrEqualToConstant:kImageSize], - [_publisherLabel.topAnchor - constraintGreaterThanOrEqualToAnchor:_imageView.bottomAnchor - constant:kStandardSpacing], - [_publisherLabel.topAnchor - constraintGreaterThanOrEqualToAnchor:_subtitleLabel.bottomAnchor - constant:kStandardSpacing], - ]]; + _titleLabel.font = [MDCTypography subheadFont]; + _subtitleLabel.font = [MDCTypography body1Font]; + _publisherLabel.font = [MDCTypography captionFont]; - ApplyVisualConstraints( - @[ - @"H:|-[title]-[image]-|", - @"H:|-[text]-[image]", - @"V:|-[title]-[text]", - @"V:|-[image]", - @"H:|-[publish]-|", - @"V:[publish]-|", - ], - @{ - @"image" : _imageView, - @"title" : _titleLabel, - @"text" : _subtitleLabel, - @"publish" : _publisherLabel, - }); + _subtitleLabel.textColor = [[MDCPalette greyPalette] tint700]; + _publisherLabel.textColor = [[MDCPalette greyPalette] tint700]; + + [self applyConstraints]; } return self; } @@ -158,12 +154,47 @@ // Adjust the text label preferredMaxLayoutWidth when the parent's width // changes, for instance on screen rotation. CGFloat parentWidth = CGRectGetWidth(self.contentView.bounds); + + self.titleLabel.preferredMaxLayoutWidth = + parentWidth - self.imageView.bounds.size.width - 3 * kStandardSpacing; self.subtitleLabel.preferredMaxLayoutWidth = - parentWidth - self.imageView.bounds.size.width - 3 * 8; + parentWidth - self.imageView.bounds.size.width - 3 * kStandardSpacing; // Re-layout with the new preferred width to allow the label to adjust its // height. [super layoutSubviews]; } +#pragma mark - Private + +- (void)applyConstraints { + [NSLayoutConstraint activateConstraints:@[ + [_imageView.widthAnchor constraintEqualToConstant:kImageSize], + [_imageView.heightAnchor constraintEqualToAnchor:_imageView.widthAnchor], + [_publisherLabel.topAnchor + constraintGreaterThanOrEqualToAnchor:_imageView.bottomAnchor + constant:kStandardSpacing], + [_publisherLabel.topAnchor + constraintGreaterThanOrEqualToAnchor:_subtitleLabel.bottomAnchor + constant:kStandardSpacing], + ]]; + + ApplyVisualConstraintsWithMetrics( + @[ + @"H:|-(space)-[title]-(space)-[image]-(space)-|", + @"H:|-(space)-[text]-(space)-[image]", + @"V:|-[title]-[text]", + @"V:|-[image]", + @"H:|-[publish]-|", + @"V:[publish]-|", + ], + @{ + @"image" : _imageView, + @"title" : _titleLabel, + @"text" : _subtitleLabel, + @"publish" : _publisherLabel, + }, + @{ @"space" : @(kStandardSpacing) }); +} + @end
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_article_item_unittest.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_article_item_unittest.mm index 60eb0ea..b8c0003 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_article_item_unittest.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_article_item_unittest.mm
@@ -75,24 +75,31 @@ EXPECT_EQ(image, cell.imageView.image); } -// Tests that configureCell: does not call the delegate is |imageBeingFetched| -// is YES even if there is no image. +// Tests that configureCell: does not call the delegate if it fetched the image +// once. TEST(ContentSuggestionsArticleItemTest, DontFetchImageIsImageIsBeingFetched) { // Setup. NSString* title = @"testTitle"; NSString* subtitle = @"testSubtitle"; GURL url = GURL("http://chromium.org"); - id delegateMock = - OCMStrictProtocolMock(@protocol(ContentSuggestionsArticleItemDelegate)); + id niceDelegateMock = + OCMProtocolMock(@protocol(ContentSuggestionsArticleItemDelegate)); ContentSuggestionsArticleItem* item = [[ContentSuggestionsArticleItem alloc] initWithType:0 title:title subtitle:subtitle - delegate:delegateMock + delegate:niceDelegateMock url:url]; - item.imageBeingFetched = YES; + + OCMExpect([niceDelegateMock loadImageForArticleItem:item]); ContentSuggestionsArticleCell* cell = [[[item cellClass] alloc] init]; ASSERT_EQ(nil, item.image); + [item configureCell:cell]; + ASSERT_OCMOCK_VERIFY(niceDelegateMock); + + id strictDelegateMock = + OCMStrictProtocolMock(@protocol(ContentSuggestionsArticleItemDelegate)); + item.delegate = strictDelegateMock; // Action. [item configureCell:cell]; @@ -101,7 +108,6 @@ EXPECT_EQ(nil, cell.imageView.image); EXPECT_EQ(title, cell.titleLabel.text); EXPECT_EQ(subtitle, cell.subtitleLabel.text); - EXPECT_OCMOCK_VERIFY(delegateMock); } } // namespace
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm index 96a0e9c2..c0f4c13 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm
@@ -153,21 +153,22 @@ __weak ContentSuggestionsCollectionUpdater* weakSelf = self; __weak ContentSuggestionsArticleItem* weakArticle = articleItem; void (^imageFetchedCallback)(const gfx::Image&) = ^(const gfx::Image& image) { + if (image.IsEmpty()) { + return; + } + ContentSuggestionsCollectionUpdater* strongSelf = weakSelf; ContentSuggestionsArticleItem* strongArticle = weakArticle; if (!strongSelf || !strongArticle) { return; } - strongArticle.imageBeingFetched = NO; strongArticle.image = image.CopyUIImage(); [strongSelf.collectionViewController reconfigureCellsForItems:@[ strongArticle ] inSectionWithIdentifier:sectionIdentifier]; }; - articleItem.imageBeingFetched = YES; - [self.dataSource.imageFetcher fetchImageForSuggestion:articleItem.suggestionIdentifier callback:imageFetchedCallback];
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.mm b/ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.mm index dff7d74..360521e9 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.mm
@@ -46,7 +46,6 @@ // the color). |spaceBeforeCaret| controls whether a space should be added // between the image and the caret. - (void)attachIconNamed:(NSString*)iconName - accessibilityLabel:(NSString*)accessibilityLabel toString:(NSMutableAttributedString*)instructionString withCaret:(NSMutableAttributedString*)caret spaceBeforeCaret:(BOOL)spaceBeforeCaret @@ -106,18 +105,23 @@ NSMutableAttributedString* instructionString = [[NSMutableAttributedString alloc] init]; + NSString* accessibilityInstructionString = @":"; // Add the images inside the string. if (IsCompact()) { // If the device has a compact display the share menu is accessed from the // toolbar menu. If it is expanded, the share menu is directly accessible. [self attachIconNamed:kToolbarMenuIcon - accessibilityLabel:l10n_util::GetNSString(IDS_IOS_TOOLBAR_SETTINGS) toString:instructionString withCaret:caret spaceBeforeCaret:NO offset:iconOffset imageAttributes:textAttributes]; + + accessibilityInstructionString = [[accessibilityInstructionString + stringByAppendingString:l10n_util::GetNSString( + IDS_IOS_TOOLBAR_SETTINGS)] + stringByAppendingString:@", "]; } // Add a space before the share icon. @@ -127,30 +131,43 @@ attributes:instructionAttributes]]; [self attachIconNamed:kShareMenuIcon - accessibilityLabel:l10n_util::GetNSString(IDS_IOS_TOOLS_MENU_SHARE) toString:instructionString withCaret:caret spaceBeforeCaret:YES offset:iconOffset imageAttributes:textAttributes]; + accessibilityInstructionString = [[accessibilityInstructionString + stringByAppendingString:l10n_util::GetNSString( + IDS_IOS_TOOLS_MENU_SHARE)] + stringByAppendingString:@", "]; + // Add the "Read Later" string. NSAttributedString* shareMenuAction = [[NSAttributedString alloc] initWithString:readLater attributes:instructionAttributes]; [instructionString appendAttributedString:shareMenuAction]; + accessibilityInstructionString = + [accessibilityInstructionString stringByAppendingString:readLater]; + // Marker NSRange iconRange = [[baseAttributedString string] rangeOfString:kOpenShareMarker]; DCHECK(iconRange.location != NSNotFound); [baseAttributedString replaceCharactersInRange:iconRange withAttributedString:instructionString]; + NSString* accessibilityLabel = + l10n_util::GetNSString(IDS_IOS_READING_LIST_EMPTY_MESSAGE); + accessibilityLabel = [accessibilityLabel + stringByReplacingOccurrencesOfString:kOpenShareMarker + withString:accessibilityInstructionString]; // Attach to the label. UILabel* label = [[UILabel alloc] initWithFrame:CGRectZero]; label.attributedText = baseAttributedString; label.numberOfLines = 0; label.textAlignment = NSTextAlignmentCenter; + label.accessibilityLabel = accessibilityLabel; [label setTranslatesAutoresizingMaskIntoConstraints:NO]; [self addSubview:label]; @@ -165,7 +182,6 @@ } - (void)attachIconNamed:(NSString*)iconName - accessibilityLabel:(NSString*)accessibilityLabel toString:(NSMutableAttributedString*)instructionString withCaret:(NSMutableAttributedString*)caret spaceBeforeCaret:(BOOL)spaceBeforeCaret @@ -179,7 +195,6 @@ NSTextAttachment* toolbarIcon = [[NSTextAttachment alloc] init]; toolbarIcon.image = [[UIImage imageNamed:iconName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - toolbarIcon.image.accessibilityLabel = accessibilityLabel; toolbarIcon.bounds = CGRectMake(0, iconOffset, kIconSize, kIconSize); [instructionString appendAttributedString:[NSAttributedString
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_toolbar.mm b/ios/chrome/browser/ui/reading_list/reading_list_toolbar.mm index 1ccd653..c2b42ba 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_toolbar.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_toolbar.mm
@@ -38,19 +38,21 @@ @property(nonatomic, strong) UIView* editButtonContainer; // Button that displays "Delete". @property(nonatomic, strong) UIButton* deleteButton; +@property(nonatomic, strong) UIView* deleteButtonContainer; // Button that displays "Delete All Read". @property(nonatomic, strong) UIButton* deleteAllButton; +@property(nonatomic, strong) UIView* deleteAllButtonContainer; // Button that displays "Cancel". @property(nonatomic, strong) UIButton* cancelButton; +@property(nonatomic, strong) UIView* cancelButtonContainer; // Button that displays the mark options. @property(nonatomic, strong) UIButton* markButton; +@property(nonatomic, strong) UIView* markButtonContainer; // Stack view for arranging the buttons. @property(nonatomic, strong) UIStackView* stackView; // Creates a button with a |title| and a style according to |destructive|. -- (UIButton*)buttonWithText:(NSString*)title - destructive:(BOOL)isDestructive - positioning:(ButtonPositioning)position; +- (UIButton*)buttonWithText:(NSString*)title destructive:(BOOL)isDestructive; // Set the mark button label to |text|. - (void)setMarkButtonText:(NSString*)text; // Updates the button labels to match an empty selection. @@ -69,41 +71,93 @@ @synthesize editButtonContainer = _editButtonContainer; @synthesize deleteButton = _deleteButton; +@synthesize deleteButtonContainer = _deleteButtonContainer; @synthesize deleteAllButton = _deleteAllButton; +@synthesize deleteAllButtonContainer = _deleteAllButtonContainer; @synthesize cancelButton = _cancelButton; +@synthesize cancelButtonContainer = _cancelButtonContainer; @synthesize stackView = _stackView; @synthesize markButton = _markButton; +@synthesize markButtonContainer = _markButtonContainer; @synthesize state = _state; @synthesize heightDelegate = _heightDelegate; - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { - UIButton* editButton = [self - buttonWithText:l10n_util::GetNSString(IDS_IOS_READING_LIST_EDIT_BUTTON) - destructive:NO - positioning:Trailing]; + NSDictionary* views = nil; + NSArray* constraints = nil; _deleteButton = [self buttonWithText:l10n_util::GetNSString( IDS_IOS_READING_LIST_DELETE_BUTTON) - destructive:YES - positioning:Leading]; + destructive:YES]; + _deleteButton.translatesAutoresizingMaskIntoConstraints = NO; + _deleteButtonContainer = [[UIView alloc] init]; + [_deleteButtonContainer addSubview:_deleteButton]; + views = @{ @"button" : _deleteButton }; + constraints = @[ @"V:|[button]|", @"H:|[button]" ]; + ApplyVisualConstraints(constraints, views); + [_deleteButton.trailingAnchor + constraintLessThanOrEqualToAnchor:_deleteButtonContainer.trailingAnchor] + .active = YES; _deleteAllButton = [self buttonWithText:l10n_util::GetNSString( IDS_IOS_READING_LIST_DELETE_ALL_READ_BUTTON) - destructive:YES - positioning:Leading]; + destructive:YES]; + _deleteAllButton.translatesAutoresizingMaskIntoConstraints = NO; + _deleteAllButtonContainer = [[UIView alloc] init]; + [_deleteAllButtonContainer addSubview:_deleteAllButton]; + views = @{ @"button" : _deleteAllButton }; + constraints = @[ @"V:|[button]|", @"H:|[button]" ]; + ApplyVisualConstraints(constraints, views); + [_deleteAllButton.trailingAnchor + constraintLessThanOrEqualToAnchor:_deleteAllButtonContainer + .trailingAnchor] + .active = YES; _markButton = [self buttonWithText:l10n_util::GetNSString( IDS_IOS_READING_LIST_MARK_ALL_BUTTON) - destructive:NO - positioning:Centered]; + destructive:NO]; + _markButton.translatesAutoresizingMaskIntoConstraints = NO; + _markButtonContainer = [[UIView alloc] init]; + [_markButtonContainer addSubview:_markButton]; + views = @{ @"button" : _markButton }; + constraints = @[ @"V:|[button]|" ]; + ApplyVisualConstraints(constraints, views); + [_markButton.centerXAnchor + constraintEqualToAnchor:_markButtonContainer.centerXAnchor] + .active = YES; + [_markButton.trailingAnchor + constraintLessThanOrEqualToAnchor:_markButtonContainer.trailingAnchor] + .active = YES; + [_markButton.leadingAnchor + constraintGreaterThanOrEqualToAnchor:_markButtonContainer.leadingAnchor] + .active = YES; _cancelButton = [self buttonWithText:l10n_util::GetNSString( IDS_IOS_READING_LIST_CANCEL_BUTTON) - destructive:NO - positioning:Trailing]; + destructive:NO]; + _cancelButton.translatesAutoresizingMaskIntoConstraints = NO; + _cancelButtonContainer = [[UIView alloc] init]; + [_cancelButtonContainer addSubview:_cancelButton]; + views = @{ @"button" : _cancelButton }; + constraints = @[ @"V:|[button]|", @"H:[button]|" ]; + ApplyVisualConstraints(constraints, views); + [_cancelButton.leadingAnchor + constraintGreaterThanOrEqualToAnchor:_cancelButtonContainer + .leadingAnchor] + .active = YES; + + UIButton* editButton = [self + buttonWithText:l10n_util::GetNSString(IDS_IOS_READING_LIST_EDIT_BUTTON) + destructive:NO]; + editButton.translatesAutoresizingMaskIntoConstraints = NO; + _editButtonContainer = [[UIView alloc] initWithFrame:CGRectZero]; + [_editButtonContainer addSubview:editButton]; + views = @{ @"button" : editButton }; + constraints = @[ @"V:|[button]|", @"H:[button]|" ]; + ApplyVisualConstraints(constraints, views); [editButton addTarget:nil action:@selector(enterEditingModePressed) @@ -125,16 +179,9 @@ action:@selector(exitEditingModePressed) forControlEvents:UIControlEventTouchUpInside]; - _editButtonContainer = [[UIView alloc] initWithFrame:CGRectZero]; - [_editButtonContainer addSubview:editButton]; - editButton.translatesAutoresizingMaskIntoConstraints = NO; - NSDictionary* views = @{ @"button" : editButton }; - NSArray* constraints = @[ @"V:|[button]|", @"H:[button]|" ]; - ApplyVisualConstraints(constraints, views); - _stackView = [[UIStackView alloc] initWithArrangedSubviews:@[ - _editButtonContainer, _deleteButton, _deleteAllButton, _markButton, - _cancelButton + _editButtonContainer, _deleteButtonContainer, _deleteAllButtonContainer, + _markButtonContainer, _cancelButtonContainer ]]; _stackView.axis = UILayoutConstraintAxisHorizontal; _stackView.alignment = UIStackViewAlignmentFill; @@ -159,10 +206,10 @@ - (void)setEditing:(BOOL)editing { self.editButtonContainer.hidden = editing; - self.deleteButton.hidden = YES; - self.deleteAllButton.hidden = !editing; - self.cancelButton.hidden = !editing; - self.markButton.hidden = !editing; + self.deleteButtonContainer.hidden = YES; + self.deleteAllButtonContainer.hidden = !editing; + self.cancelButtonContainer.hidden = !editing; + self.markButtonContainer.hidden = !editing; [self updateHeight]; } @@ -231,9 +278,7 @@ IDS_IOS_READING_LIST_MARK_BUTTON)]; } -- (UIButton*)buttonWithText:(NSString*)title - destructive:(BOOL)isDestructive - positioning:(ButtonPositioning)position { +- (UIButton*)buttonWithText:(NSString*)title destructive:(BOOL)isDestructive { UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom]; button.contentEdgeInsets = UIEdgeInsetsMake(0, 8, 0, 8); [button setTitle:title forState:UIControlStateNormal]; @@ -251,31 +296,7 @@ [[button titleLabel] setFont:[[MDCTypography fontLoader] regularFontOfSize:14]]; - UIControlContentHorizontalAlignment horizontalAlignement; - - switch (position) { - case Leading: - if (UseRTLLayout()) { - horizontalAlignement = UIControlContentHorizontalAlignmentRight; - } else { - horizontalAlignement = UIControlContentHorizontalAlignmentLeft; - } - break; - - case Centered: - horizontalAlignement = UIControlContentHorizontalAlignmentCenter; - break; - - case Trailing: - if (UseRTLLayout()) { - horizontalAlignement = UIControlContentHorizontalAlignmentLeft; - } else { - horizontalAlignement = UIControlContentHorizontalAlignmentRight; - } - break; - } - - button.contentHorizontalAlignment = horizontalAlignement; + button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; button.titleLabel.textAlignment = NSTextAlignmentCenter; return button; @@ -288,7 +309,7 @@ - (void)updateHeight { for (UIButton* button in @[ _deleteButton, _deleteAllButton, _markButton, _cancelButton ]) { - if (!button.hidden) { + if (!button.superview.hidden) { CGFloat rect = [button.titleLabel.text cr_pixelAlignedSizeWithFont:button.titleLabel.font] .width;
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc index e98358fb..f0ab24a7 100644 --- a/net/spdy/spdy_session_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc
@@ -5625,7 +5625,9 @@ ASSERT_TRUE(altsvc_vector.empty()); } -TEST_F(AltSvcFrameTest, DoNotProcessAltSvcFrameWithEmptyOriginOnZeroStream) { +// An ALTSVC frame on stream 0 with empty origin MUST be ignored. +// (RFC 7838 Section 4) +TEST_F(AltSvcFrameTest, DoNotProcessAltSvcFrameWithEmptyOriginOnStreamZero) { SpdyAltSvcIR altsvc_ir(0); altsvc_ir.add_altsvc(alternative_service_); AddSocketData(altsvc_ir); @@ -5644,6 +5646,29 @@ ASSERT_TRUE(altsvc_vector.empty()); } +// An ALTSVC frame on a stream other than stream 0 with non-empty origin MUST be +// ignored. (RFC 7838 Section 4) +TEST_F(AltSvcFrameTest, + DoNotProcessAltSvcFrameWithNonEmptyOriginOnNonZeroStream) { + SpdyAltSvcIR altsvc_ir(1); + altsvc_ir.add_altsvc(alternative_service_); + altsvc_ir.set_origin("https://mail.example.org"); + AddSocketData(altsvc_ir); + AddSSLSocketData(); + + CreateNetworkSession(); + CreateSecureSpdySession(); + + base::RunLoop().RunUntilIdle(); + + const url::SchemeHostPort session_origin("https", test_url_.host(), + test_url_.EffectiveIntPort()); + AlternativeServiceVector altsvc_vector = + spdy_session_pool_->http_server_properties()->GetAlternativeServices( + session_origin); + ASSERT_TRUE(altsvc_vector.empty()); +} + TEST_F(AltSvcFrameTest, ProcessAltSvcFrameOnActiveStream) { SpdyAltSvcIR altsvc_ir(1); altsvc_ir.add_altsvc(alternative_service_);
diff --git a/third_party/WebKit/Source/build/scripts/make_computed_style_base.py b/third_party/WebKit/Source/build/scripts/make_computed_style_base.py index b86dd26..db00f7da 100755 --- a/third_party/WebKit/Source/build/scripts/make_computed_style_base.py +++ b/third_party/WebKit/Source/build/scripts/make_computed_style_base.py
@@ -18,6 +18,11 @@ NONPROPERTY_FIELDS = set([ # Style can not be shared. 'unique', + # Whether this style is affected by these pseudo-classes. + 'affectedByFocus', + 'affectedByHover', + 'affectedByActive', + 'affectedByDrag', ])
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp b/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp index 4bb1437..621e4e3 100644 --- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp +++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp
@@ -38,6 +38,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <memory> #include "core/CSSPropertyNames.h" #include "core/CSSValueKeywords.h" #include "core/StyleBuilderFunctions.h" @@ -53,6 +54,7 @@ #include "core/css/CSSPendingSubstitutionValue.h" #include "core/css/CSSPrimitiveValueMappings.h" #include "core/css/CSSPropertyMetadata.h" +#include "core/css/CSSValueIDMappings.h" #include "core/css/CSSVariableReferenceValue.h" #include "core/css/PropertyRegistration.h" #include "core/css/PropertyRegistry.h" @@ -79,7 +81,6 @@ #include "wtf/PtrUtil.h" #include "wtf/StdLibExtras.h" #include "wtf/Vector.h" -#include <memory> namespace blink { @@ -759,11 +760,8 @@ ContentData::create(state.styleImage(CSSPropertyContent, *item)); } else if (item->isCounterValue()) { const CSSCounterValue* counterValue = toCSSCounterValue(item.get()); - EListStyleType listStyleType = EListStyleType::kNone; - CSSValueID listStyleIdent = counterValue->listStyle(); - if (listStyleIdent != CSSValueNone) - listStyleType = - static_cast<EListStyleType>(listStyleIdent - CSSValueDisc); + const auto listStyleType = + cssValueIDToPlatformEnum<EListStyleType>(counterValue->listStyle()); std::unique_ptr<CounterContent> counter = WTF::wrapUnique(new CounterContent( AtomicString(counterValue->identifier()), listStyleType,
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h index 3903fb7..71a827109 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyle.h +++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -273,11 +273,6 @@ unsigned m_emptyState : 1; - unsigned m_affectedByFocus : 1; - unsigned m_affectedByHover : 1; - unsigned m_affectedByActive : 1; - unsigned m_affectedByDrag : 1; - // 64 bits unsigned m_isLink : 1; @@ -310,10 +305,6 @@ m_nonInheritedData.m_unique = false; m_nonInheritedData.m_emptyState = false; m_nonInheritedData.m_hasViewportUnits = false; - m_nonInheritedData.m_affectedByFocus = false; - m_nonInheritedData.m_affectedByHover = false; - m_nonInheritedData.m_affectedByActive = false; - m_nonInheritedData.m_affectedByDrag = false; m_nonInheritedData.m_isLink = false; m_nonInheritedData.m_hasRemUnits = false; } @@ -2457,20 +2448,6 @@ bool hasRemUnits() const { return m_nonInheritedData.m_hasRemUnits; } void setHasRemUnits() const { m_nonInheritedData.m_hasRemUnits = true; } - bool affectedByFocus() const { return m_nonInheritedData.m_affectedByFocus; } - void setAffectedByFocus() { m_nonInheritedData.m_affectedByFocus = true; } - - bool affectedByHover() const { return m_nonInheritedData.m_affectedByHover; } - void setAffectedByHover() { m_nonInheritedData.m_affectedByHover = true; } - - bool affectedByActive() const { - return m_nonInheritedData.m_affectedByActive; - } - void setAffectedByActive() { m_nonInheritedData.m_affectedByActive = true; } - - bool affectedByDrag() const { return m_nonInheritedData.m_affectedByDrag; } - void setAffectedByDrag() { m_nonInheritedData.m_affectedByDrag = true; } - bool emptyState() const { return m_nonInheritedData.m_emptyState; } void setEmptyState(bool b) { setUnique();
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc index 742f845..b534f51 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc
@@ -282,8 +282,8 @@ base::TimeTicks next_delayed_task = main_thread_only().delayed_incoming_queue.top().delayed_run_time; if (next_delayed_task == delayed_run_time && IsQueueEnabled()) { - main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, - now); + main_thread_only().time_domain->ScheduleDelayedWork( + this, {delayed_run_time, pending_task.sequence_num}, now); } TraceQueueSize(false); @@ -414,8 +414,8 @@ return main_thread_only().delayed_incoming_queue.top().delayed_run_time; } -base::Optional<base::TimeTicks> TaskQueueImpl::WakeUpForDelayedWork( - LazyNow* lazy_now) { +base::Optional<TaskQueueImpl::DelayedWakeUp> +TaskQueueImpl::WakeUpForDelayedWork(LazyNow* lazy_now) { // Enqueue all delayed tasks that should be running now, skipping any that // have been canceled. while (!main_thread_only().delayed_incoming_queue.empty()) { @@ -434,8 +434,11 @@ } // Make sure the next wake up is scheduled. - if (!main_thread_only().delayed_incoming_queue.empty()) - return main_thread_only().delayed_incoming_queue.top().delayed_run_time; + if (!main_thread_only().delayed_incoming_queue.empty()) { + return DelayedWakeUp{ + main_thread_only().delayed_incoming_queue.top().delayed_run_time, + main_thread_only().delayed_incoming_queue.top().sequence_num}; + } return base::nullopt; } @@ -587,7 +590,9 @@ if (IsQueueEnabled() && !main_thread_only().delayed_incoming_queue.empty()) { time_domain->ScheduleDelayedWork( - this, main_thread_only().delayed_incoming_queue.top().delayed_run_time, + this, + {main_thread_only().delayed_incoming_queue.top().delayed_run_time, + main_thread_only().delayed_incoming_queue.top().sequence_num}, time_domain->Now()); } } @@ -817,7 +822,8 @@ if (!main_thread_only().delayed_incoming_queue.empty()) { main_thread_only().time_domain->ScheduleDelayedWork( this, - main_thread_only().delayed_incoming_queue.top().delayed_run_time, + {main_thread_only().delayed_incoming_queue.top().delayed_run_time, + main_thread_only().delayed_incoming_queue.top().sequence_num}, main_thread_only().time_domain->Now()); } // Note the selector calls TaskQueueManager::OnTaskQueueEnabled which posts @@ -864,7 +870,8 @@ if (IsQueueEnabled()) { main_thread_only().time_domain->ScheduleDelayedWork( this, - main_thread_only().delayed_incoming_queue.top().delayed_run_time, + {main_thread_only().delayed_incoming_queue.top().delayed_run_time, + main_thread_only().delayed_incoming_queue.top().sequence_num}, main_thread_only().time_domain->Now()); } }
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h index 8381157..79503356b 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h
@@ -111,6 +111,21 @@ EnqueueOrder enqueue_order_; }; + // Represents a time at which a task wants to run. Tasks scheduled for the + // same point in time will be ordered by their sequence numbers. + struct DelayedWakeUp { + base::TimeTicks time; + int sequence_num; + + bool operator<=(const DelayedWakeUp& other) const { + if (time == other.time) { + DCHECK_NE(sequence_num, other.sequence_num); + return (sequence_num - other.sequence_num) < 0; + } + return time < other.time; + } + }; + // TaskQueue implementation. void UnregisterTaskQueue() override; bool RunsTasksOnCurrentThread() const override; @@ -177,9 +192,9 @@ } // Enqueues any delayed tasks which should be run now on the - // |delayed_work_queue|. Returns the deadline if a subsequent wakeup is - // required. Must be called from the main thread. - base::Optional<base::TimeTicks> WakeUpForDelayedWork(LazyNow* lazy_now); + // |delayed_work_queue|. Returns the subsequent wakeup that is required, if + // any. Must be called from the main thread. + base::Optional<DelayedWakeUp> WakeUpForDelayedWork(LazyNow* lazy_now); base::TimeTicks scheduled_time_domain_wakeup() const { return main_thread_only().scheduled_time_domain_wakeup;
diff --git a/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc b/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc index 9f8c909..5c68b3d 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc
@@ -31,9 +31,10 @@ CancelDelayedWork(queue); } -void TimeDomain::ScheduleDelayedWork(internal::TaskQueueImpl* queue, - base::TimeTicks delayed_run_time, - base::TimeTicks now) { +void TimeDomain::ScheduleDelayedWork( + internal::TaskQueueImpl* queue, + internal::TaskQueueImpl::DelayedWakeUp wake_up, + base::TimeTicks now) { DCHECK(main_thread_checker_.CalledOnValidThread()); DCHECK_EQ(queue->GetTimeDomain(), this); DCHECK(queue->IsQueueEnabled()); @@ -43,18 +44,17 @@ DCHECK_NE(queue->scheduled_time_domain_wakeup(), base::TimeTicks()); // O(log n) - delayed_wakeup_queue_.ChangeKey(queue->heap_handle(), - {delayed_run_time, queue}); + delayed_wakeup_queue_.ChangeKey(queue->heap_handle(), {wake_up, queue}); } else { // O(log n) - delayed_wakeup_queue_.insert({delayed_run_time, queue}); + delayed_wakeup_queue_.insert({wake_up, queue}); } - queue->set_scheduled_time_domain_wakeup(delayed_run_time); + queue->set_scheduled_time_domain_wakeup(wake_up.time); // If |queue| is the first wakeup then request the wakeup. if (delayed_wakeup_queue_.min().queue == queue) - RequestWakeupAt(now, delayed_run_time); + RequestWakeupAt(now, wake_up.time); if (observer_) observer_->OnTimeDomainHasDelayedWork(queue); @@ -75,34 +75,34 @@ DCHECK_NE(queue->scheduled_time_domain_wakeup(), base::TimeTicks()); DCHECK(!delayed_wakeup_queue_.empty()); - base::TimeTicks prev_first_wakeup = delayed_wakeup_queue_.min().time; + base::TimeTicks prev_first_wakeup = delayed_wakeup_queue_.min().wake_up.time; // O(log n) delayed_wakeup_queue_.erase(queue->heap_handle()); if (delayed_wakeup_queue_.empty()) { CancelWakeupAt(prev_first_wakeup); - } else if (prev_first_wakeup != delayed_wakeup_queue_.min().time) { + } else if (prev_first_wakeup != delayed_wakeup_queue_.min().wake_up.time) { CancelWakeupAt(prev_first_wakeup); - RequestWakeupAt(Now(), delayed_wakeup_queue_.min().time); + RequestWakeupAt(Now(), delayed_wakeup_queue_.min().wake_up.time); } } void TimeDomain::WakeupReadyDelayedQueues(LazyNow* lazy_now) { DCHECK(main_thread_checker_.CalledOnValidThread()); - // Wake up any queues with pending delayed work. Note std::multipmap stores + // Wake up any queues with pending delayed work. Note std::multimap stores // the elements sorted by key, so the begin() iterator points to the earliest // queue to wakeup. while (!delayed_wakeup_queue_.empty() && - delayed_wakeup_queue_.min().time <= lazy_now->Now()) { + delayed_wakeup_queue_.min().wake_up.time <= lazy_now->Now()) { internal::TaskQueueImpl* queue = delayed_wakeup_queue_.min().queue; - base::Optional<base::TimeTicks> next_wakeup = + base::Optional<internal::TaskQueueImpl::DelayedWakeUp> next_wake_up = queue->WakeUpForDelayedWork(lazy_now); - if (next_wakeup) { + if (next_wake_up) { // O(log n) - delayed_wakeup_queue_.ReplaceMin({next_wakeup.value(), queue}); - queue->set_scheduled_time_domain_wakeup(next_wakeup.value()); + delayed_wakeup_queue_.ReplaceMin({*next_wake_up, queue}); + queue->set_scheduled_time_domain_wakeup(next_wake_up->time); } else { // O(log n) delayed_wakeup_queue_.pop(); @@ -116,7 +116,7 @@ if (delayed_wakeup_queue_.empty()) return false; - *out_time = delayed_wakeup_queue_.min().time; + *out_time = delayed_wakeup_queue_.min().wake_up.time; return true; } @@ -134,7 +134,7 @@ state->SetString("name", GetName()); state->SetInteger("registered_delay_count", delayed_wakeup_queue_.size()); if (!delayed_wakeup_queue_.empty()) { - base::TimeDelta delay = delayed_wakeup_queue_.min().time - Now(); + base::TimeDelta delay = delayed_wakeup_queue_.min().wake_up.time - Now(); state->SetDouble("next_delay_ms", delay.InMillisecondsF()); } AsValueIntoInternal(state);
diff --git a/third_party/WebKit/Source/platform/scheduler/base/time_domain.h b/third_party/WebKit/Source/platform/scheduler/base/time_domain.h index c2b828a8b..4c96597 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/time_domain.h +++ b/third_party/WebKit/Source/platform/scheduler/base/time_domain.h
@@ -94,7 +94,7 @@ // TimeDomain reaches |delayed_run_time|. This supersedes any previously // registered wakeup for |queue|. void ScheduleDelayedWork(internal::TaskQueueImpl* queue, - base::TimeTicks delayed_run_time, + internal::TaskQueueImpl::DelayedWakeUp wake_up, base::TimeTicks now); // Cancels any scheduled calls to TaskQueueImpl::WakeUpForDelayedWork for @@ -137,14 +137,12 @@ } private: - struct DelayedWakeup { - base::TimeTicks time; + struct ScheduledDelayedWakeUp { + internal::TaskQueueImpl::DelayedWakeUp wake_up; internal::TaskQueueImpl* queue; - bool operator<=(const DelayedWakeup& other) const { - if (time == other.time) - return queue <= other.queue; - return time < other.time; + bool operator<=(const ScheduledDelayedWakeUp& other) const { + return wake_up <= other.wake_up; } void SetHeapHandle(HeapHandle handle) { @@ -161,7 +159,7 @@ } }; - IntrusiveHeap<DelayedWakeup> delayed_wakeup_queue_; + IntrusiveHeap<ScheduledDelayedWakeUp> delayed_wakeup_queue_; Observer* const observer_; // NOT OWNED.
diff --git a/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc index c8b6acb..1c47328 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc
@@ -94,7 +94,7 @@ base::TimeTicks delayed_runtime = time_domain_->Now() + delay; EXPECT_CALL(*time_domain_.get(), RequestWakeupAt(_, delayed_runtime)); base::TimeTicks now = time_domain_->Now(); - time_domain_->ScheduleDelayedWork(task_queue_.get(), now + delay, now); + time_domain_->ScheduleDelayedWork(task_queue_.get(), {now + delay, 0}, now); base::TimeTicks next_scheduled_runtime; EXPECT_TRUE(time_domain_->NextScheduledRunTime(&next_scheduled_runtime)); @@ -115,7 +115,8 @@ base::TimeTicks delayed_runtime2 = time_domain_->Now() + delay2; EXPECT_CALL(*time_domain_.get(), RequestWakeupAt(_, delayed_runtime1)); base::TimeTicks now = time_domain_->Now(); - time_domain_->ScheduleDelayedWork(task_queue_.get(), delayed_runtime1, now); + time_domain_->ScheduleDelayedWork(task_queue_.get(), {delayed_runtime1, 0}, + now); base::TimeTicks next_scheduled_runtime; EXPECT_TRUE(time_domain_->NextScheduledRunTime(&next_scheduled_runtime)); @@ -126,7 +127,8 @@ // Now scheduler a later wakeup, which should replace the previously requested // one. EXPECT_CALL(*time_domain_.get(), RequestWakeupAt(_, delayed_runtime2)); - time_domain_->ScheduleDelayedWork(task_queue_.get(), delayed_runtime2, now); + time_domain_->ScheduleDelayedWork(task_queue_.get(), {delayed_runtime2, 0}, + now); EXPECT_TRUE(time_domain_->NextScheduledRunTime(&next_scheduled_runtime)); EXPECT_EQ(delayed_runtime2, next_scheduled_runtime); @@ -159,19 +161,19 @@ // RequestWakeupAt should always be called if there are no other wakeups. base::TimeTicks now = time_domain_->Now(); EXPECT_CALL(*time_domain_.get(), RequestWakeupAt(_, now + delay1)); - time_domain_->ScheduleDelayedWork(task_queue_.get(), now + delay1, now); + time_domain_->ScheduleDelayedWork(task_queue_.get(), {now + delay1, 0}, now); Mock::VerifyAndClearExpectations(time_domain_.get()); // RequestWakeupAt should not be called when scheduling later tasks. EXPECT_CALL(*time_domain_.get(), RequestWakeupAt(_, _)).Times(0); - time_domain_->ScheduleDelayedWork(task_queue2.get(), now + delay2, now); - time_domain_->ScheduleDelayedWork(task_queue3.get(), now + delay3, now); + time_domain_->ScheduleDelayedWork(task_queue2.get(), {now + delay2, 0}, now); + time_domain_->ScheduleDelayedWork(task_queue3.get(), {now + delay3, 0}, now); // RequestWakeupAt should be called when scheduling earlier tasks. Mock::VerifyAndClearExpectations(time_domain_.get()); EXPECT_CALL(*time_domain_.get(), RequestWakeupAt(_, now + delay4)); - time_domain_->ScheduleDelayedWork(task_queue4.get(), now + delay4, now); + time_domain_->ScheduleDelayedWork(task_queue4.get(), {now + delay4, 0}, now); Mock::VerifyAndClearExpectations(time_domain_.get()); @@ -191,9 +193,9 @@ base::TimeTicks now = time_domain_->Now(); base::TimeTicks wakeup1 = now + base::TimeDelta::FromMilliseconds(10); EXPECT_CALL(*time_domain_.get(), RequestWakeupAt(_, wakeup1)).Times(1); - time_domain_->ScheduleDelayedWork(task_queue_.get(), wakeup1, now); + time_domain_->ScheduleDelayedWork(task_queue_.get(), {wakeup1, 0}, now); base::TimeTicks wakeup2 = now + base::TimeDelta::FromMilliseconds(100); - time_domain_->ScheduleDelayedWork(task_queue2_.get(), wakeup2, now); + time_domain_->ScheduleDelayedWork(task_queue2_.get(), {wakeup2, 0}, now); TaskQueue* next_task_queue; EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue)); @@ -222,7 +224,8 @@ base::TimeTicks now = time_domain_->Now(); base::TimeTicks delayed_runtime = now + delay; EXPECT_CALL(*time_domain_.get(), RequestWakeupAt(_, delayed_runtime)); - time_domain_->ScheduleDelayedWork(task_queue_.get(), delayed_runtime, now); + time_domain_->ScheduleDelayedWork(task_queue_.get(), {delayed_runtime, 0}, + now); base::TimeTicks next_run_time; ASSERT_TRUE(time_domain_->NextScheduledRunTime(&next_run_time)); @@ -239,12 +242,42 @@ ASSERT_FALSE(time_domain_->NextScheduledRunTime(&next_run_time)); } +TEST_F(TimeDomainTest, WakeupReadyDelayedQueuesWithIdenticalRuntimes) { + int sequence_num = 0; + base::TimeDelta delay = base::TimeDelta::FromMilliseconds(50); + base::TimeTicks now = time_domain_->Now(); + base::TimeTicks delayed_runtime = now + delay; + EXPECT_CALL(*time_domain_.get(), RequestWakeupAt(_, delayed_runtime)); + EXPECT_CALL(*time_domain_.get(), CancelWakeupAt(delayed_runtime)); + + scoped_refptr<internal::TaskQueueImpl> task_queue2 = make_scoped_refptr( + new internal::TaskQueueImpl(nullptr, time_domain_.get(), + TaskQueue::Spec(TaskQueue::QueueType::TEST), + "test.category", "test.category")); + + time_domain_->ScheduleDelayedWork(task_queue2.get(), + {delayed_runtime, ++sequence_num}, now); + time_domain_->ScheduleDelayedWork(task_queue_.get(), + {delayed_runtime, ++sequence_num}, now); + + LazyNow lazy_now = time_domain_->CreateLazyNow(); + time_domain_->WakeupReadyDelayedQueues(&lazy_now); + + // The second task queue should wake up first since it has a lower sequence + // number. + TaskQueue* next_task_queue; + EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue)); + EXPECT_EQ(task_queue2.get(), next_task_queue); + + task_queue2->UnregisterTaskQueue(); +} + TEST_F(TimeDomainTest, CancelDelayedWork) { base::TimeTicks now = time_domain_->Now(); base::TimeTicks run_time = now + base::TimeDelta::FromMilliseconds(20); EXPECT_CALL(*time_domain_.get(), RequestWakeupAt(_, run_time)); - time_domain_->ScheduleDelayedWork(task_queue_.get(), run_time, now); + time_domain_->ScheduleDelayedWork(task_queue_.get(), {run_time, 0}, now); TaskQueue* next_task_queue; EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue)); @@ -265,11 +298,11 @@ base::TimeTicks run_time1 = now + base::TimeDelta::FromMilliseconds(20); base::TimeTicks run_time2 = now + base::TimeDelta::FromMilliseconds(40); EXPECT_CALL(*time_domain_.get(), RequestWakeupAt(_, run_time1)); - time_domain_->ScheduleDelayedWork(task_queue_.get(), run_time1, now); + time_domain_->ScheduleDelayedWork(task_queue_.get(), {run_time1, 0}, now); Mock::VerifyAndClearExpectations(time_domain_.get()); EXPECT_CALL(*time_domain_.get(), RequestWakeupAt(_, _)).Times(0); - time_domain_->ScheduleDelayedWork(task_queue2.get(), run_time2, now); + time_domain_->ScheduleDelayedWork(task_queue2.get(), {run_time2, 0}, now); Mock::VerifyAndClearExpectations(time_domain_.get()); TaskQueue* next_task_queue; @@ -327,7 +360,7 @@ EXPECT_CALL(*time_domain_.get(), RequestWakeupAt(_, _)); base::TimeTicks now = time_domain_->Now(); time_domain_->ScheduleDelayedWork( - task_queue_.get(), now + base::TimeDelta::FromMilliseconds(10), now); + task_queue_.get(), {now + base::TimeDelta::FromMilliseconds(10), 0}, now); } } // namespace scheduler
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 4696764..27aaf12 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -98498,6 +98498,7 @@ <int value="609112512" label="touch-selection-strategy"/> <int value="610545308" label="enable-potentially-annoying-security-features"/> <int value="624317932" label="print-pdf-as-image"/> + <int value="624368375" label="OmniboxEntitySuggestions:enabled"/> <int value="625273056" label="disable-boot-animation"/> <int value="628302973" label="NTPSnippets:enabled"/> <int value="630947363" label="touch-events"/> @@ -98610,6 +98611,7 @@ <int value="1114629582" label="enable-floating-virtual-keyboard"/> <int value="1118109174" label="enable-launcher-search-provider-api"/> <int value="1127183523" label="PassiveEventListenersDueToFling:enabled"/> + <int value="1127427821" label="OmniboxEntitySuggestions:disabled"/> <int value="1129888794" label="ash-touch-hud"/> <int value="1133635187" label="force-gpu-rasterization"/> <int value="1139226452" label="enable-nacl-debug"/>