diff --git a/DEPS b/DEPS index 8beb64bd..e2e819e 100644 --- a/DEPS +++ b/DEPS
@@ -133,11 +133,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': '24b0b59e4409f41d8e6749a32001a7fdbfe18e7e', + 'skia_revision': 'b085fa9c8c19e0afd64ea77a4c018a4aef37e9ed', # 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': '3e8a733af17a7812eba188dad612be503bd45c57', + 'v8_revision': '028b41c56f0450bfb0eac4325e9db629e95afd8f', # 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. @@ -153,7 +153,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '9384947f47f28811e7b15b0c267e89a277d24880', + 'pdfium_revision': 'ed5dc24c07a33561e53522779bfc2282b4f9bcdf', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -184,7 +184,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. - 'freetype_revision': '6d65c60fca0ebce88e2bcfeac92a7a791e03bf42', + 'freetype_revision': '31757f969fba60d75404f31e8f1168bef5011770', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling HarfBuzz # and whatever else without interference from each other. @@ -248,7 +248,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'spv_headers_revision': 'dc3db3a5ae5e97e007dd2fb6b76f57bee3f809fc', + 'spv_headers_revision': '03a081524afabdde274d885880c2fef213e46a59', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -752,7 +752,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '3a9f8f45de46efae4eea2758dc6922634d121d58', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '6195cd0e66d03a29c616c74d6c07d5867bd747bb', 'condition': 'checkout_linux', }, @@ -846,7 +846,7 @@ }, 'src/third_party/glslang/src': - Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + 'cc4a756d48e9c49d31265962c85fee28b5828e5f', + Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '79d25ea0ce184f583e07aec9989101740e139033', 'src/third_party/google_toolbox_for_mac/src': { 'url': Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'), @@ -1116,7 +1116,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'eb748c338927823601af8d364e1e172cd590f01c', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'c854c371c89b02fd1da270a80585985bb0f52c89', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1290,7 +1290,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'a0f51b2e123f39c9ff12e621b0b47dd28dd64424', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'd36c08623d9085dad821fbb1462a7fe03badcef5', + Var('webrtc_git') + '/src.git' + '@' + 'be7af9399ceb88171bf60b50419ff2dec8184fb9', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1331,7 +1331,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@327e9ae49a2d7bbfdef893e5977dd92c9dae9d1c', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0563888d38680bd28f06e48686d79c936c81f4a1', 'condition': 'checkout_src_internal', }, @@ -2749,7 +2749,7 @@ 'src/third_party/libovr/src', ], }, - # Download ink resources for chromeos. + # Download common ink resources for chromeos. { 'name': 'ink-build', 'pattern': '.', @@ -2763,7 +2763,7 @@ '-d', 'src/third_party/ink/build', ], }, - # Download ink resources for chromeos. + # Download wasm ink resources for chromeos. { 'name': 'ink-build-wasm', 'pattern': '.', @@ -2777,6 +2777,20 @@ '-d', 'src/third_party/ink/build/wasm', ], }, + # Download wasm threaded ink resources for chromeos. + { + 'name': 'ink-build-wasm', + 'pattern': '.', + 'condition': 'checkout_chromeos', + 'action': [ 'python', + 'src/third_party/depot_tools/download_from_google_storage.py', + '--no_resume', + '--no_auth', + '--num_threads=4', + '--bucket', 'chromium-ink', + '-d', 'src/third_party/ink/build/wasm-threads', + ], + }, { # Pull doclava binaries if building for Android. 'name': 'doclava',
diff --git a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java index 46e9b1e..0779796 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java +++ b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java
@@ -8,6 +8,7 @@ import android.content.Context; import android.media.AudioManager; import android.net.Uri; +import android.os.Build; import android.os.Handler; import android.os.Message; import android.provider.MediaStore; @@ -152,11 +153,17 @@ Log.w(TAG, "Unknown message level, defaulting to DEBUG"); break; } - + // Calling onConsoleMessage(...) even that the result is ignored if it's a non-debuggable + // app or device as it can be overriden by the user with some custom logic that is expected + // to be always run. boolean result = mContentsClient.onConsoleMessage( new AwConsoleMessage(message, sourceId, lineNumber, messageLevel)); - if (result && message != null && message.startsWith("[blocked]")) { - Log.e(TAG, "Blocked URL: " + message); + boolean isAppDebuggable = mContext.getApplicationInfo().FLAG_DEBUGGABLE != 0; + boolean isOsDebuggable = !Build.TYPE.equals("user"); + // Always return true if not debuggable so js console messages won't be mirrored to logcat + // for privacy. + if (!isAppDebuggable && !isOsDebuggable) { + return true; } return result; }
diff --git a/ash/perftests/ash_background_filter_blur_perftest.cc b/ash/perftests/ash_background_filter_blur_perftest.cc index c5edf228..1bbdf3a5 100644 --- a/ash/perftests/ash_background_filter_blur_perftest.cc +++ b/ash/perftests/ash_background_filter_blur_perftest.cc
@@ -6,7 +6,7 @@ #include "ash/shell.h" #include "ash/test/ash_test_base.h" -#include "cc/base/lap_timer.h" +#include "base/timer/lap_timer.h" #include "testing/perf/perf_test.h" #include "ui/aura/window.h" #include "ui/compositor/test/draw_waiter_for_test.h" @@ -45,7 +45,7 @@ ui::Compositor* compositor_ = nullptr; - cc::LapTimer timer_; + base::LapTimer timer_; DISALLOW_COPY_AND_ASSIGN(AshBackgroundFilterBlurPerfTest); };
diff --git a/base/BUILD.gn b/base/BUILD.gn index f7791c4..f0f3461 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -892,6 +892,8 @@ "timer/elapsed_timer.h", "timer/hi_res_timer_manager.h", "timer/hi_res_timer_manager_win.cc", + "timer/lap_timer.cc", + "timer/lap_timer.h", "timer/timer.cc", "timer/timer.h", "token.cc", @@ -2576,6 +2578,7 @@ "time/time_unittest.cc", "time/time_win_unittest.cc", "timer/hi_res_timer_manager_unittest.cc", + "timer/lap_timer_unittest.cc", "timer/mock_timer_unittest.cc", "timer/timer_unittest.cc", "token_unittest.cc",
diff --git a/base/android/java/src/org/chromium/base/task/DefaultTaskExecutor.java b/base/android/java/src/org/chromium/base/task/DefaultTaskExecutor.java index 0c6ea796b..87db587b 100644 --- a/base/android/java/src/org/chromium/base/task/DefaultTaskExecutor.java +++ b/base/android/java/src/org/chromium/base/task/DefaultTaskExecutor.java
@@ -52,4 +52,9 @@ runner.postDelayedTask(task, delay); } } + + @Override + public boolean canRunTaskImmediately(TaskTraits traits) { + return false; + } }
diff --git a/base/android/java/src/org/chromium/base/task/PostTask.java b/base/android/java/src/org/chromium/base/task/PostTask.java index efc15db..0b6b30d 100644 --- a/base/android/java/src/org/chromium/base/task/PostTask.java +++ b/base/android/java/src/org/chromium/base/task/PostTask.java
@@ -87,6 +87,27 @@ } /** + * This function executes the task immediately if the current thread is the + * same as the one corresponding to the SingleThreadTaskRunner, otherwise it + * posts it. + * + * It should be executed only for tasks with traits corresponding to + * executors backed by a SingleThreadTaskRunner, like UiThreadTaskTraits. + * + * Use this only for trivial tasks as it ignores task priorities. + * + * @param taskTraits The TaskTraits that describe the desired TaskRunner. + * @param task The task to be run with the specified traits. + */ + public static void runOrPostTask(TaskTraits taskTraits, Runnable task) { + if (getTaskExecutorForTraits(taskTraits).canRunTaskImmediately(taskTraits)) { + task.run(); + } else { + postTask(taskTraits, task); + } + } + + /** * Registers a TaskExecutor, this must be called before any other usages of this API. * * @param extensionId The id associated with the TaskExecutor.
diff --git a/base/android/java/src/org/chromium/base/task/TaskExecutor.java b/base/android/java/src/org/chromium/base/task/TaskExecutor.java index 3a9e8cf..ad2b8c90 100644 --- a/base/android/java/src/org/chromium/base/task/TaskExecutor.java +++ b/base/android/java/src/org/chromium/base/task/TaskExecutor.java
@@ -34,4 +34,10 @@ * @return The TaskRunner for the specified TaskTraits. */ public SingleThreadTaskRunner createSingleThreadTaskRunner(TaskTraits traits); + + /** + * @return true iff the executor for these traits is backed by a SingleThreadTaskRunner + * associated with the current thread. + */ + public boolean canRunTaskImmediately(TaskTraits traits); }
diff --git a/base/containers/util.h b/base/containers/util.h index a190435..435db0d1 100644 --- a/base/containers/util.h +++ b/base/containers/util.h
@@ -5,6 +5,8 @@ #ifndef BASE_CONTAINERS_UTIL_H_ #define BASE_CONTAINERS_UTIL_H_ +#include <stdint.h> + namespace base { // TODO(crbug.com/817982): What we really need is for checked_math.h to be
diff --git a/base/task/sequence_manager/task_queue_impl.cc b/base/task/sequence_manager/task_queue_impl.cc index 850f177..53e28e9 100644 --- a/base/task/sequence_manager/task_queue_impl.cc +++ b/base/task/sequence_manager/task_queue_impl.cc
@@ -118,7 +118,7 @@ // contains a strong reference to this TaskQueueImpl and the // SequenceManagerImpl destructor calls UnregisterTaskQueue on all task // queues. - DCHECK(any_thread().unregistered) + DCHECK(any_thread_.unregistered) << "UnregisterTaskQueue must be called first!"; #endif } @@ -160,20 +160,18 @@ { AutoLock lock(any_thread_lock_); - AutoLock immediate_incoming_queue_lock(immediate_incoming_queue_lock_); - if (main_thread_only().time_domain) main_thread_only().time_domain->UnregisterQueue(this); - any_thread().unregistered = true; + any_thread_.unregistered = true; main_thread_only().on_task_completed_handler = OnTaskCompletedHandler(); - any_thread().time_domain = nullptr; + any_thread_.time_domain = nullptr; main_thread_only().time_domain = nullptr; main_thread_only().on_next_wake_up_changed_callback = OnNextWakeUpChangedCallback(); - immediate_incoming_queue.swap(immediate_incoming_queue_); + immediate_incoming_queue.swap(any_thread_.immediate_incoming_queue); empty_queues_to_reload_handle_.ReleaseAtomicFlag(); } @@ -221,42 +219,40 @@ // for details. CHECK(task.callback); - TimeTicks now; - bool add_queue_time_to_tasks = sequence_manager_->GetAddQueueTimeToTasks(); - if (delayed_fence_allowed_ || add_queue_time_to_tasks) { - if (current_thread == CurrentThread::kMainThread) { - now = main_thread_only().time_domain->Now(); - } else { - AutoLock lock(any_thread_lock_); - now = any_thread().time_domain->Now(); - } - if (add_queue_time_to_tasks) { - task.queue_time = now; - } - } - bool should_schedule_work = false; { // TODO(alexclarke): Maybe add a main thread only immediate_incoming_queue // See https://crbug.com/901800 - AutoLock lock(immediate_incoming_queue_lock_); + AutoLock lock(any_thread_lock_); + TimeTicks now; + bool add_queue_time_to_tasks = sequence_manager_->GetAddQueueTimeToTasks(); + if (delayed_fence_allowed_ || add_queue_time_to_tasks) { + now = any_thread_.time_domain->Now(); + if (add_queue_time_to_tasks) + task.queue_time = now; + } + // The sequence number must be incremented atomically with pushing onto the // incoming queue. Otherwise if there are several threads posting task we // risk breaking the assumption that sequence numbers increase monotonically // within a queue. EnqueueOrder sequence_number = sequence_manager_->GetNextSequenceNumber(); - bool was_immediate_incoming_queue_empty = immediate_incoming_queue_.empty(); - immediate_incoming_queue_.push_back( + bool was_immediate_incoming_queue_empty = + any_thread_.immediate_incoming_queue.empty(); + any_thread_.immediate_incoming_queue.push_back( Task(std::move(task), now, sequence_number, sequence_number)); - sequence_manager_->WillQueueTask(&immediate_incoming_queue_.back()); + sequence_manager_->WillQueueTask( + &any_thread_.immediate_incoming_queue.back()); // If this queue was completely empty, then the SequenceManager needs to be // informed so it can reload the work queue and add us to the // TaskQueueSelector which can only be done from the main thread. In // addition it may need to schedule a DoWork if this queue isn't blocked. - if (was_immediate_incoming_queue_empty && immediate_work_queue_empty_) { + if (was_immediate_incoming_queue_empty && + any_thread_.immediate_work_queue_empty) { empty_queues_to_reload_handle_.SetActive(true); - should_schedule_work = post_immediate_task_should_schedule_work_; + should_schedule_work = + any_thread_.post_immediate_task_should_schedule_work; } } @@ -265,9 +261,9 @@ // http://shortn/_ntnKNqjDQT for a discussion. // // Calling ScheduleWork outside the lock should be safe, only the main thread - // can mutate |post_immediate_task_should_schedule_work_|. If it transitions - // to false we call ScheduleWork redundantly that's harmless. If it - // transitions to true, the side effect of + // can mutate |any_thread_.post_immediate_task_should_schedule_work|. If it + // transitions to false we call ScheduleWork redundantly that's harmless. If + // it transitions to true, the side effect of // |empty_queues_to_reload_handle_SetActive(true)| is guaranteed to be picked // up by the ThreadController's call to SequenceManagerImpl::DelayTillNextTask // when it computes what continuation (if any) is needed. @@ -318,7 +314,7 @@ TimeTicks time_domain_now; { AutoLock lock(any_thread_lock_); - time_domain_now = any_thread().time_domain->Now(); + time_domain_now = any_thread_.time_domain->Now(); } TimeTicks time_domain_delayed_run_time = time_domain_now + task.delay; if (sequence_manager_->GetAddQueueTimeToTasks()) { @@ -389,13 +385,13 @@ } void TaskQueueImpl::TakeImmediateIncomingQueueTasks(TaskDeque* queue) { - AutoLock immediate_incoming_queue_lock(immediate_incoming_queue_lock_); + AutoLock any_thread_lock(any_thread_lock_); DCHECK(queue->empty()); - queue->swap(immediate_incoming_queue_); + queue->swap(any_thread_.immediate_incoming_queue); // Since |immediate_incoming_queue| is empty, now is a good time to consider // reducing it's capacity if we're wasting memory. - immediate_incoming_queue_.MaybeShrinkQueue(); + any_thread_.immediate_incoming_queue.MaybeShrinkQueue(); // Activate delayed fence if necessary. This is ideologically similar to // ActivateDelayedFenceIfNeeded, but due to immediate tasks being posted @@ -429,8 +425,8 @@ return false; } - AutoLock lock(immediate_incoming_queue_lock_); - return immediate_incoming_queue_.empty(); + AutoLock lock(any_thread_lock_); + return any_thread_.immediate_incoming_queue.empty(); } size_t TaskQueueImpl::GetNumberOfPendingTasks() const { @@ -439,8 +435,8 @@ task_count += main_thread_only().delayed_incoming_queue.size(); task_count += main_thread_only().immediate_work_queue->Size(); - AutoLock lock(immediate_incoming_queue_lock_); - task_count += immediate_incoming_queue_.size(); + AutoLock lock(any_thread_lock_); + task_count += any_thread_.immediate_incoming_queue.size(); return task_count; } @@ -460,8 +456,8 @@ } // Finally tasks on |immediate_incoming_queue| count as immediate work. - AutoLock lock(immediate_incoming_queue_lock_); - return !immediate_incoming_queue_.empty(); + AutoLock lock(any_thread_lock_); + return !any_thread_.immediate_incoming_queue.empty(); } Optional<DelayedWakeUp> TaskQueueImpl::GetNextScheduledWakeUpImpl() { @@ -520,9 +516,9 @@ if (!associated_thread_->IsBoundToCurrentThread()) return; - AutoLock lock(immediate_incoming_queue_lock_); + AutoLock lock(any_thread_lock_); TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("sequence_manager"), GetName(), - immediate_incoming_queue_.size() + + any_thread_.immediate_incoming_queue.size() + main_thread_only().immediate_work_queue->Size() + main_thread_only().delayed_work_queue->Size() + main_thread_only().delayed_incoming_queue.size()); @@ -545,10 +541,9 @@ trace_event::TracedValue* state, bool force_verbose) const { AutoLock lock(any_thread_lock_); - AutoLock immediate_incoming_queue_lock(immediate_incoming_queue_lock_); state->BeginDictionary(); state->SetString("name", GetName()); - if (any_thread().unregistered) { + if (any_thread_.unregistered) { state->SetBoolean("unregistered", true); state->EndDictionary(); return; @@ -564,8 +559,8 @@ state->SetBoolean("enabled", IsQueueEnabled()); state->SetString("time_domain_name", main_thread_only().time_domain->GetName()); - state->SetInteger("immediate_incoming_queue_size", - immediate_incoming_queue_.size()); + state->SetInteger("any_thread_.immediate_incoming_queuesize", + any_thread_.immediate_incoming_queue.size()); state->SetInteger("delayed_incoming_queue_size", main_thread_only().delayed_incoming_queue.size()); state->SetInteger("immediate_work_queue_size", @@ -573,8 +568,8 @@ state->SetInteger("delayed_work_queue_size", main_thread_only().delayed_work_queue->Size()); - state->SetInteger("immediate_incoming_queue_capacity", - immediate_incoming_queue_.capacity()); + state->SetInteger("any_thread_.immediate_incoming_queuecapacity", + any_thread_.immediate_incoming_queue.capacity()); state->SetInteger("immediate_work_queue_capacity", immediate_work_queue()->Capacity()); state->SetInteger("delayed_work_queue_capacity", @@ -602,7 +597,7 @@ if (verbose || force_verbose) { state->BeginArray("immediate_incoming_queue"); - QueueAsValueInto(immediate_incoming_queue_, now, state); + QueueAsValueInto(any_thread_.immediate_incoming_queue, now, state); state->EndArray(); state->BeginArray("delayed_work_queue"); main_thread_only().delayed_work_queue->AsValueInto(now, state); @@ -647,14 +642,14 @@ { AutoLock lock(any_thread_lock_); DCHECK(time_domain); - DCHECK(!any_thread().unregistered); - if (any_thread().unregistered) + DCHECK(!any_thread_.unregistered); + if (any_thread_.unregistered) return; DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker); if (time_domain == main_thread_only().time_domain) return; - any_thread().time_domain = time_domain; + any_thread_.time_domain = time_domain; } main_thread_only().time_domain->UnregisterQueue(this); @@ -697,11 +692,13 @@ main_thread_only().delayed_work_queue->InsertFence(current_fence); { - AutoLock lock(immediate_incoming_queue_lock_); + AutoLock lock(any_thread_lock_); if (!task_unblocked && previous_fence && previous_fence < current_fence) { - if (!immediate_incoming_queue_.empty() && - immediate_incoming_queue_.front().enqueue_order() > previous_fence && - immediate_incoming_queue_.front().enqueue_order() < current_fence) { + if (!any_thread_.immediate_incoming_queue.empty() && + any_thread_.immediate_incoming_queue.front().enqueue_order() > + previous_fence && + any_thread_.immediate_incoming_queue.front().enqueue_order() < + current_fence) { task_unblocked = true; } } @@ -732,10 +729,11 @@ task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); { - AutoLock lock(immediate_incoming_queue_lock_); + AutoLock lock(any_thread_lock_); if (!task_unblocked && previous_fence) { - if (!immediate_incoming_queue_.empty() && - immediate_incoming_queue_.front().enqueue_order() > previous_fence) { + if (!any_thread_.immediate_incoming_queue.empty() && + any_thread_.immediate_incoming_queue.front().enqueue_order() > + previous_fence) { task_unblocked = true; } } @@ -756,11 +754,11 @@ return false; } - AutoLock lock(immediate_incoming_queue_lock_); - if (immediate_incoming_queue_.empty()) + AutoLock lock(any_thread_lock_); + if (any_thread_.immediate_incoming_queue.empty()) return true; - return immediate_incoming_queue_.front().enqueue_order() > + return any_thread_.immediate_incoming_queue.front().enqueue_order() > main_thread_only().current_fence; } @@ -833,7 +831,7 @@ bool has_pending_immediate_work; { - AutoLock lock(immediate_incoming_queue_lock_); + AutoLock lock(any_thread_lock_); UpdateCrossThreadQueueStateLocked(); has_pending_immediate_work = HasPendingImmediateWorkLocked(); } @@ -854,18 +852,18 @@ } void TaskQueueImpl::UpdateCrossThreadQueueStateLocked() { - immediate_work_queue_empty_ = + any_thread_.immediate_work_queue_empty = main_thread_only().immediate_work_queue->Empty(); if (main_thread_only().on_next_wake_up_changed_callback) { // If there's a callback we need a DoWork for the callback to be issued by // ReloadEmptyImmediateWorkQueue. The callback isn't // sent for disabled queues. - post_immediate_task_should_schedule_work_ = IsQueueEnabled(); + any_thread_.post_immediate_task_should_schedule_work = IsQueueEnabled(); } else { // Otherwise we need PostImmediateTaskImpl to ScheduleWork unless the queue // is blocked or disabled. - post_immediate_task_should_schedule_work_ = + any_thread_.post_immediate_task_should_schedule_work = IsQueueEnabled() && !main_thread_only().current_fence; } } @@ -880,8 +878,8 @@ main_thread_only().immediate_work_queue->MaybeShrinkQueue(); { - AutoLock lock(immediate_incoming_queue_lock_); - immediate_incoming_queue_.MaybeShrinkQueue(); + AutoLock lock(any_thread_lock_); + any_thread_.immediate_incoming_queue.MaybeShrinkQueue(); } LazyNow lazy_now(now); @@ -889,8 +887,8 @@ } void TaskQueueImpl::PushImmediateIncomingTaskForTest(Task&& task) { - AutoLock lock(immediate_incoming_queue_lock_); - immediate_incoming_queue_.push_back(std::move(task)); + AutoLock lock(any_thread_lock_); + any_thread_.immediate_incoming_queue.push_back(std::move(task)); } void TaskQueueImpl::RequeueDeferredNonNestableTask( @@ -906,15 +904,16 @@ } else { // We're about to push |task| onto an empty |immediate_work_queue|. This // may mean we'd be violating the contract of AtomicFlagSet, it's - // only supposed to contain queues where |immediate_incoming_queue_| is - // non empty but |immediate_work_queue| is empty. We remedy that by removing - // ourselves from that list (a NOP if we're not in the list). + // only supposed to contain queues where + // |any_thread_.immediate_incoming_queue| is non empty but + // |immediate_work_queue| is empty. We remedy that by removing ourselves + // from that list (a NOP if we're not in the list). if (main_thread_only().immediate_work_queue->Empty()) { empty_queues_to_reload_handle_.SetActive(false); { - AutoLock lock(immediate_incoming_queue_lock_); - immediate_work_queue_empty_ = false; + AutoLock lock(any_thread_lock_); + any_thread_.immediate_work_queue_empty = false; main_thread_only().immediate_work_queue->PushNonNestableTaskToFront( std::move(task.task)); } @@ -974,15 +973,14 @@ } // Finally tasks on |immediate_incoming_queue| count as immediate work. - AutoLock lock(immediate_incoming_queue_lock_); - return !immediate_incoming_queue_.empty(); + AutoLock lock(any_thread_lock_); + return !any_thread_.immediate_incoming_queue.empty(); } bool TaskQueueImpl::HasPendingImmediateWorkLocked() { - immediate_incoming_queue_lock_.AssertAcquired(); return !main_thread_only().delayed_work_queue->Empty() || !main_thread_only().immediate_work_queue->Empty() || - !immediate_incoming_queue_.empty(); + !any_thread_.immediate_incoming_queue.empty(); } void TaskQueueImpl::SetOnTaskStartedHandler( @@ -1016,7 +1014,7 @@ bool TaskQueueImpl::IsUnregistered() const { AutoLock lock(any_thread_lock_); - return any_thread().unregistered; + return any_thread_.unregistered; } WeakPtr<SequenceManagerImpl> TaskQueueImpl::GetSequenceManagerWeakPtr() { @@ -1044,9 +1042,9 @@ { // Limit the scope of the lock to ensure that the deque is destroyed // outside of the lock to allow it to post tasks. - base::AutoLock lock(immediate_incoming_queue_lock_); - deque.swap(immediate_incoming_queue_); - immediate_work_queue_empty_ = true; + base::AutoLock lock(any_thread_lock_); + deque.swap(any_thread_.immediate_incoming_queue); + any_thread_.immediate_work_queue_empty = true; } LazyNow lazy_now = main_thread_only().time_domain->CreateLazyNow(); @@ -1061,8 +1059,8 @@ if (!main_thread_only().delayed_incoming_queue.empty()) return true; - base::AutoLock lock(immediate_incoming_queue_lock_); - if (!immediate_incoming_queue_.empty()) + base::AutoLock lock(any_thread_lock_); + if (!any_thread_.immediate_incoming_queue.empty()) return true; return false;
diff --git a/base/task/sequence_manager/task_queue_impl.h b/base/task/sequence_manager/task_queue_impl.h index 24af883..f06f599 100644 --- a/base/task/sequence_manager/task_queue_impl.h +++ b/base/task/sequence_manager/task_queue_impl.h
@@ -146,7 +146,7 @@ // Used to check if we need to generate notifications about delayed work. bool HasPendingImmediateWork(); bool HasPendingImmediateWorkLocked() - EXCLUSIVE_LOCKS_REQUIRED(immediate_incoming_queue_lock_); + EXCLUSIVE_LOCKS_REQUIRED(any_thread_lock_); bool has_pending_high_resolution_tasks() const { return main_thread_only() @@ -282,18 +282,6 @@ const int task_type_; }; - struct AnyThread { - explicit AnyThread(TimeDomain* time_domain); - ~AnyThread(); - - // TimeDomain is maintained in two copies: inside AnyThread and inside - // MainThreadOnly. It can be changed only from main thread, so it should be - // locked before accessing from other threads. - TimeDomain* time_domain; - - bool unregistered = false; - }; - // A queue for holding delayed tasks before their delay has expired. struct DelayedIncomingQueue { public: @@ -376,7 +364,8 @@ void ScheduleDelayedWorkTask(Task pending_task); - void MoveReadyImmediateTasksToImmediateWorkQueueLocked(); + void MoveReadyImmediateTasksToImmediateWorkQueueLocked() + EXCLUSIVE_LOCKS_REQUIRED(any_thread_lock_); // LazilyDeallocatedDeque use TimeTicks to figure out when to resize. We // should use real time here always. @@ -409,9 +398,9 @@ // Activate a delayed fence if a time has come. void ActivateDelayedFenceIfNeeded(TimeTicks now); - // Updates state protected by immediate_incoming_queue_lock_. + // Updates state protected by any_thread_lock_. void UpdateCrossThreadQueueStateLocked() - EXCLUSIVE_LOCKS_REQUIRED(immediate_incoming_queue_lock_); + EXCLUSIVE_LOCKS_REQUIRED(any_thread_lock_); const char* name_; SequenceManagerImpl* const sequence_manager_; @@ -421,15 +410,27 @@ const scoped_refptr<GuardedTaskPoster> task_poster_; mutable Lock any_thread_lock_; - AnyThread any_thread_; - struct AnyThread& any_thread() { - any_thread_lock_.AssertAcquired(); - return any_thread_; - } - const struct AnyThread& any_thread() const { - any_thread_lock_.AssertAcquired(); - return any_thread_; - } + + struct AnyThread { + explicit AnyThread(TimeDomain* time_domain); + ~AnyThread(); + + // TimeDomain is maintained in two copies: inside AnyThread and inside + // MainThreadOnly. It can be changed only from main thread, so it should be + // locked before accessing from other threads. + TimeDomain* time_domain; + + TaskDeque immediate_incoming_queue; + + // True if main_thread_only().immediate_work_queue is empty. + bool immediate_work_queue_empty = true; + + bool post_immediate_task_should_schedule_work = true; + + bool unregistered = false; + }; + + AnyThread any_thread_ GUARDED_BY(any_thread_lock_); MainThreadOnly main_thread_only_; MainThreadOnly& main_thread_only() { @@ -441,15 +442,6 @@ return main_thread_only_; } - mutable Lock immediate_incoming_queue_lock_; - TaskDeque immediate_incoming_queue_ - GUARDED_BY(immediate_incoming_queue_lock_); - // True if main_thread_only().immediate_work_queue is empty. - bool immediate_work_queue_empty_ GUARDED_BY(immediate_incoming_queue_lock_) = - true; - bool post_immediate_task_should_schedule_work_ - GUARDED_BY(immediate_incoming_queue_lock_) = true; - // Handle to our entry within the SequenceManagers |empty_queues_to_reload_| // atomic flag set. Used to signal that this queue needs to be reloaded. AtomicFlagSet::AtomicFlag empty_queues_to_reload_handle_;
diff --git a/base/test/scoped_task_environment.cc b/base/test/scoped_task_environment.cc index d601723..b9827df 100644 --- a/base/test/scoped_task_environment.cc +++ b/base/test/scoped_task_environment.cc
@@ -191,9 +191,12 @@ // We don't need to call ReclaimMemory here because // DelayTillNextTask will have dealt with cancelled delayed tasks for us. Optional<TimeTicks> run_time = NextScheduledRunTime(); - if (!run_time) { - // We've run out of tasks, but ScopedTaskEnvironment::FastForwardBy - // requires the virtual time to be consumed. + if (!run_time || run_time == now_ticks_) { + // We've run out of tasks (or an immediate task came in racily from + // another thread after reaching idle, ignore it, it will be processed in + // the next run as-if it arrived slightly later). + // ScopedTaskEnvironment::FastForwardBy requires the remaining virtual + // time to be consumed upon reaching idle. if (now_ticks_ < allow_advance_until_ && !allow_advance_until_.is_max()) SetTime(allow_advance_until_); return false; @@ -432,7 +435,6 @@ } sequence_manager::TimeDomain* ScopedTaskEnvironment::GetTimeDomain() const { - DCHECK(subclass_creates_default_taskrunner_); return mock_time_domain_ ? mock_time_domain_.get() : sequence_manager_->GetRealTimeDomain(); }
diff --git a/base/test/scoped_task_environment_unittest.cc b/base/test/scoped_task_environment_unittest.cc index 1c6fa67..f79a971281 100644 --- a/base/test/scoped_task_environment_unittest.cc +++ b/base/test/scoped_task_environment_unittest.cc
@@ -14,6 +14,7 @@ #include "base/synchronization/atomic_flag.h" #include "base/synchronization/waitable_event.h" #include "base/task/post_task.h" +#include "base/task/sequence_manager/time_domain.h" #include "base/test/mock_callback.h" #include "base/test/test_timeouts.h" #include "base/threading/platform_thread.h" @@ -38,6 +39,19 @@ namespace { +class ScopedTaskEnvironmentForTest : public ScopedTaskEnvironment { + public: + template < + class... ArgTypes, + class CheckArgumentsAreValid = std::enable_if_t< + base::trait_helpers::AreValidTraits<ScopedTaskEnvironment::ValidTrait, + ArgTypes...>::value>> + NOINLINE ScopedTaskEnvironmentForTest(const ArgTypes... args) + : ScopedTaskEnvironment(args...) {} + + using ScopedTaskEnvironment::GetTimeDomain; +}; + class ScopedTaskEnvironmentTest : public testing::TestWithParam<ScopedTaskEnvironment::MainThreadType> {}; @@ -345,6 +359,46 @@ EXPECT_EQ(start_time + kDelay, base::TimeTicks::Now()); } +TEST_F(ScopedTaskEnvironmentTest, MockTimeDomain_MaybeFastForwardToNextTask) { + constexpr base::TimeDelta kDelay = TimeDelta::FromSeconds(42); + ScopedTaskEnvironmentForTest scoped_task_environment( + ScopedTaskEnvironment::MainThreadType::MOCK_TIME, + ScopedTaskEnvironment::NowSource::MAIN_THREAD_MOCK_TIME); + const TimeTicks start_time = base::TimeTicks::Now(); + EXPECT_FALSE( + scoped_task_environment.GetTimeDomain()->MaybeFastForwardToNextTask( + false)); + EXPECT_EQ(start_time, base::TimeTicks::Now()); + + ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, base::DoNothing(), + kDelay); + EXPECT_TRUE( + scoped_task_environment.GetTimeDomain()->MaybeFastForwardToNextTask( + false)); + EXPECT_EQ(start_time + kDelay, base::TimeTicks::Now()); +} + +TEST_F(ScopedTaskEnvironmentTest, + MockTimeDomain_MaybeFastForwardToNextTask_ImmediateTaskPending) { + constexpr base::TimeDelta kDelay = TimeDelta::FromSeconds(42); + ScopedTaskEnvironmentForTest scoped_task_environment( + ScopedTaskEnvironment::MainThreadType::MOCK_TIME, + ScopedTaskEnvironment::NowSource::MAIN_THREAD_MOCK_TIME); + const TimeTicks start_time = base::TimeTicks::Now(); + EXPECT_FALSE( + scoped_task_environment.GetTimeDomain()->MaybeFastForwardToNextTask( + false)); + EXPECT_EQ(start_time, base::TimeTicks::Now()); + + ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, base::DoNothing(), + kDelay); + ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::DoNothing()); + EXPECT_FALSE( + scoped_task_environment.GetTimeDomain()->MaybeFastForwardToNextTask( + false)); + EXPECT_EQ(start_time, base::TimeTicks::Now()); +} + #if defined(OS_WIN) // Regression test to ensure that ScopedTaskEnvironment enables the MTA in the // thread pool (so that the test environment matches that of the browser process
diff --git a/base/timer/lap_timer.cc b/base/timer/lap_timer.cc new file mode 100644 index 0000000..3ff2465 --- /dev/null +++ b/base/timer/lap_timer.cc
@@ -0,0 +1,118 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/timer/lap_timer.h" +#include "base/logging.h" + +namespace base { + +namespace { + +// Default values. +constexpr TimeDelta kDefaultTimeLimit = TimeDelta::FromSeconds(3); +constexpr int kDefaultWarmupRuns = 5; +constexpr int kDefaultTimeCheckInterval = 10; + +} // namespace + +LapTimer::LapTimer(int warmup_laps, + TimeDelta time_limit, + int check_interval, + LapTimer::TimerMethod method) + : warmup_laps_(warmup_laps), + time_limit_(time_limit), + check_interval_(check_interval), + method_(method) { + DETACH_FROM_SEQUENCE(sequence_checker_); + DCHECK_GT(check_interval, 0); + Reset(); +} + +LapTimer::LapTimer(LapTimer::TimerMethod method) + : LapTimer(kDefaultWarmupRuns, + kDefaultTimeLimit, + kDefaultTimeCheckInterval, + method) {} + +void LapTimer::Reset() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (ThreadTicks::IsSupported() && method_ == TimerMethod::kUseThreadTicks) + ThreadTicks::WaitUntilInitialized(); + num_laps_ = 0; + remaining_warmups_ = warmup_laps_; + remaining_no_check_laps_ = check_interval_; + Start(); +} + +void LapTimer::Start() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(num_laps_, 0); + // last_timed_ variables are initialized here (instead of in the constructor) + // because not all platforms support ThreadTicks. + if (method_ == TimerMethod::kUseThreadTicks) { + start_thread_ticks_ = ThreadTicks::Now(); + last_timed_lap_end_thread_ticks_ = ThreadTicks::Now(); + } else { + start_time_ticks_ = TimeTicks::Now(); + last_timed_lap_end_ticks_ = TimeTicks::Now(); + } +} + +bool LapTimer::IsWarmedUp() const { + return remaining_warmups_ <= 0; +} + +void LapTimer::NextLap() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!start_thread_ticks_.is_null() || !start_time_ticks_.is_null()); + if (!IsWarmedUp()) { + --remaining_warmups_; + if (IsWarmedUp()) { + Start(); + } + return; + } + ++num_laps_; + --remaining_no_check_laps_; + if (!remaining_no_check_laps_) { + if (method_ == TimerMethod::kUseTimeTicks) { + last_timed_lap_end_ticks_ = TimeTicks::Now(); + } else { + last_timed_lap_end_thread_ticks_ = ThreadTicks::Now(); + } + remaining_no_check_laps_ = check_interval_; + } +} + +TimeDelta LapTimer::GetAccumulatedTime() const { + if (method_ == TimerMethod::kUseTimeTicks) { + return last_timed_lap_end_ticks_ - start_time_ticks_; + } + return last_timed_lap_end_thread_ticks_ - start_thread_ticks_; +} + +bool LapTimer::HasTimeLimitExpired() const { + return GetAccumulatedTime() >= time_limit_; +} + +bool LapTimer::HasTimedAllLaps() const { + return num_laps_ && !(num_laps_ % check_interval_); +} + +TimeDelta LapTimer::TimePerLap() const { + DCHECK(HasTimedAllLaps()); + DCHECK_GT(num_laps_, 0); + return GetAccumulatedTime() / num_laps_; +} + +float LapTimer::LapsPerSecond() const { + DCHECK(HasTimedAllLaps()); + DCHECK_GT(num_laps_, 0); + return num_laps_ / GetAccumulatedTime().InSecondsF(); +} + +int LapTimer::NumLaps() const { + return num_laps_; +} +} // namespace base
diff --git a/base/timer/lap_timer.h b/base/timer/lap_timer.h new file mode 100644 index 0000000..c28a0df --- /dev/null +++ b/base/timer/lap_timer.h
@@ -0,0 +1,87 @@ +// Copyright 2014 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 BASE_TIMER_LAP_TIMER_H_ +#define BASE_TIMER_LAP_TIMER_H_ + +#include "base/base_export.h" +#include "base/macros.h" +#include "base/sequence_checker.h" +#include "base/time/time.h" + +namespace base { + +// LapTimer is used to calculate average times per "Lap" in perf tests. +// NextLap increments the lap counter, used in counting the per lap averages. +// If you initialize the LapTimer with a non zero |warmup_laps|, it will ignore +// the times for that many laps at the start. +// If you set the |time_limit| then you can use HasTimeLimitExpired() to see if +// the current accumulated time has crossed that threshold, with an optimization +// that it only tests this every |check_interval| laps. +// +// See base/timer/lap_timer_unittest.cc for a usage example. +// +class BASE_EXPORT LapTimer { + public: + enum class TimerMethod { + // Measures CPU time consumed by the thread running the LapTimer. + kUseThreadTicks, + // Measures elapsed wall time (default). + kUseTimeTicks + }; + + LapTimer(int warmup_laps, + TimeDelta time_limit, + int check_interval, + TimerMethod timing_method = TimerMethod::kUseTimeTicks); + // Create LapTimer with sensible default values. + LapTimer(TimerMethod timing_method = TimerMethod::kUseTimeTicks); + // Sets the timer back to its starting state. + void Reset(); + // Sets the start point to now. + void Start(); + // Returns true if there are no more warmup laps to do. + bool IsWarmedUp() const; + // Advance the lap counter and update the accumulated time. + // The accumulated time is only updated every check_interval laps. + // If accumulating then the start point will also be updated. + void NextLap(); + // Returns true if the stored time has exceeded the time limit specified. + // May cause a call to Store(). + bool HasTimeLimitExpired() const; + // The average time taken per lap. + TimeDelta TimePerLap() const; + // The number of laps per second. + float LapsPerSecond() const; + // The number of laps recorded. + int NumLaps() const; + + private: + // Returns true if all lap times have been timed. Only true every n'th + // lap, where n = check_interval. + bool HasTimedAllLaps() const; + // Returns the current accumulated time. + TimeDelta GetAccumulatedTime() const; + + const int warmup_laps_; + const TimeDelta time_limit_; + const int check_interval_; + const TimerMethod method_; + + ThreadTicks start_thread_ticks_; + TimeTicks start_time_ticks_; + + ThreadTicks last_timed_lap_end_thread_ticks_; + TimeTicks last_timed_lap_end_ticks_; + + int num_laps_; + int remaining_warmups_ = 0; + int remaining_no_check_laps_ = 0; + + SEQUENCE_CHECKER(sequence_checker_); + DISALLOW_COPY_AND_ASSIGN(LapTimer); +}; +} // namespace base + +#endif // BASE_TIMER_LAP_TIMER_H_
diff --git a/base/timer/lap_timer_unittest.cc b/base/timer/lap_timer_unittest.cc new file mode 100644 index 0000000..b45ab39 --- /dev/null +++ b/base/timer/lap_timer_unittest.cc
@@ -0,0 +1,85 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/timer/lap_timer.h" +#include "base/test/scoped_task_environment.h" +#include "base/time/time.h" +#include "build/build_config.h" +#include "testing/gtest/include/gtest/gtest.h" + +// This file contains a minimal unit test for LapTimer, used for benchmarking. +// This file is supposed to match closely with the example code, documented in +// lap_timer.h. Please update that documentation if you need to change things. + +namespace base { + +namespace test { + +namespace { + +constexpr base::TimeDelta kTimeLimit = base::TimeDelta::FromMilliseconds(15); +constexpr base::TimeDelta kTimeAdvance = base::TimeDelta::FromMilliseconds(1); +constexpr int kWarmupRuns = 5; +constexpr int kTimeCheckInterval = 10; + +} // namespace + +TEST(LapTimer, UsageExample) { + ScopedTaskEnvironment scoped_task_environment( + ScopedTaskEnvironment::MainThreadType::MOCK_TIME, + ScopedTaskEnvironment::NowSource::MAIN_THREAD_MOCK_TIME); + + // Advance time a little bit so that TimeTicks::Now().is_null() becomes false. + scoped_task_environment.FastForwardBy(kTimeAdvance); + + LapTimer timer(kWarmupRuns, kTimeLimit, kTimeCheckInterval); + + EXPECT_FALSE(timer.HasTimeLimitExpired()); + EXPECT_FALSE(timer.IsWarmedUp()); + + do { + scoped_task_environment.FastForwardBy(kTimeAdvance); + timer.NextLap(); + } while (!timer.HasTimeLimitExpired()); + + EXPECT_NEAR(timer.LapsPerSecond(), 1000, 0.1); + EXPECT_NEAR(timer.TimePerLap().InMillisecondsF(), 1.0f, 0.1); + // Output number of laps is 20, because the warm up runs are ignored and the + // timer is only checked every kTimeInterval laps. + EXPECT_EQ(timer.NumLaps(), 20); + + EXPECT_TRUE(timer.HasTimeLimitExpired()); + EXPECT_TRUE(timer.IsWarmedUp()); +} + +#if !defined(OS_IOS) +// iOS simulator does not support using ThreadTicks. +TEST(LapTimer, ThreadTicksUsageExample) { + ScopedTaskEnvironment scoped_task_environment( + ScopedTaskEnvironment::MainThreadType::MOCK_TIME, + ScopedTaskEnvironment::NowSource::MAIN_THREAD_MOCK_TIME); + LapTimer timer(kWarmupRuns, kTimeLimit, kTimeCheckInterval, + LapTimer::TimerMethod::kUseThreadTicks); + + EXPECT_FALSE(timer.HasTimeLimitExpired()); + EXPECT_FALSE(timer.IsWarmedUp()); + + do { + scoped_task_environment.FastForwardBy(kTimeAdvance); + timer.NextLap(); + } while (!timer.HasTimeLimitExpired()); + + // Because advancing the ScopedTaskEnvironment time won't affect the + // ThreadTicks, laps will be much faster than the regular UsageExample. + EXPECT_GT(timer.LapsPerSecond(), 1000); + EXPECT_LT(timer.TimePerLap().InMillisecondsF(), 1.0f); + EXPECT_GT(timer.NumLaps(), 20); + + EXPECT_TRUE(timer.HasTimeLimitExpired()); + EXPECT_TRUE(timer.IsWarmedUp()); +} +#endif + +} // namespace test +} // namespace base
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 135cdf3..38329cb 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -882938bbc85eb6781490026cad45e29448c26cf1 \ No newline at end of file +8384d21f4cd044e49e9688d570fa8527acfc709e \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index d45cd81..6fd5deb 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -1a7a29783cf061f4b571e4ebc8f56a7dc1a82935 \ No newline at end of file +81f6ea6d6e06600e407138c46ad4439b1db09a5e \ No newline at end of file
diff --git a/cc/animation/animation_host_perftest.cc b/cc/animation/animation_host_perftest.cc index afadb46..3bd2568 100644 --- a/cc/animation/animation_host_perftest.cc +++ b/cc/animation/animation_host_perftest.cc
@@ -5,11 +5,11 @@ #include "cc/animation/animation_host.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/timer/lap_timer.h" #include "cc/animation/animation_id_provider.h" #include "cc/animation/animation_timeline.h" #include "cc/animation/keyframe_effect.h" #include "cc/animation/single_keyframe_effect_animation.h" -#include "cc/base/lap_timer.h" #include "cc/test/fake_impl_task_runner_provider.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_layer_tree_host_client.h" @@ -149,7 +149,7 @@ int first_animation_id_; int last_animation_id_; - LapTimer timer_; + base::LapTimer timer_; TestTaskGraphRunner task_graph_runner_; };
diff --git a/cc/base/BUILD.gn b/cc/base/BUILD.gn index 8f8a1845..9546cd27 100644 --- a/cc/base/BUILD.gn +++ b/cc/base/BUILD.gn
@@ -20,8 +20,6 @@ "index_rect.h", "invalidation_region.cc", "invalidation_region.h", - "lap_timer.cc", - "lap_timer.h", "list_container.h", "list_container_helper.cc", "list_container_helper.h",
diff --git a/cc/base/DEPS b/cc/base/DEPS index 1bcb1a1..909b4a27 100644 --- a/cc/base/DEPS +++ b/cc/base/DEPS
@@ -9,8 +9,4 @@ ".*unittest\.cc": [ "+cc/test", ], - # Allow lap_timer.h for perftests - ".*perftest\.cc": [ - "+cc/debug/lap_timer.h", - ], }
diff --git a/cc/base/lap_timer.cc b/cc/base/lap_timer.cc deleted file mode 100644 index 42335a8c..0000000 --- a/cc/base/lap_timer.cc +++ /dev/null
@@ -1,105 +0,0 @@ -// Copyright 2014 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 "cc/base/lap_timer.h" - -#include "base/logging.h" - -namespace cc { - -namespace { - -// Returns the offset from the origin from the ThreadTicks time source. -// TimeTicks is used as a fallback if ThreadTicks is not available on the -// current platform. -base::TimeDelta Now() { - return base::ThreadTicks::IsSupported() - ? base::ThreadTicks::Now().since_origin() - : base::TimeTicks::Now().since_origin(); -} - -// Default values. -static const int kTimeLimitMillis = 3000; -static const int kWarmupRuns = 5; -static const int kTimeCheckInterval = 10; - -} // namespace - -LapTimer::LapTimer(int warmup_laps, - base::TimeDelta time_limit, - int check_interval) - : warmup_laps_(warmup_laps), - remaining_warmups_(0), - remaining_no_check_laps_(0), - time_limit_(time_limit), - check_interval_(check_interval) { - DCHECK_GT(check_interval, 0); - Reset(); -} - -LapTimer::LapTimer() - : LapTimer(kWarmupRuns, - base::TimeDelta::FromMilliseconds(kTimeLimitMillis), - kTimeCheckInterval) { - if (base::ThreadTicks::IsSupported()) - base::ThreadTicks::WaitUntilInitialized(); -} - -void LapTimer::Reset() { - accumulator_ = base::TimeDelta(); - num_laps_ = 0; - remaining_warmups_ = warmup_laps_; - remaining_no_check_laps_ = check_interval_; - Start(); -} - -void LapTimer::Start() { - start_time_ = Now(); -} - -bool LapTimer::IsWarmedUp() { - return remaining_warmups_ <= 0; -} - -void LapTimer::NextLap() { - if (!IsWarmedUp()) { - --remaining_warmups_; - if (IsWarmedUp()) { - Start(); - } - return; - } - ++num_laps_; - --remaining_no_check_laps_; - if (!remaining_no_check_laps_) { - base::TimeDelta now = Now(); - accumulator_ += now - start_time_; - start_time_ = now; - remaining_no_check_laps_ = check_interval_; - } -} - -bool LapTimer::HasTimeLimitExpired() { - return accumulator_ >= time_limit_; -} - -bool LapTimer::HasTimedAllLaps() { - return !(num_laps_ % check_interval_); -} - -float LapTimer::MsPerLap() { - DCHECK(HasTimedAllLaps()); - return accumulator_.InMillisecondsF() / num_laps_; -} - -float LapTimer::LapsPerSecond() { - DCHECK(HasTimedAllLaps()); - return num_laps_ / accumulator_.InSecondsF(); -} - -int LapTimer::NumLaps() { - return num_laps_; -} - -} // namespace cc
diff --git a/cc/base/lap_timer.h b/cc/base/lap_timer.h deleted file mode 100644 index 5b27e25..0000000 --- a/cc/base/lap_timer.h +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright 2014 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 CC_BASE_LAP_TIMER_H_ -#define CC_BASE_LAP_TIMER_H_ - -#include "base/macros.h" -#include "base/time/time.h" -#include "cc/base/base_export.h" - -namespace cc { - -// LapTimer is used to calculate average times per "Lap" in perf tests. -// Current() reports the time since the last call to Start(). -// Store() adds the time since the last call to Start() to the accumulator, and -// resets the start time to now. Stored() returns the accumulated time. -// NextLap increments the lap counter, used in counting the per lap averages. -// If you initialize the LapTimer with a non zero warmup_laps, it will ignore -// the times for that many laps at the start. -// If you set the time_limit then you can use HasTimeLimitExpired() to see if -// the current accumulated time has crossed that threshold, with an optimization -// that it only tests this every check_interval laps. -class CC_BASE_EXPORT LapTimer { - public: - LapTimer(int warmup_laps, base::TimeDelta time_limit, int check_interval); - // Create LapTimer with sensible default values. - LapTimer(); - // Resets the timer back to it's starting state. - void Reset(); - // Sets the start point to now. - void Start(); - // Returns true if there are no more warmup laps to do. - bool IsWarmedUp(); - // Advance the lap counter and update the accumulated time. - // The accumulated time is only updated every check_interval laps. - // If accumulating then the start point will also be updated. - void NextLap(); - // Returns true if the stored time has exceeded the time limit specified. - // May cause a call to Store(). - bool HasTimeLimitExpired(); - // Returns true if all lap times have been timed. Only true every n'th - // lap, where n = check_interval. - bool HasTimedAllLaps(); - // The average milliseconds per lap. - float MsPerLap(); - // The number of laps per second. - float LapsPerSecond(); - // The number of laps recorded. - int NumLaps(); - - private: - base::TimeDelta start_time_; - base::TimeDelta accumulator_; - int num_laps_; - int warmup_laps_; - int remaining_warmups_; - int remaining_no_check_laps_; - base::TimeDelta time_limit_; - int check_interval_; - - DISALLOW_COPY_AND_ASSIGN(LapTimer); -}; - -} // namespace cc - -#endif // CC_BASE_LAP_TIMER_H_
diff --git a/cc/base/rtree_perftest.cc b/cc/base/rtree_perftest.cc index 70d44bc..3b12bf5 100644 --- a/cc/base/rtree_perftest.cc +++ b/cc/base/rtree_perftest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/base/lap_timer.h" +#include "base/timer/lap_timer.h" #include "cc/base/rtree.h" #include "testing/gtest/include/gtest/gtest.h" @@ -85,7 +85,7 @@ } protected: - LapTimer timer_; + base::LapTimer timer_; }; TEST_F(RTreePerfTest, Construct) {
diff --git a/cc/benchmarks/rasterize_and_record_benchmark.cc b/cc/benchmarks/rasterize_and_record_benchmark.cc index 4b78bfd..844f66a 100644 --- a/cc/benchmarks/rasterize_and_record_benchmark.cc +++ b/cc/benchmarks/rasterize_and_record_benchmark.cc
@@ -13,8 +13,8 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/strings/stringprintf.h" +#include "base/timer/lap_timer.h" #include "base/values.h" -#include "cc/base/lap_timer.h" #include "cc/benchmarks/rasterize_and_record_benchmark_impl.h" #include "cc/layers/content_layer_client.h" #include "cc/layers/layer.h" @@ -31,7 +31,7 @@ const int kDefaultRecordRepeatCount = 100; -// Parameters for LapTimer. +// Parameters for base::LapTimer. const int kTimeLimitMillis = 1; const int kWarmupRuns = 0; const int kTimeCheckInterval = 1; @@ -158,9 +158,9 @@ for (int i = 0; i < record_repeat_count_; ++i) { // Run for a minimum amount of time to avoid problems with timer // quantization when the layer is very small. - LapTimer timer(kWarmupRuns, - base::TimeDelta::FromMilliseconds(kTimeLimitMillis), - kTimeCheckInterval); + base::LapTimer timer(kWarmupRuns, + base::TimeDelta::FromMilliseconds(kTimeLimitMillis), + kTimeCheckInterval); do { display_list = painter->PaintContentsToDisplayList(painting_control); @@ -179,8 +179,7 @@ timer.NextLap(); } while (!timer.HasTimeLimitExpired()); - base::TimeDelta duration = - base::TimeDelta::FromMillisecondsD(timer.MsPerLap()); + base::TimeDelta duration = timer.TimePerLap(); if (duration < min_time) min_time = duration; }
diff --git a/cc/benchmarks/rasterize_and_record_benchmark_impl.cc b/cc/benchmarks/rasterize_and_record_benchmark_impl.cc index d3652f0d..cf7f706 100644 --- a/cc/benchmarks/rasterize_and_record_benchmark_impl.cc +++ b/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
@@ -9,8 +9,8 @@ #include <algorithm> #include <limits> +#include "base/timer/lap_timer.h" #include "base/values.h" -#include "cc/base/lap_timer.h" #include "cc/layers/layer_impl.h" #include "cc/layers/picture_layer_impl.h" #include "cc/raster/playback_image_provider.h" @@ -34,7 +34,7 @@ size_t repeat_count, base::TimeDelta* min_time, bool* is_solid_color) { - // Parameters for LapTimer. + // Parameters for base::LapTimer. const int kTimeLimitMillis = 1; const int kWarmupRuns = 0; const int kTimeCheckInterval = 1; @@ -43,9 +43,9 @@ for (size_t i = 0; i < repeat_count; ++i) { // Run for a minimum amount of time to avoid problems with timer // quantization when the layer is very small. - LapTimer timer(kWarmupRuns, - base::TimeDelta::FromMilliseconds(kTimeLimitMillis), - kTimeCheckInterval); + base::LapTimer timer(kWarmupRuns, + base::TimeDelta::FromMilliseconds(kTimeLimitMillis), + kTimeCheckInterval); SkColor color = SK_ColorTRANSPARENT; gfx::Rect layer_rect = gfx::ScaleToEnclosingRect(content_rect, 1.f / contents_scale); @@ -78,8 +78,7 @@ timer.NextLap(); } while (!timer.HasTimeLimitExpired()); - base::TimeDelta duration = - base::TimeDelta::FromMillisecondsD(timer.MsPerLap()); + base::TimeDelta duration = timer.TimePerLap(); if (duration < *min_time) *min_time = duration; }
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index 837b7e0..d2e95ca 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h
@@ -126,6 +126,10 @@ void PopulateSharedQuadState(viz::SharedQuadState* state, bool contents_opaque) const; + + // If using this, you need to override GetEnclosingRectInTargetSpace() to + // use GetScaledEnclosingRectInTargetSpace(). To do otherwise may result in + // inconsistent values, and drawing/clipping problems. void PopulateScaledSharedQuadState(viz::SharedQuadState* state, float layer_to_content_scale_x, float layer_to_content_scale_y, @@ -425,6 +429,10 @@ // for layers that provide it. virtual Region GetInvalidationRegionForDebugging(); + // If you override this, and are making use of + // PopulateScaledSharedQuadState(), make sure you call + // GetScaledEnclosingRectInTargetSpace(). See comment for + // PopulateScaledSharedQuadState(). virtual gfx::Rect GetEnclosingRectInTargetSpace() const; void UpdatePropertyTreeForAnimationIfNeeded(ElementId element_id); @@ -476,6 +484,10 @@ SkColor color, float width) const; + // Returns the bounds of this layer in target space when scaled by |scale|. + // This function scales in the same way as + // PopulateScaledSharedQuadStateQuadState(). See + // PopulateScaledSharedQuadStateQuadState() for more details. gfx::Rect GetScaledEnclosingRectInTargetSpace(float scale) const; private: @@ -551,6 +563,8 @@ DrawMode current_draw_mode_; private: + FRIEND_TEST_ALL_PREFIXES(SurfaceLayerImplTest, GetEnclosingRectInTargetSpace); + PropertyTrees* GetPropertyTrees() const; ClipTree& GetClipTree() const; EffectTree& GetEffectTree() const;
diff --git a/cc/layers/layer_perftest.cc b/cc/layers/layer_perftest.cc index a0bee52..c217188 100644 --- a/cc/layers/layer_perftest.cc +++ b/cc/layers/layer_perftest.cc
@@ -5,8 +5,8 @@ #include "cc/layers/layer.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/timer/lap_timer.h" #include "cc/animation/animation_host.h" -#include "cc/base/lap_timer.h" #include "cc/test/fake_impl_task_runner_provider.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_layer_tree_host_client.h" @@ -53,7 +53,7 @@ FakeLayerTreeHostClient fake_client_; std::unique_ptr<AnimationHost> animation_host_; std::unique_ptr<FakeLayerTreeHost> layer_tree_host_; - LapTimer timer_; + base::LapTimer timer_; }; TEST_F(LayerPerfTest, PushPropertiesTo) {
diff --git a/cc/layers/picture_layer_impl_perftest.cc b/cc/layers/picture_layer_impl_perftest.cc index 36425eb..281beab 100644 --- a/cc/layers/picture_layer_impl_perftest.cc +++ b/cc/layers/picture_layer_impl_perftest.cc
@@ -6,7 +6,7 @@ #include "base/macros.h" #include "base/threading/thread_task_runner_handle.h" -#include "cc/base/lap_timer.h" +#include "base/timer/lap_timer.h" #include "cc/test/fake_impl_task_runner_provider.h" #include "cc/test/fake_layer_tree_frame_sink.h" #include "cc/test/fake_layer_tree_host_impl.h" @@ -174,7 +174,7 @@ std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink_; FakeLayerTreeHostImpl host_impl_; FakePictureLayerImpl* pending_layer_; - LapTimer timer_; + base::LapTimer timer_; private: DISALLOW_COPY_AND_ASSIGN(PictureLayerImplPerfTest);
diff --git a/cc/layers/surface_layer_impl.cc b/cc/layers/surface_layer_impl.cc index 36c4dc3..9f9bd25 100644 --- a/cc/layers/surface_layer_impl.cc +++ b/cc/layers/surface_layer_impl.cc
@@ -152,6 +152,11 @@ return true; } +gfx::Rect SurfaceLayerImpl::GetEnclosingRectInTargetSpace() const { + return GetScaledEnclosingRectInTargetSpace( + layer_tree_impl()->device_scale_factor()); +} + viz::SurfaceDrawQuad* SurfaceLayerImpl::CreateSurfaceDrawQuad( viz::RenderPass* render_pass, const viz::SurfaceRange& surface_range) {
diff --git a/cc/layers/surface_layer_impl.h b/cc/layers/surface_layer_impl.h index 64ff796..d00a8ba 100644 --- a/cc/layers/surface_layer_impl.h +++ b/cc/layers/surface_layer_impl.h
@@ -69,6 +69,7 @@ void AppendQuads(viz::RenderPass* render_pass, AppendQuadsData* append_quads_data) override; bool is_surface_layer() const override; + gfx::Rect GetEnclosingRectInTargetSpace() const override; protected: SurfaceLayerImpl(LayerTreeImpl* tree_impl, int id, UpdateSubmissionStateCB);
diff --git a/cc/layers/surface_layer_impl_unittest.cc b/cc/layers/surface_layer_impl_unittest.cc index c0fc9e7..531445a 100644 --- a/cc/layers/surface_layer_impl_unittest.cc +++ b/cc/layers/surface_layer_impl_unittest.cc
@@ -262,4 +262,31 @@ } } // namespace + +// This test is outside the anonymous namespace so that it can be a friend. +TEST(SurfaceLayerImplTest, GetEnclosingRectInTargetSpace) { + gfx::Size layer_size(902, 1000); + gfx::Size viewport_size(902, 1000); + LayerTestCommon::LayerImplTest impl; + SurfaceLayerImpl* surface_layer_impl = + impl.AddChildToRoot<SurfaceLayerImpl>(); + surface_layer_impl->SetBounds(layer_size); + surface_layer_impl->SetDrawsContent(true); + + // A device scale of 1.33 and transform of 1.5 were chosen as they produce + // different results when rounding at each stage, vs applying a single + // transform. + gfx::Transform transform; + transform.Scale(1.5, 1.5); + impl.host_impl()->active_tree()->SetDeviceScaleFactor(1.33); + impl.CalcDrawProps(viewport_size); + surface_layer_impl->draw_properties().target_space_transform = transform; + + // GetEnclosingRectInTargetSpace() and GetScaledEnclosingRectInTargetSpace() + // should return the same value, otherwise we may not damage the right + // pixels. + EXPECT_EQ(surface_layer_impl->GetScaledEnclosingRectInTargetSpace(1.33), + surface_layer_impl->GetEnclosingRectInTargetSpace()); +} + } // namespace cc
diff --git a/cc/paint/paint_op_perftest.cc b/cc/paint/paint_op_perftest.cc index d137118..6dacf3eb 100644 --- a/cc/paint/paint_op_perftest.cc +++ b/cc/paint/paint_op_perftest.cc
@@ -6,7 +6,7 @@ #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_suite.h" -#include "cc/base/lap_timer.h" +#include "base/timer/lap_timer.h" #include "cc/paint/paint_op_buffer.h" #include "cc/paint/paint_op_buffer_serializer.h" #include "cc/test/test_options_provider.h" @@ -104,7 +104,7 @@ } protected: - LapTimer timer_; + base::LapTimer timer_; std::unique_ptr<char, base::AlignedFreeDeleter> serialized_data_; std::unique_ptr<char, base::AlignedFreeDeleter> deserialized_data_; };
diff --git a/cc/raster/raster_buffer_provider_perftest.cc b/cc/raster/raster_buffer_provider_perftest.cc index dc5fd57..6eb36031 100644 --- a/cc/raster/raster_buffer_provider_perftest.cc +++ b/cc/raster/raster_buffer_provider_perftest.cc
@@ -8,8 +8,8 @@ #include "base/macros.h" #include "base/test/test_simple_task_runner.h" #include "base/time/time.h" +#include "base/timer/lap_timer.h" #include "build/build_config.h" -#include "cc/base/lap_timer.h" #include "cc/raster/bitmap_raster_buffer_provider.h" #include "cc/raster/gpu_raster_buffer_provider.h" #include "cc/raster/one_copy_raster_buffer_provider.h" @@ -340,7 +340,7 @@ scoped_refptr<base::TestSimpleTaskRunner> task_runner_; std::unique_ptr<ResourcePool> resource_pool_; std::unique_ptr<SynchronousTaskGraphRunner> task_graph_runner_; - LapTimer timer_; + base::LapTimer timer_; }; class RasterBufferProviderPerfTest
diff --git a/cc/raster/task_graph_runner_perftest.cc b/cc/raster/task_graph_runner_perftest.cc index 8a67451..36ee90fa 100644 --- a/cc/raster/task_graph_runner_perftest.cc +++ b/cc/raster/task_graph_runner_perftest.cc
@@ -11,8 +11,8 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/time/time.h" +#include "base/timer/lap_timer.h" #include "cc/base/completion_event.h" -#include "cc/base/lap_timer.h" #include "cc/raster/synchronous_task_graph_runner.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/perf/perf_test.h" @@ -274,7 +274,7 @@ // minimal additional complexity over the TaskGraphWorkQueue helpers. std::unique_ptr<SynchronousTaskGraphRunner> task_graph_runner_; NamespaceToken namespace_token_; - LapTimer timer_; + base::LapTimer timer_; }; TEST_F(TaskGraphRunnerPerfTest, BuildTaskGraph) {
diff --git a/cc/tiles/gpu_image_decode_cache_perftest.cc b/cc/tiles/gpu_image_decode_cache_perftest.cc index 819d16bb..5d0f2e6 100644 --- a/cc/tiles/gpu_image_decode_cache_perftest.cc +++ b/cc/tiles/gpu_image_decode_cache_perftest.cc
@@ -4,7 +4,7 @@ #include <vector> -#include "cc/base/lap_timer.h" +#include "base/timer/lap_timer.h" #include "cc/paint/draw_image.h" #include "cc/paint/paint_image_builder.h" #include "cc/raster/tile_task.h" @@ -87,7 +87,7 @@ } } - LapTimer timer_; + base::LapTimer timer_; scoped_refptr<TestInProcessContextProvider> context_provider_; std::unique_ptr<GpuImageDecodeCache> cache_; };
diff --git a/cc/tiles/software_image_decode_cache_perftest.cc b/cc/tiles/software_image_decode_cache_perftest.cc index 5f69317..f873c977 100644 --- a/cc/tiles/software_image_decode_cache_perftest.cc +++ b/cc/tiles/software_image_decode_cache_perftest.cc
@@ -4,7 +4,7 @@ #include <vector> -#include "cc/base/lap_timer.h" +#include "base/timer/lap_timer.h" #include "cc/paint/draw_image.h" #include "cc/paint/paint_image_builder.h" #include "cc/raster/tile_task.h" @@ -82,7 +82,7 @@ } private: - LapTimer timer_; + base::LapTimer timer_; }; TEST_F(SoftwareImageDecodeCachePerfTest, FromDrawImage) {
diff --git a/cc/tiles/tile_manager_perftest.cc b/cc/tiles/tile_manager_perftest.cc index 8a875845..e6334235e 100644 --- a/cc/tiles/tile_manager_perftest.cc +++ b/cc/tiles/tile_manager_perftest.cc
@@ -10,7 +10,7 @@ #include "base/stl_util.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" -#include "cc/base/lap_timer.h" +#include "base/timer/lap_timer.h" #include "cc/raster/raster_buffer.h" #include "cc/test/fake_impl_task_runner_provider.h" #include "cc/test/fake_layer_tree_frame_sink.h" @@ -292,7 +292,7 @@ TileManager* tile_manager() { return host_impl()->tile_manager(); } protected: - LapTimer timer_; + base::LapTimer timer_; }; // Failing. https://crbug.com/792995
diff --git a/cc/trees/layer_tree_host_common_perftest.cc b/cc/trees/layer_tree_host_common_perftest.cc index 561cdd1..2c1c4ab 100644 --- a/cc/trees/layer_tree_host_common_perftest.cc +++ b/cc/trees/layer_tree_host_common_perftest.cc
@@ -13,7 +13,7 @@ #include "base/strings/string_piece.h" #include "base/threading/thread.h" #include "base/time/time.h" -#include "cc/base/lap_timer.h" +#include "base/timer/lap_timer.h" #include "cc/layers/layer.h" #include "cc/test/fake_content_layer_client.h" #include "cc/test/fake_layer_tree_host_client.h" @@ -62,17 +62,13 @@ void AfterTest() override { CHECK(!test_name_.empty()) << "Must SetTestName() before TearDown()."; - perf_test::PrintResult("calc_draw_props_time", - "", - test_name_, - 1000 * timer_.MsPerLap(), - "us", - true); + perf_test::PrintResult("calc_draw_props_time", "", test_name_, + timer_.TimePerLap().InMicrosecondsF(), "us", true); } protected: FakeContentLayerClient content_layer_client_; - LapTimer timer_; + base::LapTimer timer_; std::string test_name_; std::string json_; };
diff --git a/cc/trees/layer_tree_host_perftest.cc b/cc/trees/layer_tree_host_perftest.cc index 0e2f8b73..35953305 100644 --- a/cc/trees/layer_tree_host_perftest.cc +++ b/cc/trees/layer_tree_host_perftest.cc
@@ -14,7 +14,7 @@ #include "base/path_service.h" #include "base/strings/string_piece.h" #include "base/time/time.h" -#include "cc/base/lap_timer.h" +#include "base/timer/lap_timer.h" #include "cc/layers/nine_patch_layer.h" #include "cc/layers/solid_color_layer.h" #include "cc/layers/texture_layer.h" @@ -108,16 +108,18 @@ void AfterTest() override { CHECK(!test_name_.empty()) << "Must SetTestName() before AfterTest()."; perf_test::PrintResult("layer_tree_host_frame_time", "", test_name_, - 1000 * draw_timer_.MsPerLap(), "us", true); + draw_timer_.TimePerLap().InMicrosecondsF(), "us", + true); if (measure_commit_cost_) { perf_test::PrintResult("layer_tree_host_commit_time", "", test_name_, - 1000 * commit_timer_.MsPerLap(), "us", true); + commit_timer_.TimePerLap().InMicrosecondsF(), "us", + true); } } protected: - LapTimer draw_timer_; - LapTimer commit_timer_; + base::LapTimer draw_timer_; + base::LapTimer commit_timer_; std::string test_name_; FakeContentLayerClient fake_content_layer_client_;
diff --git a/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java index ce3f589..d96094be 100644 --- a/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java +++ b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java
@@ -773,7 +773,9 @@ removeVrRootView(); } - mActivity.getFullscreenManager().exitPersistentFullscreenMode(); + if (!mActivity.isActivityFinishingOrDestroyed()) { + mActivity.getFullscreenManager().exitPersistentFullscreenMode(); + } reparentAllTabs(mActivity.getWindowAndroid()); if (mNativeVrShell != 0) { nativeDestroy(mNativeVrShell);
diff --git a/chrome/android/java/res_autofill_assistant/drawable/autofill_assistant_details_bg.xml b/chrome/android/java/res_autofill_assistant/drawable/autofill_assistant_details_bg.xml index 9ce233e..67ed25d0 100644 --- a/chrome/android/java/res_autofill_assistant/drawable/autofill_assistant_details_bg.xml +++ b/chrome/android/java/res_autofill_assistant/drawable/autofill_assistant_details_bg.xml
@@ -7,7 +7,5 @@ android:shape="rectangle"> <corners android:radius="8dp" /> - <stroke - android:width="1dp" - android:color="@color/hairline_stroke_color" /> + <solid android:color="@color/modern_secondary_color"/> </shape>
diff --git a/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_details.xml b/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_details.xml index c5cddbd..d9ceff0 100644 --- a/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_details.xml +++ b/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_details.xml
@@ -42,7 +42,7 @@ android:id="@+id/details_line1" android:layout_width="match_parent" android:layout_height="wrap_content" - android:textAppearance="@style/TextAppearance.AssistantBlackCaption" + android:textAppearance="@style/TextAppearance.AssistantGreyCaption" android:singleLine="true" android:requiresFadingEdge="horizontal" android:fadingEdgeLength="20dp" @@ -54,7 +54,7 @@ android:id="@+id/details_line2" android:layout_width="match_parent" android:layout_height="wrap_content" - android:textAppearance="@style/TextAppearance.AssistantBlackCaption" + android:textAppearance="@style/TextAppearance.AssistantGreyCaption" android:singleLine="true" android:requiresFadingEdge="horizontal" android:fadingEdgeLength="20dp"
diff --git a/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_onboarding.xml b/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_onboarding.xml index 955fc64..86d9e46 100644 --- a/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_onboarding.xml +++ b/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_onboarding.xml
@@ -21,8 +21,6 @@ android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation="vertical" - android:paddingTop="20dp" - android:paddingBottom="20dp" android:paddingStart="24dp" android:paddingEnd="24dp"> @@ -33,7 +31,6 @@ android:layout_height="141dp" android:scaleType="centerCrop" android:src="@drawable/onboarding_background" - android:paddingTop="10dp" android:paddingBottom="15dp"/> <!-- Title (e.g., 'Fast Checkout')--> @@ -129,5 +126,4 @@ android:text="@string/init_ok" style="FilledButton" /> </LinearLayout> - <Space android:layout_width="0dp" android:layout_height="24dp"/> </LinearLayout> \ No newline at end of file
diff --git a/chrome/android/java/res_autofill_assistant/values-v17/colors.xml b/chrome/android/java/res_autofill_assistant/values-v17/colors.xml index ee06f025..3f38ff3 100644 --- a/chrome/android/java/res_autofill_assistant/values-v17/colors.xml +++ b/chrome/android/java/res_autofill_assistant/values-v17/colors.xml
@@ -9,6 +9,7 @@ Please see src/ui/android/java/res/values/colors.xml for the shared common colors. --> + <color name="autofill_assistant_caption_grey">@color/modern_grey_800</color> <color name="autofill_assistant_light_grey">@color/modern_grey_300</color> <color name="autofill_assistant_light_blue">#E9F0FD</color> </resources>
diff --git a/chrome/android/java/res_autofill_assistant/values-v17/styles.xml b/chrome/android/java/res_autofill_assistant/values-v17/styles.xml index 7eadf5ac..f9f39f4 100644 --- a/chrome/android/java/res_autofill_assistant/values-v17/styles.xml +++ b/chrome/android/java/res_autofill_assistant/values-v17/styles.xml
@@ -16,6 +16,10 @@ <style name="TextAppearance.AssistantBlackCaption" parent="TextAppearance.BlackCaption"> <item name="android:fontFamily">@font/accent_font</item> </style> + <style name="TextAppearance.AssistantGreyCaption" parent="TextAppearance.BlackCaption"> + <item name="android:textColor">@color/autofill_assistant_caption_grey</item> + <item name="android:fontFamily">@font/accent_font</item> + </style> <style name="TextAppearance.AssistantBlackBody" parent="TextAppearance.BlackBody"> <item name="android:fontFamily">@font/accent_font</item> </style>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index 5e9216a..5f1f5a0a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -1288,6 +1288,9 @@ public void processUrlViewIntent(String url, String referer, String headers, @TabOpenType int tabOpenType, String externalAppId, int tabIdToBringToFront, boolean hasUserGesture, Intent intent) { + if (isActivityFinishingOrDestroyed()) { + return; + } if (isFromChrome(intent, externalAppId)) { RecordUserAction.record("MobileTabbedModeViewIntentFromChrome"); } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java index 2e286c1..b60f3e2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java
@@ -32,6 +32,7 @@ private static final int BOTTOM_BAR_WITHOUT_INDICATOR_PADDING_TOP_DP = 16; private final ViewGroup mBottomBarView; + private final ViewGroup mBottomBarContainerView; private final View mSwipeIndicatorView; private final BottomSheetBehavior mBottomBarBehavior; @@ -47,6 +48,8 @@ AssistantBottomBarCoordinator(Context context, View assistantView, AssistantModel model) { mBottomBarView = assistantView.findViewById(R.id.autofill_assistant_bottombar); + mBottomBarContainerView = + mBottomBarView.findViewById(R.id.autofill_assistant_bottombar_container); mSwipeIndicatorView = mBottomBarView.findViewById(R.id.swipe_indicator); mBottomBarBehavior = BottomSheetBehavior.from(mBottomBarView); @@ -66,12 +69,10 @@ mActionsCoordinator = new AssistantCarouselCoordinator(context, model.getActionsModel()); // Add child views to bottom bar container. - ViewGroup bottomBarContainer = - mBottomBarView.findViewById(R.id.autofill_assistant_bottombar_container); - bottomBarContainer.addView(mDetailsCoordinator.getView()); - bottomBarContainer.addView(mPaymentRequestCoordinator.getView()); - bottomBarContainer.addView(mSuggestionsCoordinator.getView()); - bottomBarContainer.addView(mActionsCoordinator.getView()); + mBottomBarContainerView.addView(mDetailsCoordinator.getView()); + mBottomBarContainerView.addView(mPaymentRequestCoordinator.getView()); + mBottomBarContainerView.addView(mSuggestionsCoordinator.getView()); + mBottomBarContainerView.addView(mActionsCoordinator.getView()); // We set the horizontal margins of the details and payment request. We don't set a padding // to the container as we want the carousels children to be scrolled at the limit of the @@ -89,6 +90,13 @@ } /** + * Returns the view container inside the bottom bar view. + */ + public ViewGroup getContainerView() { + return mBottomBarContainerView; + } + + /** * Make sure the bottom bar is expanded and text is visible. */ public void expand() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java index 0917d910d..ae7b40e4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java
@@ -107,7 +107,7 @@ // Disable swiping for the onboarding because it interferes with letting the user scroll // the onboarding contents. mBottomBarCoordinator.allowSwipingBottomSheet(false); - AssistantOnboardingCoordinator.show(mActivity, mBottomBarCoordinator.getView()) + AssistantOnboardingCoordinator.show(mActivity, mBottomBarCoordinator.getContainerView()) .then(accepted -> { mBottomBarCoordinator.allowSwipingBottomSheet(true); if (!accepted) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChip.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChip.java index 31af6008..e6b9ed9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChip.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChip.java
@@ -13,12 +13,14 @@ * A chip to display to the user. */ public class AssistantChip { - @IntDef({Type.CHIP_ASSISTIVE, Type.BUTTON_FILLED_BLUE, Type.BUTTON_HAIRLINE}) + @IntDef({Type.CHIP_ASSISTIVE, Type.BUTTON_FILLED_BLUE, Type.BUTTON_HAIRLINE, + Type.BUTTON_FILLED_DISABLED}) @Retention(RetentionPolicy.SOURCE) public @interface Type { int CHIP_ASSISTIVE = 0; int BUTTON_FILLED_BLUE = 1; int BUTTON_HAIRLINE = 2; + int BUTTON_FILLED_DISABLED = 3; } private final @Type int mType;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChipViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChipViewHolder.java index 6e8bda68..f83d313 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChipViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChipViewHolder.java
@@ -31,6 +31,7 @@ case AssistantChip.Type.CHIP_ASSISTIVE: resId = R.layout.autofill_assistant_chip_assistive; break; + case AssistantChip.Type.BUTTON_FILLED_DISABLED: case AssistantChip.Type.BUTTON_FILLED_BLUE: resId = R.layout.autofill_assistant_button_filled; break; @@ -40,8 +41,13 @@ default: assert false : "Unsupported view type " + viewType; } - return new AssistantChipViewHolder( - (TextView) layoutInflater.inflate(resId, /* root= */ null)); + + TextView view = (TextView) layoutInflater.inflate(resId, /* root= */ null); + if (viewType == AssistantChip.Type.BUTTON_FILLED_DISABLED) { + view.setEnabled(false); + } + + return new AssistantChipViewHolder(view); } public void bind(AssistantChip chip) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetails.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetails.java index f403e76b..3343a63 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetails.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetails.java
@@ -24,6 +24,7 @@ private final String mTitle; private final String mImageUrl; + private final boolean mShowImagePlaceholder; @Nullable private final Date mDate; private final String mDescriptionLine1; @@ -37,7 +38,7 @@ /** Whether the second description line should be highlighted. */ private boolean mHighlightLine2; /** Whether empty fields should have the animated placeholder background. */ - private final boolean mShowPlaceholdersForEmptyFields; + private final boolean mAnimatePlaceholders; /** * The correctly formatted price for the client locale, including the currency. * Example: '$20.50' or '20.50 €'. @@ -46,14 +47,14 @@ /** An optional price label, such as 'Estimated Total incl. VAT'. */ private final String mTotalPriceLabel; - public AssistantDetails(String title, String imageUrl, String totalPriceLabel, - String totalPrice, @Nullable Date date, String descriptionLine1, + public AssistantDetails(String title, String imageUrl, boolean showImagePlaceholder, + String totalPriceLabel, String totalPrice, @Nullable Date date, String descriptionLine1, String descriptionLine2, boolean userApprovalRequired, boolean highlightTitle, - boolean highlightLine1, boolean highlightLine2, - boolean showPlaceholdersForEmptyFields) { + boolean highlightLine1, boolean highlightLine2, boolean animatePlaceholders) { this.mTotalPriceLabel = totalPriceLabel; this.mTitle = title; this.mImageUrl = imageUrl; + this.mShowImagePlaceholder = showImagePlaceholder; this.mTotalPrice = totalPrice; this.mDate = date; this.mDescriptionLine1 = descriptionLine1; @@ -63,7 +64,7 @@ this.mHighlightTitle = highlightTitle; this.mHighlightLine1 = highlightLine1; this.mHighlightLine2 = highlightLine2; - this.mShowPlaceholdersForEmptyFields = showPlaceholdersForEmptyFields; + this.mAnimatePlaceholders = animatePlaceholders; } String getTitle() { @@ -74,6 +75,10 @@ return mImageUrl; } + boolean getShowImagePlaceholder() { + return mShowImagePlaceholder; + } + @Nullable Date getDate() { return mDate; @@ -111,19 +116,20 @@ return mHighlightLine2; } - boolean getShowPlaceholdersForEmptyFields() { - return mShowPlaceholdersForEmptyFields; + boolean getAnimatePlaceholders() { + return mAnimatePlaceholders; } /** * Create details with the given values. */ @CalledByNative - private static AssistantDetails create(String title, String imageUrl, String totalPriceLabel, - String totalPrice, String datetime, long year, int month, int day, int hour, int minute, - int second, String descriptionLine1, String descriptionLine2, - boolean userApprovalRequired, boolean highlightTitle, boolean highlightLine1, - boolean highlightLine2) { + private static AssistantDetails create(String title, String imageUrl, + boolean showImagePlaceholder, String totalPriceLabel, String totalPrice, + String datetime, long year, int month, int day, int hour, int minute, int second, + String descriptionLine1, String descriptionLine2, boolean userApprovalRequired, + boolean highlightTitle, boolean highlightLine1, boolean highlightLine2, + boolean animatePlaceholders) { Date date = null; if (year > 0 && month > 0 && day > 0 && hour >= 0 && minute >= 0 && second >= 0) { Calendar calendar = Calendar.getInstance(); @@ -142,8 +148,8 @@ } } - return new AssistantDetails(title, imageUrl, totalPriceLabel, totalPrice, date, - descriptionLine1, descriptionLine2, userApprovalRequired, highlightTitle, - highlightLine1, highlightLine2, /* showPlaceholdersForEmptyFields= */ false); + return new AssistantDetails(title, imageUrl, showImagePlaceholder, totalPriceLabel, + totalPrice, date, descriptionLine1, descriptionLine2, userApprovalRequired, + highlightTitle, highlightLine1, highlightLine2, animatePlaceholders); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsViewBinder.java index dc9702c..bb3de57 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsViewBinder.java
@@ -35,10 +35,8 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; -import java.util.HashSet; import java.util.List; import java.util.Locale; -import java.util.Set; /** * This class is responsible for pushing updates to the Autofill Assistant details view. These @@ -86,7 +84,6 @@ private final int mPulseAnimationStartColor; private final int mPulseAnimationEndColor; - private final Set<View> mViewsToAnimate = new HashSet<>(); private ValueAnimator mPulseAnimation; AssistantDetailsViewBinder(Context context) { @@ -95,8 +92,8 @@ R.dimen.autofill_assistant_details_image_size); mImageHeight = context.getResources().getDimensionPixelSize( R.dimen.autofill_assistant_details_image_size); - mPulseAnimationStartColor = context.getResources().getColor(R.color.modern_grey_100); - mPulseAnimationEndColor = context.getResources().getColor(R.color.modern_grey_50); + mPulseAnimationStartColor = context.getResources().getColor(R.color.modern_grey_300); + mPulseAnimationEndColor = context.getResources().getColor(R.color.modern_grey_200); } @Override @@ -141,15 +138,15 @@ viewHolder.mPriceView.setVisibility( details.getTotalPrice().isEmpty() ? View.GONE : View.VISIBLE); - if (viewHolder.mImageView.getDrawable() == null) { - // Set default image if no image was set before. - viewHolder.mImageView.setImageDrawable(viewHolder.mDefaultImage); - } - - setTextStyles(details, viewHolder); - - // Download image and then set it in the model. - if (!details.getImageUrl().isEmpty()) { + viewHolder.mImageView.setVisibility(View.VISIBLE); + if (details.getImageUrl().isEmpty()) { + if (details.getShowImagePlaceholder()) { + viewHolder.mImageView.setImageDrawable(viewHolder.mDefaultImage); + } else { + viewHolder.mImageView.setVisibility(View.GONE); + } + } else { + // Download image and then set it in the view. CachedImageFetcher.getInstance().fetchImage(details.getImageUrl(), CachedImageFetcher.ASSISTANT_DETAILS_UMA_CLIENT_NAME, image -> { if (image != null) { @@ -157,6 +154,8 @@ } }); } + + setTextStyles(details, viewHolder); } private String makeDescriptionLine1Text(AssistantDetails details) { @@ -208,20 +207,20 @@ setSubtextStyle(viewHolder.mDescriptionLine2View, details.getUserApprovalRequired(), details.getHighlightLine2(), viewHolder); - animateIfEmpty( - viewHolder.mTitleView, details.getShowPlaceholdersForEmptyFields(), viewHolder); - animateIfEmpty(viewHolder.mDescriptionLine1View, - details.getShowPlaceholdersForEmptyFields(), viewHolder); - animateIfEmpty(viewHolder.mDescriptionLine2View, - details.getShowPlaceholdersForEmptyFields(), viewHolder); + if (shouldStartOrContinuePlaceholderAnimation(details, viewHolder)) { + startOrContinuePlaceholderAnimations(viewHolder); + } else { + stopPlaceholderAnimations(); + } } - private void animateIfEmpty(TextView view, boolean animate, ViewHolder viewHolder) { - if (animate && view.length() == 0) { - addViewToAnimation(view, viewHolder); - } else { - removeViewFromAnimation(view); - } + private boolean shouldStartOrContinuePlaceholderAnimation( + AssistantDetails details, ViewHolder viewHolder) { + boolean isAtLeastOneFieldEmpty = viewHolder.mTitleView.length() == 0 + || viewHolder.mDescriptionLine1View.length() == 0 + || viewHolder.mDescriptionLine2View.length() == 0 + || viewHolder.mImageView.getDrawable() == viewHolder.mDefaultImage; + return details.getAnimatePlaceholders() && isAtLeastOneFieldEmpty; } private void setTitleStyle(boolean approvalRequired, boolean highlight, ViewHolder viewHolder) { @@ -235,7 +234,9 @@ // Normal style: bold black text. ApiCompatibilityUtils.setTextAppearance( titleView, R.style.TextAppearance_BlackCaptionDefault); - titleView.setTypeface(titleView.getTypeface(), Typeface.BOLD); + if (highlight) { + titleView.setTypeface(titleView.getTypeface(), Typeface.BOLD); + } } } @@ -244,7 +245,7 @@ // Emphasized style. if (approvalRequired && highlight) { view.setTypeface(view.getTypeface(), Typeface.BOLD_ITALIC); - } else if (approvalRequired && !highlight) { + } else if (approvalRequired) { // De-emphasized style. view.setTextColor(ApiCompatibilityUtils.getColor( mContext.getResources(), R.color.modern_grey_300)); @@ -263,39 +264,45 @@ return roundedBitmap; } - private void addViewToAnimation(View view, ViewHolder viewHolder) { - mViewsToAnimate.add(view); - if (mPulseAnimation == null) { - mPulseAnimation = - ValueAnimator.ofInt(mPulseAnimationStartColor, mPulseAnimationEndColor); - mPulseAnimation.setDuration(PULSING_DURATION_MS); - mPulseAnimation.setEvaluator(new ArgbEvaluator()); - mPulseAnimation.setRepeatCount(ValueAnimator.INFINITE); - mPulseAnimation.setRepeatMode(ValueAnimator.REVERSE); - mPulseAnimation.setInterpolator(CompositorAnimator.ACCELERATE_INTERPOLATOR); - mPulseAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationCancel(Animator animation) { - viewHolder.mTitleView.setBackgroundColor(Color.WHITE); - viewHolder.mDescriptionLine1View.setBackgroundColor(Color.WHITE); - viewHolder.mDescriptionLine2View.setBackgroundColor(Color.WHITE); - viewHolder.mDefaultImage.setColor(mPulseAnimationStartColor); - } - }); - mPulseAnimation.addUpdateListener(animation -> { - int animatedValue = (int) animation.getAnimatedValue(); - for (View viewToAnimate : mViewsToAnimate) { - viewToAnimate.setBackgroundColor(animatedValue); - } - viewHolder.mDefaultImage.setColor(animatedValue); - }); - mPulseAnimation.start(); + private void startOrContinuePlaceholderAnimations(ViewHolder viewHolder) { + if (mPulseAnimation != null) { + return; } + mPulseAnimation = ValueAnimator.ofInt(mPulseAnimationStartColor, mPulseAnimationEndColor); + mPulseAnimation.setDuration(PULSING_DURATION_MS); + mPulseAnimation.setEvaluator(new ArgbEvaluator()); + mPulseAnimation.setRepeatCount(ValueAnimator.INFINITE); + mPulseAnimation.setRepeatMode(ValueAnimator.REVERSE); + mPulseAnimation.setInterpolator(CompositorAnimator.ACCELERATE_INTERPOLATOR); + mPulseAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationCancel(Animator animation) { + viewHolder.mTitleView.setBackgroundColor(Color.TRANSPARENT); + viewHolder.mDescriptionLine1View.setBackgroundColor(Color.TRANSPARENT); + viewHolder.mDescriptionLine2View.setBackgroundColor(Color.TRANSPARENT); + viewHolder.mDefaultImage.setColor(Color.TRANSPARENT); + } + }); + mPulseAnimation.addUpdateListener(animation -> { + int animatedValue = (int) animation.getAnimatedValue(); + viewHolder.mTitleView.setBackgroundColor( + viewHolder.mTitleView.length() == 0 ? animatedValue : Color.TRANSPARENT); + viewHolder.mDescriptionLine1View.setBackgroundColor( + viewHolder.mDescriptionLine1View.length() == 0 ? animatedValue + : Color.TRANSPARENT); + viewHolder.mDescriptionLine2View.setBackgroundColor( + viewHolder.mDescriptionLine2View.length() == 0 ? animatedValue + : Color.TRANSPARENT); + viewHolder.mDefaultImage.setColor( + viewHolder.mImageView.getDrawable() == viewHolder.mDefaultImage + ? animatedValue + : Color.TRANSPARENT); + }); + mPulseAnimation.start(); } - private void removeViewFromAnimation(View view) { - mViewsToAnimate.remove(view); - if (mViewsToAnimate.isEmpty() && mPulseAnimation != null) { + private void stopPlaceholderAnimations() { + if (mPulseAnimation != null) { mPulseAnimation.cancel(); mPulseAnimation = null; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java index 8c74fbe..4b2ac81b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java
@@ -9,6 +9,7 @@ import android.content.pm.PackageManager; import android.net.Uri; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.customtabs.CustomTabsService; import android.support.customtabs.CustomTabsService.Relation; import android.text.TextUtils; @@ -67,7 +68,7 @@ private final String mSignatureFingerprint; private final @Relation int mRelation; private long mNativeOriginVerifier; - private OriginVerificationListener mListener; + @Nullable private OriginVerificationListener mListener; private Origin mOrigin; /** @@ -274,6 +275,13 @@ } } + /** + * Removes the verification listener, but finishes the ongoing verification process, if any. + */ + public void removeListener() { + mListener = null; + } + private static boolean shouldOverrideVerification(String packageName, Origin origin, int relation) { if (sVerificationOverrides.get() == null) return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java index ef411bb..7f9f52a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java
@@ -19,6 +19,7 @@ import org.chromium.chrome.browser.customtabs.TabObserverRegistrar; import org.chromium.chrome.browser.dependency_injection.ActivityScope; import org.chromium.chrome.browser.init.ActivityLifecycleDispatcher; +import org.chromium.chrome.browser.lifecycle.Destroyable; import org.chromium.chrome.browser.lifecycle.NativeInitObserver; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; @@ -40,7 +41,7 @@ * {@link TrustedWebActivityModel} accordingly. */ @ActivityScope -public class TrustedWebActivityVerifier implements NativeInitObserver { +public class TrustedWebActivityVerifier implements NativeInitObserver, Destroyable { /** The Digital Asset Link relationship used for Trusted Web Activities. */ private final static int RELATIONSHIP = CustomTabsService.RELATION_HANDLE_ALL_URLS; @@ -208,6 +209,12 @@ } } + @Override + public void destroy() { + // Verification may finish after activity is destroyed. + mOriginVerifier.removeListener(); + } + /** * Register that we have Chrome data relevant to the Client app. *
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/view/TrustedWebActivityToolbarView.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/view/TrustedWebActivityToolbarView.java index 02752afc..4321d696 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/view/TrustedWebActivityToolbarView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/view/TrustedWebActivityToolbarView.java
@@ -6,6 +6,7 @@ import static org.chromium.chrome.browser.browserservices.trustedwebactivityui.TrustedWebActivityModel.TOOLBAR_HIDDEN; +import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.browserservices.trustedwebactivityui.TrustedWebActivityModel; import org.chromium.chrome.browser.customtabs.CustomTabBrowserControlsVisibilityDelegate; import org.chromium.chrome.browser.dependency_injection.ActivityScope; @@ -27,21 +28,27 @@ private final Lazy<ChromeFullscreenManager> mFullscreenManager; private final CustomTabBrowserControlsVisibilityDelegate mControlsVisibilityDelegate; private final TrustedWebActivityModel mModel; + private final ChromeActivity mActivity; private int mControlsHidingToken = FullscreenManager.INVALID_TOKEN; @Inject public TrustedWebActivityToolbarView(Lazy<ChromeFullscreenManager> fullscreenManager, CustomTabBrowserControlsVisibilityDelegate controlsVisibilityDelegate, - TrustedWebActivityModel model) { + TrustedWebActivityModel model, ChromeActivity activity) { mFullscreenManager = fullscreenManager; mControlsVisibilityDelegate = controlsVisibilityDelegate; mModel = model; + mActivity = activity; mModel.addObserver(this); } @Override public void onPropertyChanged(PropertyObservable<PropertyKey> observable, PropertyKey key) { + if (mActivity.isActivityFinishingOrDestroyed()) { + assert false : "Tried to change toolbar visibility when activity is destroyed"; + return; + } if (key != TOOLBAR_HIDDEN) return; boolean hide = mModel.get(TOOLBAR_HIDDEN);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java index 97d0336..8557349 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -1186,7 +1186,7 @@ * Wraps calling extraCallback in a try/catch so exceptions thrown by the host app don't crash * Chrome. See https://crbug.com/517023. */ - private boolean safeExtraCallback( + protected boolean safeExtraCallback( CustomTabsSessionToken session, String callbackName, @Nullable Bundle args) { CustomTabsCallback callback = mClientManager.getCallbackForSession(session); if (callback == null) return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementScreenHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementScreenHelper.java index efcfd6ee..9e5359b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementScreenHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementScreenHelper.java
@@ -4,35 +4,36 @@ package org.chromium.chrome.browser.signin; +import android.app.Activity; import android.content.Intent; -import android.provider.Settings; +import android.support.annotation.Nullable; import org.chromium.base.ContextUtils; import org.chromium.base.ThreadUtils; import org.chromium.base.annotations.CalledByNative; import org.chromium.chrome.browser.ChromeFeatureList; -import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.ProfileAccountManagementMetrics; +import org.chromium.chrome.browser.util.IntentUtils; +import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.GAIAServiceType; +import org.chromium.ui.base.WindowAndroid; /** * Stub entry points and implementation interface for the account management fragment delegate. */ public class AccountManagementScreenHelper { - private static final String EXTRA_ACCOUNT_TYPES = "account_types"; - private static final String EXTRA_VALUE_GOOGLE_ACCOUNTS = "com.google"; - @CalledByNative private static void openAccountManagementScreen( - Profile profile, @GAIAServiceType int gaiaServiceType) { + WindowAndroid windowAndroid, @GAIAServiceType int gaiaServiceType) { ThreadUtils.assertOnUiThread(); - if (gaiaServiceType == GAIAServiceType.GAIA_SERVICE_TYPE_SIGNUP) { - openAndroidAccountCreationScreen(); - return; - } - if (ChromeFeatureList.isEnabled(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY)) { + if (gaiaServiceType == GAIAServiceType.GAIA_SERVICE_TYPE_SIGNUP + || gaiaServiceType == GAIAServiceType.GAIA_SERVICE_TYPE_ADDSESSION) { + startAddAccountActivity(windowAndroid, gaiaServiceType); + return; + } + SigninUtils.openSettingsForAllAccounts(ContextUtils.getApplicationContext()); return; } @@ -41,20 +42,22 @@ } /** - * Opens the Android account manager for adding or creating a Google account. + * Tries starting an Activity to add a Google account to the device. If this activity cannot + * be started, opens "Accounts" page in the Android Settings app. */ - private static void openAndroidAccountCreationScreen() { - logEvent(ProfileAccountManagementMetrics.DIRECT_ADD_ACCOUNT, - GAIAServiceType.GAIA_SERVICE_TYPE_SIGNUP); + private static void startAddAccountActivity( + WindowAndroid windowAndroid, @GAIAServiceType int gaiaServiceTypeSignup) { + logEvent(ProfileAccountManagementMetrics.DIRECT_ADD_ACCOUNT, gaiaServiceTypeSignup); - Intent createAccountIntent = new Intent(Settings.ACTION_ADD_ACCOUNT); - createAccountIntent.putExtra( - EXTRA_ACCOUNT_TYPES, new String[]{EXTRA_VALUE_GOOGLE_ACCOUNTS}); - createAccountIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT - | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_CLEAR_TOP); - - ContextUtils.getApplicationContext().startActivity(createAccountIntent); + AccountManagerFacade.get().createAddAccountIntent((@Nullable Intent intent) -> { + Activity activity = windowAndroid.getActivity().get(); + if (intent == null || activity == null + || !IntentUtils.safeStartActivity(activity, intent)) { + // Failed to create or show an intent, open settings for all accounts so + // the user has a chance to create an account manually. + SigninUtils.openSettingsForAllAccounts(ContextUtils.getApplicationContext()); + } + }); } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java index 0975817..11df2137 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java
@@ -159,13 +159,14 @@ -> assistantCoordinator.getModel().getDetailsModel().set( AssistantDetailsModel.DETAILS, new AssistantDetails(movieTitle, /* imageUrl = */ "", + /* showImage = */ false, /* totalPriceLabel = */ "", /* totalPrice = */ "", Calendar.getInstance().getTime(), descriptionLine1, descriptionLine2, /* userApprovalRequired= */ false, /* highlightTitle= */ false, /* highlightLine1= */ false, /* highlightLine1 = */ false, - /* showPlaceholdersForEmptyFields= */ false))); + /* animatePlaceholders= */ false))); TextView detailsTitle = bottomSheet.findViewById(R.id.details_title); TextView detailsLine1 = bottomSheet.findViewById(R.id.details_line1); TextView detailsLine2 = bottomSheet.findViewById(R.id.details_line2);
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 715cce3..34e3132 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1826,6 +1826,7 @@ "//chrome/browser/push_messaging:budget_proto", "//chrome/browser/resource_coordinator:mojo_bindings", "//chrome/browser/safe_browsing", + "//chrome/browser/security_events", "//chrome/browser/ssl:proto", "//chrome/browser/ui", "//chrome/browser/ui/webui/bluetooth_internals",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index eb4a547..e6eea37 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3661,11 +3661,6 @@ flag_descriptions::kLookalikeUrlNavigationSuggestionsDescription, kOsAll, FEATURE_VALUE_TYPE(features::kLookalikeUrlNavigationSuggestionsUI)}, - {"sync-standalone-transport", - flag_descriptions::kSyncStandaloneTransportName, - flag_descriptions::kSyncStandaloneTransportDescription, kOsAll, - FEATURE_VALUE_TYPE(switches::kSyncStandaloneTransport)}, - {"sync-USS-autofill-profile", flag_descriptions::kSyncUSSAutofillProfileName, flag_descriptions::kSyncUSSAutofillProfileDescription, kOsAll, @@ -3676,6 +3671,11 @@ flag_descriptions::kSyncUSSAutofillWalletDataDescription, kOsAll, FEATURE_VALUE_TYPE(switches::kSyncUSSAutofillWalletData)}, + {"sync-USS-autofill-wallet-metadata", + flag_descriptions::kSyncUSSAutofillWalletMetadataName, + flag_descriptions::kSyncUSSAutofillWalletMetadataDescription, kOsAll, + FEATURE_VALUE_TYPE(switches::kSyncUSSAutofillWalletMetadata)}, + {"enable-resampling-input-events", flag_descriptions::kEnableResamplingInputEventsName, flag_descriptions::kEnableResamplingInputEventsDescription, kOsAll,
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc index e7938f4..65c52b1 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -562,9 +562,11 @@ const DetailsProto& proto = details->proto().details(); const DetailsChangesProto& changes = details->proto().change_flags(); + auto jdetails = Java_AssistantDetails_create( env, base::android::ConvertUTF8ToJavaString(env, proto.title()), base::android::ConvertUTF8ToJavaString(env, proto.image_url()), + proto.show_image_placeholder(), base::android::ConvertUTF8ToJavaString(env, proto.total_price_label()), base::android::ConvertUTF8ToJavaString(env, proto.total_price()), base::android::ConvertUTF8ToJavaString(env, details->GetDatetime()), @@ -574,7 +576,8 @@ base::android::ConvertUTF8ToJavaString(env, proto.description_line_1()), base::android::ConvertUTF8ToJavaString(env, proto.description_line_2()), changes.user_approval_required(), changes.highlight_title(), - changes.highlight_line1(), changes.highlight_line2()); + changes.highlight_line1(), changes.highlight_line2(), + proto.animate_placeholders()); Java_AssistantDetailsModel_setDetails(env, jmodel, jdetails); }
diff --git a/chrome/browser/android/cached_image_fetcher/cached_image_fetcher_bridge.cc b/chrome/browser/android/cached_image_fetcher/cached_image_fetcher_bridge.cc index 678e4947..0737c2b4 100644 --- a/chrome/browser/android/cached_image_fetcher/cached_image_fetcher_bridge.cc +++ b/chrome/browser/android/cached_image_fetcher/cached_image_fetcher_bridge.cc
@@ -65,12 +65,14 @@ JNIEnv* j_env, const JavaParamRef<jobject>& j_profile) { Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile); + SimpleFactoryKey* simple_factory_key = Profile::GetSimpleFactoryKey(profile); base::FilePath file_path = - CachedImageFetcherServiceFactory::GetCachePath(profile).Append( - kPathPostfix); + CachedImageFetcherServiceFactory::GetCachePath(simple_factory_key) + .Append(kPathPostfix); CachedImageFetcherService* cif_service = - CachedImageFetcherServiceFactory::GetForBrowserContext(profile); + CachedImageFetcherServiceFactory::GetForKey(simple_factory_key, + profile->GetPrefs()); CachedImageFetcherBridge* native_cif_bridge = new CachedImageFetcherBridge( cif_service->GetCachedImageFetcher(), file_path); return reinterpret_cast<intptr_t>(native_cif_bridge);
diff --git a/chrome/browser/android/signin/account_management_screen_helper.cc b/chrome/browser/android/signin/account_management_screen_helper.cc index 205b847..834c699 100644 --- a/chrome/browser/android/signin/account_management_screen_helper.cc +++ b/chrome/browser/android/signin/account_management_screen_helper.cc
@@ -9,19 +9,17 @@ #include "chrome/browser/profiles/profile_android.h" #include "chrome/browser/profiles/profile_metrics.h" #include "jni/AccountManagementScreenHelper_jni.h" +#include "ui/android/window_android.h" using base::android::JavaParamRef; // static void AccountManagementScreenHelper::OpenAccountManagementScreen( - Profile* profile, + ui::WindowAndroid* window, signin::GAIAServiceType service_type) { - DCHECK(profile); - DCHECK(ProfileAndroid::FromProfile(profile)); - + DCHECK(window); Java_AccountManagementScreenHelper_openAccountManagementScreen( - base::android::AttachCurrentThread(), - ProfileAndroid::FromProfile(profile)->GetJavaObject(), + base::android::AttachCurrentThread(), window->GetJavaObject(), static_cast<int>(service_type)); }
diff --git a/chrome/browser/android/signin/account_management_screen_helper.h b/chrome/browser/android/signin/account_management_screen_helper.h index a5a9adf..909ae88 100644 --- a/chrome/browser/android/signin/account_management_screen_helper.h +++ b/chrome/browser/android/signin/account_management_screen_helper.h
@@ -8,13 +8,15 @@ #include "base/macros.h" #include "components/signin/core/browser/signin_header_helper.h" -class Profile; +namespace ui { +class WindowAndroid; +} // The glue for Java-side implementation of AccountManagementScreenHelper. class AccountManagementScreenHelper { public: // Opens the account management screen. - static void OpenAccountManagementScreen(Profile* profile, + static void OpenAccountManagementScreen(ui::WindowAndroid* profile, signin::GAIAServiceType service_type); private:
diff --git a/chrome/browser/cached_image_fetcher/cached_image_fetcher_service_factory.cc b/chrome/browser/cached_image_fetcher/cached_image_fetcher_service_factory.cc index fff90ec..eeda470 100644 --- a/chrome/browser/cached_image_fetcher/cached_image_fetcher_service_factory.cc +++ b/chrome/browser/cached_image_fetcher/cached_image_fetcher_service_factory.cc
@@ -13,16 +13,16 @@ #include "base/task/post_task.h" #include "base/time/default_clock.h" #include "build/build_config.h" -#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/search/suggestions/image_decoder_impl.h" #include "chrome/common/chrome_paths_internal.h" #include "components/image_fetcher/core/cache/image_cache.h" #include "components/image_fetcher/core/cache/image_data_store_disk.h" #include "components/image_fetcher/core/cache/image_metadata_store_leveldb.h" #include "components/image_fetcher/core/cached_image_fetcher_service.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/storage_partition.h" +#include "components/keyed_service/core/simple_dependency_manager.h" +#include "components/keyed_service/core/simple_factory_key.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" namespace image_fetcher { @@ -37,18 +37,18 @@ // static base::FilePath CachedImageFetcherServiceFactory::GetCachePath( - Profile* profile) { + SimpleFactoryKey* key) { base::FilePath cache_path; - chrome::GetUserCacheDirectory(profile->GetPath(), &cache_path); + chrome::GetUserCacheDirectory(key->path(), &cache_path); return cache_path.Append(kImageCacheSubdir); } // static -CachedImageFetcherService* -CachedImageFetcherServiceFactory::GetForBrowserContext( - content::BrowserContext* context) { +CachedImageFetcherService* CachedImageFetcherServiceFactory::GetForKey( + SimpleFactoryKey* key, + PrefService* prefs) { return static_cast<CachedImageFetcherService*>( - GetInstance()->GetServiceForBrowserContext(context, true)); + GetInstance()->GetServiceForKey(key, prefs, true)); } // static @@ -58,16 +58,16 @@ } CachedImageFetcherServiceFactory::CachedImageFetcherServiceFactory() - : BrowserContextKeyedServiceFactory( - "CachedImageFetcherService", - BrowserContextDependencyManager::GetInstance()) {} + : SimpleKeyedServiceFactory("CachedImageFetcherService", + SimpleDependencyManager::GetInstance()) {} CachedImageFetcherServiceFactory::~CachedImageFetcherServiceFactory() = default; -KeyedService* CachedImageFetcherServiceFactory::BuildServiceInstanceFor( - content::BrowserContext* context) const { - Profile* profile = Profile::FromBrowserContext(context); - base::FilePath cache_path = GetCachePath(profile); +std::unique_ptr<KeyedService> +CachedImageFetcherServiceFactory::BuildServiceInstanceFor( + SimpleFactoryKey* key, + PrefService* prefs) const { + base::FilePath cache_path = GetCachePath(key); scoped_refptr<base::SequencedTaskRunner> task_runner = base::CreateSequencedTaskRunnerWithTraits( @@ -80,24 +80,23 @@ std::make_unique<ImageDataStoreDisk>(cache_path, task_runner); scoped_refptr<ImageCache> image_cache = base::MakeRefCounted<ImageCache>( - std::move(data_store), std::move(metadata_store), profile->GetPrefs(), - clock, task_runner); + std::move(data_store), std::move(metadata_store), prefs, clock, + task_runner); scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory = - content::BrowserContext::GetDefaultStoragePartition(profile) - ->GetURLLoaderFactoryForBrowserProcess(); + SystemNetworkContextManager::GetInstance()->GetSharedURLLoaderFactory(); - return new CachedImageFetcherService( - std::make_unique<suggestions::ImageDecoderImpl>(), - std::move(url_loader_factory), std::move(image_cache), - context->IsOffTheRecord()); + auto cached_image_fetcher_service = + std::make_unique<CachedImageFetcherService>( + std::make_unique<suggestions::ImageDecoderImpl>(), + std::move(url_loader_factory), std::move(image_cache), + key->is_off_the_record()); + return cached_image_fetcher_service; } -content::BrowserContext* -CachedImageFetcherServiceFactory::GetBrowserContextToUse( - content::BrowserContext* context) const { - // Return different BrowserContexts for regular/incognito. - return context; +SimpleFactoryKey* CachedImageFetcherServiceFactory::GetKeyToUse( + SimpleFactoryKey* key) const { + return key; } } // namespace image_fetcher
diff --git a/chrome/browser/cached_image_fetcher/cached_image_fetcher_service_factory.h b/chrome/browser/cached_image_fetcher/cached_image_fetcher_service_factory.h index 0c68a082..07177143 100644 --- a/chrome/browser/cached_image_fetcher/cached_image_fetcher_service_factory.h +++ b/chrome/browser/cached_image_fetcher/cached_image_fetcher_service_factory.h
@@ -5,30 +5,28 @@ #ifndef CHROME_BROWSER_CACHED_IMAGE_FETCHER_CACHED_IMAGE_FETCHER_SERVICE_FACTORY_H_ #define CHROME_BROWSER_CACHED_IMAGE_FETCHER_CACHED_IMAGE_FETCHER_SERVICE_FACTORY_H_ +#include <memory> + #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/singleton.h" -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" +#include "components/keyed_service/core/simple_keyed_service_factory.h" -namespace content { -class BrowserContext; -} // namespace content - -class Profile; +class SimpleFactoryKey; +class PrefService; namespace image_fetcher { class CachedImageFetcherService; // Factory to create one CachedImageFetcherService per browser context. -class CachedImageFetcherServiceFactory - : public BrowserContextKeyedServiceFactory { +class CachedImageFetcherServiceFactory : public SimpleKeyedServiceFactory { public: // Return the cache path for the given profile. - static base::FilePath GetCachePath(Profile* profile); + static base::FilePath GetCachePath(SimpleFactoryKey* key); - static CachedImageFetcherService* GetForBrowserContext( - content::BrowserContext* context); + static CachedImageFetcherService* GetForKey(SimpleFactoryKey* key, + PrefService* prefs); static CachedImageFetcherServiceFactory* GetInstance(); private: @@ -37,11 +35,11 @@ CachedImageFetcherServiceFactory(); ~CachedImageFetcherServiceFactory() override; - // BrowserContextKeyedServiceFactory: - KeyedService* BuildServiceInstanceFor( - content::BrowserContext* context) const override; - content::BrowserContext* GetBrowserContextToUse( - content::BrowserContext* context) const override; + // SimpleKeyedServiceFactory: + std::unique_ptr<KeyedService> BuildServiceInstanceFor( + SimpleFactoryKey* key, + PrefService* prefs) const override; + SimpleFactoryKey* GetKeyToUse(SimpleFactoryKey* key) const override; DISALLOW_COPY_AND_ASSIGN(CachedImageFetcherServiceFactory); };
diff --git a/chrome/browser/chrome_browser_field_trials.cc b/chrome/browser/chrome_browser_field_trials.cc index 2ac704f..8bba8b3 100644 --- a/chrome/browser/chrome_browser_field_trials.cc +++ b/chrome/browser/chrome_browser_field_trials.cc
@@ -13,6 +13,7 @@ #include "base/strings/string_util.h" #include "base/time/time.h" #include "build/build_config.h" +#include "chrome/browser/metrics/chrome_metrics_service_accessor.h" #include "chrome/browser/metrics/chrome_metrics_service_client.h" #include "chrome/browser/metrics/chrome_metrics_services_manager_client.h" #include "chrome/browser/metrics/persistent_histograms.h" @@ -23,6 +24,8 @@ #include "components/version_info/version_info.h" #if defined(OS_ANDROID) +#include "base/android/library_loader/library_loader_hooks.h" +#include "base/android/reached_code_profiler.h" #include "chrome/browser/chrome_browser_field_trials_mobile.h" #else #include "chrome/browser/chrome_browser_field_trials_desktop.h" @@ -85,6 +88,33 @@ } } +void ChromeBrowserFieldTrials::RegisterSyntheticTrials() { +#if defined(OS_ANDROID) + static constexpr char kEnabledGroup[] = "Enabled"; + static constexpr char kDisabledGroup[] = "Disabled"; + + static constexpr char kOrderfileOptimizationTrial[] = + "AndroidOrderfileOptimization"; + if (base::android::IsUsingOrderfileOptimization()) { + ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial( + kOrderfileOptimizationTrial, kEnabledGroup); + } else { + ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial( + kOrderfileOptimizationTrial, kDisabledGroup); + } + + static constexpr char kReachedCodeProfilerTrial[] = + "ReachedCodeProfilerSynthetic"; + if (base::android::IsReachedCodeProfilerEnabled()) { + ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial( + kReachedCodeProfilerTrial, kEnabledGroup); + } else { + ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial( + kReachedCodeProfilerTrial, kDisabledGroup); + } +#endif // defined(OS_ANDROID) +} + void ChromeBrowserFieldTrials::InstantiateDynamicTrials() { // Persistent histograms must be enabled as soon as possible. InstantiatePersistentHistograms();
diff --git a/chrome/browser/chrome_browser_field_trials.h b/chrome/browser/chrome_browser_field_trials.h index 747a8a7..e80020b 100644 --- a/chrome/browser/chrome_browser_field_trials.h +++ b/chrome/browser/chrome_browser_field_trials.h
@@ -22,6 +22,7 @@ void SetupFeatureControllingFieldTrials( bool has_seed, base::FeatureList* feature_list) override; + void RegisterSyntheticTrials() override; private: // Instantiates dynamic trials by querying their state, to ensure they get
diff --git a/chrome/browser/chrome_browser_field_trials_mobile.cc b/chrome/browser/chrome_browser_field_trials_mobile.cc index e999f030..fba54a6 100644 --- a/chrome/browser/chrome_browser_field_trials_mobile.cc +++ b/chrome/browser/chrome_browser_field_trials_mobile.cc
@@ -5,48 +5,18 @@ #include "chrome/browser/chrome_browser_field_trials_mobile.h" #include "build/build_config.h" +#include "chrome/browser/browser_process.h" #if defined(OS_ANDROID) -#include "base/android/library_loader/library_loader_hooks.h" -#include "base/android/reached_code_profiler.h" -#include "base/base_switches.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/metrics/chrome_metrics_service_accessor.h" #include "chrome/browser/prerender/prerender_field_trial.h" #endif namespace chrome { void SetupMobileFieldTrials() { + DCHECK(!g_browser_process); #if defined(OS_ANDROID) prerender::ConfigureNoStatePrefetch(); - - // For tests on some platforms, g_browser_process is not initialized yet. - if (g_browser_process) { - static constexpr char kEnabledGroup[] = "Enabled"; - static constexpr char kDisabledGroup[] = "Disabled"; - - static constexpr char kOrderfileOptimizationTrial[] = - "AndroidOrderfileOptimization"; - if (base::android::IsUsingOrderfileOptimization()) { - ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial( - kOrderfileOptimizationTrial, kEnabledGroup); - } else { - ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial( - kOrderfileOptimizationTrial, kDisabledGroup); - } - - static constexpr char kReachedCodeProfilerTrial[] = - "ReachedCodeProfilerSynthetic"; - if (base::android::IsReachedCodeProfilerEnabled()) { - ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial( - kReachedCodeProfilerTrial, kEnabledGroup); - } else { - ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial( - kReachedCodeProfilerTrial, kDisabledGroup); - } - } - #endif }
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 657dff3..0b78469 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -661,6 +661,9 @@ variations::SyntheticTrialsActiveGroupIdProvider::GetInstance()); // Now that field trials have been created, initializes metrics recording. metrics->InitializeMetricsRecordingState(); + + chrome_feature_list_creator_->browser_field_trials() + ->RegisterSyntheticTrials(); } void ChromeBrowserMainParts::StartMetricsRecording() {
diff --git a/chrome/browser/chrome_browser_main.h b/chrome/browser/chrome_browser_main.h index ae86339..679f397 100644 --- a/chrome/browser/chrome_browser_main.h +++ b/chrome/browser/chrome_browser_main.h
@@ -10,7 +10,6 @@ #include "base/macros.h" #include "build/build_config.h" -#include "chrome/browser/chrome_browser_field_trials.h" #include "chrome/browser/chrome_process_singleton.h" #include "chrome/browser/first_run/first_run.h" #include "chrome/browser/process_singleton.h" @@ -138,8 +137,6 @@ const base::CommandLine& parsed_command_line_; int result_code_; - ChromeBrowserFieldTrials browser_field_trials_; - #if !defined(OS_ANDROID) // Create StartupTimeBomb object for watching jank during startup. std::unique_ptr<StartupTimeBomb> startup_watcher_;
diff --git a/chrome/browser/chromeos/account_manager/account_manager_migrator.cc b/chrome/browser/chromeos/account_manager/account_manager_migrator.cc index 3626926..0a7678a 100644 --- a/chrome/browser/chromeos/account_manager/account_manager_migrator.cc +++ b/chrome/browser/chromeos/account_manager/account_manager_migrator.cc
@@ -114,14 +114,6 @@ return; } - // |IdentityManager::LegacySeedAccountInfo| must be called before - // |AccountManager::UpsertToken|. |AccountManager| observers will need to - // translate |AccountManager::AccountKey| to other formats using - // |IdentityManager| and hence |IdentityManager| should be updated first. - AccountInfo account_info; - account_info.email = email; - account_info.gaia = gaia_id; - identity_manager_->LegacySeedAccountInfo(account_info); account_manager_->UpsertAccount( AccountManager::AccountKey{ gaia_id, account_manager::AccountType::ACCOUNT_TYPE_GAIA},
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index 8e8a98a..2edcaf5 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -578,6 +578,11 @@ TestCase("dirCreateWithoutChangingCurrent").EnableMyFilesVolume(), TestCase("dirCreateWithoutChangingCurrent"), TestCase("dirContextMenuRecent"), + TestCase("dirContextMenuMyFiles").EnableMyFilesVolume(), + TestCase("dirContextMenuCrostini"), + TestCase("dirContextMenuPlayFiles"), + TestCase("dirContextMenuUsbs"), + TestCase("dirContextMenuFsp"), TestCase("dirContextMenuShortcut"))); WRAPPED_INSTANTIATE_TEST_SUITE_P(
diff --git a/chrome/browser/chromeos/oauth2_token_service_delegate.cc b/chrome/browser/chromeos/oauth2_token_service_delegate.cc index 61512d7..d7b3e02 100644 --- a/chrome/browser/chromeos/oauth2_token_service_delegate.cc +++ b/chrome/browser/chromeos/oauth2_token_service_delegate.cc
@@ -314,7 +314,7 @@ account_manager_->UpdateEmail(account.key, email); } - std::string account_id = account_tracker_service_->PickAccountIdForAccount( + std::string account_id = account_tracker_service_->SeedAccountInfo( account.key.id /* gaia_id */, email); DCHECK(!account_id.empty());
diff --git a/chrome/browser/chromeos/policy/display_resolution_handler.cc b/chrome/browser/chromeos/policy/display_resolution_handler.cc index 4d83d00..feb7d5e 100644 --- a/chrome/browser/chromeos/policy/display_resolution_handler.cc +++ b/chrome/browser/chromeos/policy/display_resolution_handler.cc
@@ -183,11 +183,13 @@ // We should reset locally stored settings and clear list of already updated // displays if any of the policy values were updated. bool should_reset_settings = false; - should_reset_settings |= !new_external_config || - !external_display_settings_ || + should_reset_settings |= + bool{new_external_config} != bool{external_display_settings_}; + should_reset_settings |= new_external_config && external_display_settings_ && *new_external_config != *external_display_settings_; - should_reset_settings |= !new_internal_config || - !internal_display_settings_ || + should_reset_settings |= + bool{new_internal_config} != bool{internal_display_settings_}; + should_reset_settings |= new_internal_config && internal_display_settings_ && *new_internal_config != *internal_display_settings_; should_reset_settings |= recommended_ != new_recommended;
diff --git a/chrome/browser/extensions/api/resources_private/resources_private_api.cc b/chrome/browser/extensions/api/resources_private/resources_private_api.cc index ef039e9..cc6e3d5 100644 --- a/chrome/browser/extensions/api/resources_private/resources_private_api.cc +++ b/chrome/browser/extensions/api/resources_private/resources_private_api.cc
@@ -9,6 +9,7 @@ #include "base/values.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/ui/webui/localized_string.h" #include "chrome/common/extensions/api/resources_private.h" #include "chrome/grit/generated_resources.h" #include "components/strings/grit/components_strings.h" @@ -30,104 +31,85 @@ namespace { -void SetL10nString(base::DictionaryValue* dict, const std::string& string_id, - int resource_id) { - dict->SetString(string_id, l10n_util::GetStringUTF16(resource_id)); -} - void AddStringsForIdentity(base::DictionaryValue* dict) { - SetL10nString(dict, "window-title", IDS_EXTENSION_CONFIRM_PERMISSIONS); + dict->SetString("window-title", + l10n_util::GetStringUTF16(IDS_EXTENSION_CONFIRM_PERMISSIONS)); } void AddStringsForPdf(base::DictionaryValue* dict) { - SetL10nString(dict, "passwordDialogTitle", IDS_PDF_PASSWORD_DIALOG_TITLE); - SetL10nString(dict, "passwordPrompt", IDS_PDF_NEED_PASSWORD); - SetL10nString(dict, "passwordSubmit", IDS_PDF_PASSWORD_SUBMIT); - SetL10nString(dict, "passwordInvalid", IDS_PDF_PASSWORD_INVALID); - SetL10nString(dict, "pageLoading", IDS_PDF_PAGE_LOADING); - SetL10nString(dict, "pageLoadFailed", IDS_PDF_PAGE_LOAD_FAILED); - SetL10nString(dict, "errorDialogTitle", IDS_PDF_ERROR_DIALOG_TITLE); - SetL10nString(dict, "pageReload", IDS_PDF_PAGE_RELOAD_BUTTON); - SetL10nString(dict, "bookmarks", IDS_PDF_BOOKMARKS); - SetL10nString(dict, "labelPageNumber", IDS_PDF_LABEL_PAGE_NUMBER); - SetL10nString(dict, "tooltipRotateCW", IDS_PDF_TOOLTIP_ROTATE_CW); - SetL10nString(dict, "tooltipDownload", IDS_PDF_TOOLTIP_DOWNLOAD); - SetL10nString(dict, "tooltipPrint", IDS_PDF_TOOLTIP_PRINT); - SetL10nString(dict, "tooltipFitToPage", IDS_PDF_TOOLTIP_FIT_PAGE); - SetL10nString(dict, "tooltipFitToWidth", IDS_PDF_TOOLTIP_FIT_WIDTH); - SetL10nString(dict, "tooltipZoomIn", IDS_PDF_TOOLTIP_ZOOM_IN); - SetL10nString(dict, "tooltipZoomOut", IDS_PDF_TOOLTIP_ZOOM_OUT); + static constexpr LocalizedString kPdfResources[] = { + {"passwordDialogTitle", IDS_PDF_PASSWORD_DIALOG_TITLE}, + {"passwordPrompt", IDS_PDF_NEED_PASSWORD}, + {"passwordSubmit", IDS_PDF_PASSWORD_SUBMIT}, + {"passwordInvalid", IDS_PDF_PASSWORD_INVALID}, + {"pageLoading", IDS_PDF_PAGE_LOADING}, + {"pageLoadFailed", IDS_PDF_PAGE_LOAD_FAILED}, + {"errorDialogTitle", IDS_PDF_ERROR_DIALOG_TITLE}, + {"pageReload", IDS_PDF_PAGE_RELOAD_BUTTON}, + {"bookmarks", IDS_PDF_BOOKMARKS}, + {"labelPageNumber", IDS_PDF_LABEL_PAGE_NUMBER}, + {"tooltipRotateCW", IDS_PDF_TOOLTIP_ROTATE_CW}, + {"tooltipDownload", IDS_PDF_TOOLTIP_DOWNLOAD}, + {"tooltipPrint", IDS_PDF_TOOLTIP_PRINT}, + {"tooltipFitToPage", IDS_PDF_TOOLTIP_FIT_PAGE}, + {"tooltipFitToWidth", IDS_PDF_TOOLTIP_FIT_WIDTH}, + {"tooltipZoomIn", IDS_PDF_TOOLTIP_ZOOM_IN}, + {"tooltipZoomOut", IDS_PDF_TOOLTIP_ZOOM_OUT}, #if defined(OS_CHROMEOS) - SetL10nString(dict, "tooltipAnnotate", IDS_PDF_ANNOTATION_ANNOTATE); - SetL10nString(dict, "annotationDocumentTooLarge", - IDS_PDF_ANNOTATION_DOCUMENT_TOO_LARGE); - SetL10nString(dict, "annotationDocumentProtected", - IDS_PDF_ANNOTATION_DOCUMENT_PROTECTED); - SetL10nString(dict, "annotationDocumentRotated", - IDS_PDF_ANNOTATION_DOCUMENT_ROTATED); - SetL10nString(dict, "annotationPen", IDS_PDF_ANNOTATION_PEN); - SetL10nString(dict, "annotationHighlighter", IDS_PDF_ANNOTATION_HIGHLIGHTER); - SetL10nString(dict, "annotationEraser", IDS_PDF_ANNOTATION_ERASER); - SetL10nString(dict, "annotationUndo", IDS_PDF_ANNOTATION_UNDO); - SetL10nString(dict, "annotationRedo", IDS_PDF_ANNOTATION_REDO); - SetL10nString(dict, "annotationExpand", IDS_PDF_ANNOTATION_EXPAND); - SetL10nString(dict, "annotationColorBlack", IDS_PDF_ANNOTATION_COLOR_BLACK); - SetL10nString(dict, "annotationColorRed", IDS_PDF_ANNOTATION_COLOR_RED); - SetL10nString(dict, "annotationColorYellow", IDS_PDF_ANNOTATION_COLOR_YELLOW); - SetL10nString(dict, "annotationColorGreen", IDS_PDF_ANNOTATION_COLOR_GREEN); - SetL10nString(dict, "annotationColorCyan", IDS_PDF_ANNOTATION_COLOR_CYAN); - SetL10nString(dict, "annotationColorPurple", IDS_PDF_ANNOTATION_COLOR_PURPLE); - SetL10nString(dict, "annotationColorBrown", IDS_PDF_ANNOTATION_COLOR_BROWN); - SetL10nString(dict, "annotationColorWhite", IDS_PDF_ANNOTATION_COLOR_WHITE); - SetL10nString(dict, "annotationColorCrimson", - IDS_PDF_ANNOTATION_COLOR_CRIMSON); - SetL10nString(dict, "annotationColorAmber", IDS_PDF_ANNOTATION_COLOR_AMBER); - SetL10nString(dict, "annotationColorAvocadoGreen", - IDS_PDF_ANNOTATION_COLOR_AVOCADO_GREEN); - SetL10nString(dict, "annotationColorCobaltBlue", - IDS_PDF_ANNOTATION_COLOR_COBALT_BLUE); - SetL10nString(dict, "annotationColorDeepPurple", - IDS_PDF_ANNOTATION_COLOR_DEEP_PURPLE); - SetL10nString(dict, "annotationColorDarkBrown", - IDS_PDF_ANNOTATION_COLOR_DARK_BROWN); - SetL10nString(dict, "annotationColorDarkGrey", - IDS_PDF_ANNOTATION_COLOR_DARK_GREY); - SetL10nString(dict, "annotationColorHotPink", - IDS_PDF_ANNOTATION_COLOR_HOT_PINK); - SetL10nString(dict, "annotationColorOrange", IDS_PDF_ANNOTATION_COLOR_ORANGE); - SetL10nString(dict, "annotationColorLime", IDS_PDF_ANNOTATION_COLOR_LIME); - SetL10nString(dict, "annotationColorBlue", IDS_PDF_ANNOTATION_COLOR_BLUE); - SetL10nString(dict, "annotationColorViolet", IDS_PDF_ANNOTATION_COLOR_VIOLET); - SetL10nString(dict, "annotationColorTeal", IDS_PDF_ANNOTATION_COLOR_TEAL); - SetL10nString(dict, "annotationColorLightGrey", - IDS_PDF_ANNOTATION_COLOR_LIGHT_GREY); - SetL10nString(dict, "annotationColorLightPink", - IDS_PDF_ANNOTATION_COLOR_LIGHT_PINK); - SetL10nString(dict, "annotationColorLightOrange", - IDS_PDF_ANNOTATION_COLOR_LIGHT_ORANGE); - SetL10nString(dict, "annotationColorLightGreen", - IDS_PDF_ANNOTATION_COLOR_LIGHT_GREEN); - SetL10nString(dict, "annotationColorLightBlue", - IDS_PDF_ANNOTATION_COLOR_LIGHT_BLUE); - SetL10nString(dict, "annotationColorLavender", - IDS_PDF_ANNOTATION_COLOR_LAVENDER); - SetL10nString(dict, "annotationColorLightTeal", - IDS_PDF_ANNOTATION_COLOR_LIGHT_TEAL); - SetL10nString(dict, "annotationSize1", IDS_PDF_ANNOTATION_SIZE1); - SetL10nString(dict, "annotationSize2", IDS_PDF_ANNOTATION_SIZE2); - SetL10nString(dict, "annotationSize3", IDS_PDF_ANNOTATION_SIZE3); - SetL10nString(dict, "annotationSize4", IDS_PDF_ANNOTATION_SIZE4); - SetL10nString(dict, "annotationSize8", IDS_PDF_ANNOTATION_SIZE8); - SetL10nString(dict, "annotationSize12", IDS_PDF_ANNOTATION_SIZE12); - SetL10nString(dict, "annotationSize16", IDS_PDF_ANNOTATION_SIZE16); - SetL10nString(dict, "annotationSize20", IDS_PDF_ANNOTATION_SIZE20); - SetL10nString(dict, "annotationFormWarningTitle", - IDS_PDF_DISCARD_FORM_CHANGES); - SetL10nString(dict, "annotationFormWarningDetail", - IDS_PDF_DISCARD_FORM_CHANGES_DETAIL); - SetL10nString(dict, "annotationFormWarningKeepEditing", IDS_PDF_KEEP_EDITING); - SetL10nString(dict, "annotationFormWarningDiscard", IDS_PDF_DISCARD); -#endif + {"tooltipAnnotate", IDS_PDF_ANNOTATION_ANNOTATE}, + {"annotationDocumentTooLarge", IDS_PDF_ANNOTATION_DOCUMENT_TOO_LARGE}, + {"annotationDocumentProtected", IDS_PDF_ANNOTATION_DOCUMENT_PROTECTED}, + {"annotationDocumentRotated", IDS_PDF_ANNOTATION_DOCUMENT_ROTATED}, + {"annotationPen", IDS_PDF_ANNOTATION_PEN}, + {"annotationHighlighter", IDS_PDF_ANNOTATION_HIGHLIGHTER}, + {"annotationEraser", IDS_PDF_ANNOTATION_ERASER}, + {"annotationUndo", IDS_PDF_ANNOTATION_UNDO}, + {"annotationRedo", IDS_PDF_ANNOTATION_REDO}, + {"annotationExpand", IDS_PDF_ANNOTATION_EXPAND}, + {"annotationColorBlack", IDS_PDF_ANNOTATION_COLOR_BLACK}, + {"annotationColorRed", IDS_PDF_ANNOTATION_COLOR_RED}, + {"annotationColorYellow", IDS_PDF_ANNOTATION_COLOR_YELLOW}, + {"annotationColorGreen", IDS_PDF_ANNOTATION_COLOR_GREEN}, + {"annotationColorCyan", IDS_PDF_ANNOTATION_COLOR_CYAN}, + {"annotationColorPurple", IDS_PDF_ANNOTATION_COLOR_PURPLE}, + {"annotationColorBrown", IDS_PDF_ANNOTATION_COLOR_BROWN}, + {"annotationColorWhite", IDS_PDF_ANNOTATION_COLOR_WHITE}, + {"annotationColorCrimson", IDS_PDF_ANNOTATION_COLOR_CRIMSON}, + {"annotationColorAmber", IDS_PDF_ANNOTATION_COLOR_AMBER}, + {"annotationColorAvocadoGreen", IDS_PDF_ANNOTATION_COLOR_AVOCADO_GREEN}, + {"annotationColorCobaltBlue", IDS_PDF_ANNOTATION_COLOR_COBALT_BLUE}, + {"annotationColorDeepPurple", IDS_PDF_ANNOTATION_COLOR_DEEP_PURPLE}, + {"annotationColorDarkBrown", IDS_PDF_ANNOTATION_COLOR_DARK_BROWN}, + {"annotationColorDarkGrey", IDS_PDF_ANNOTATION_COLOR_DARK_GREY}, + {"annotationColorHotPink", IDS_PDF_ANNOTATION_COLOR_HOT_PINK}, + {"annotationColorOrange", IDS_PDF_ANNOTATION_COLOR_ORANGE}, + {"annotationColorLime", IDS_PDF_ANNOTATION_COLOR_LIME}, + {"annotationColorBlue", IDS_PDF_ANNOTATION_COLOR_BLUE}, + {"annotationColorViolet", IDS_PDF_ANNOTATION_COLOR_VIOLET}, + {"annotationColorTeal", IDS_PDF_ANNOTATION_COLOR_TEAL}, + {"annotationColorLightGrey", IDS_PDF_ANNOTATION_COLOR_LIGHT_GREY}, + {"annotationColorLightPink", IDS_PDF_ANNOTATION_COLOR_LIGHT_PINK}, + {"annotationColorLightOrange", IDS_PDF_ANNOTATION_COLOR_LIGHT_ORANGE}, + {"annotationColorLightGreen", IDS_PDF_ANNOTATION_COLOR_LIGHT_GREEN}, + {"annotationColorLightBlue", IDS_PDF_ANNOTATION_COLOR_LIGHT_BLUE}, + {"annotationColorLavender", IDS_PDF_ANNOTATION_COLOR_LAVENDER}, + {"annotationColorLightTeal", IDS_PDF_ANNOTATION_COLOR_LIGHT_TEAL}, + {"annotationSize1", IDS_PDF_ANNOTATION_SIZE1}, + {"annotationSize2", IDS_PDF_ANNOTATION_SIZE2}, + {"annotationSize3", IDS_PDF_ANNOTATION_SIZE3}, + {"annotationSize4", IDS_PDF_ANNOTATION_SIZE4}, + {"annotationSize8", IDS_PDF_ANNOTATION_SIZE8}, + {"annotationSize12", IDS_PDF_ANNOTATION_SIZE12}, + {"annotationSize16", IDS_PDF_ANNOTATION_SIZE16}, + {"annotationSize20", IDS_PDF_ANNOTATION_SIZE20}, + {"annotationFormWarningTitle", IDS_PDF_DISCARD_FORM_CHANGES}, + {"annotationFormWarningDetail", IDS_PDF_DISCARD_FORM_CHANGES_DETAIL}, + {"annotationFormWarningKeepEditing", IDS_PDF_KEEP_EDITING}, + {"annotationFormWarningDiscard", IDS_PDF_DISCARD}, +#endif // defined(OS_CHROMEOS) + }; + for (const auto& resource : kPdfResources) + dict->SetString(resource.name, l10n_util::GetStringUTF16(resource.id)); } void AddAdditionalDataForPdf(base::DictionaryValue* dict) {
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index d2967ab..178fc9bd 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -1927,8 +1927,8 @@ }, { "name": "enable-webnfc", - // "owners": [ "your-team" ], - "expiry_milestone": 76 + "owners": [ "rijubrata.bhaumik@intel.com","reillyg" ], + "expiry_milestone": 79 }, { "name": "enable-webrtc-h264-with-openh264-ffmpeg", @@ -2935,6 +2935,11 @@ "expiry_milestone": 76 }, { + "name": "sync-USS-autofill-wallet-metadata", + "owners": [ "jkrcal", "//components/sync/OWNERS" ], + "expiry_milestone": 76 + }, + { "name": "sync-standalone-transport", "owners": [ "treib", "//components/sync/OWNERS" ], "expiry_milestone": 76 @@ -3168,8 +3173,8 @@ }, { "name": "webrtc-unified-plan-by-default", - // "owners": [ "your-team" ], - "expiry_milestone": 76 + "owners": [ "//third_party/blink/renderer/modules/peerconnection/OWNERS", "hbos@chromium.org" ], + "expiry_milestone": 75 }, { "name": "webxr",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index ac93910..c23f9017 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -1825,12 +1825,6 @@ "Match Autofill suggestions based on substrings (token prefixes) rather " "than just prefixes."; -const char kSyncStandaloneTransportName[] = "Allow Sync standalone transport"; -const char kSyncStandaloneTransportDescription[] = - "If enabled, allows Chrome Sync to start in standalone transport mode. In " - "this mode, the Sync machinery can start without user opt-in, but only a " - "subset of data types are supported."; - const char kSyncSupportSecondaryAccountName[] = "Support secondary accounts for Sync standalone transport"; const char kSyncSupportSecondaryAccountDescription[] = @@ -1847,6 +1841,11 @@ const char kSyncUSSAutofillWalletDataDescription[] = "Enables the new implementation of autofill walet data sync"; +const char kSyncUSSAutofillWalletMetadataName[] = + "Enable USS for autofill wallet metadata"; +const char kSyncUSSAutofillWalletMetadataDescription[] = + "Enables the new implementation of autofill walet metadata sync"; + const char kSyncSandboxName[] = "Use Chrome Sync sandbox"; const char kSyncSandboxDescription[] = "Connects to the testing server for Chrome Sync.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 93b418ae..1bda146 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1086,9 +1086,6 @@ extern const char kSyncSandboxName[]; extern const char kSyncSandboxDescription[]; -extern const char kSyncStandaloneTransportName[]; -extern const char kSyncStandaloneTransportDescription[]; - extern const char kSyncSupportSecondaryAccountName[]; extern const char kSyncSupportSecondaryAccountDescription[]; @@ -1098,6 +1095,9 @@ extern const char kSyncUSSAutofillWalletDataName[]; extern const char kSyncUSSAutofillWalletDataDescription[]; +extern const char kSyncUSSAutofillWalletMetadataName[]; +extern const char kSyncUSSAutofillWalletMetadataDescription[]; + extern const char kTabGridLayoutAndroidName[]; extern const char kTabGridLayoutAndroidDescription[];
diff --git a/chrome/browser/media/router/discovery/dial/dial_service.cc b/chrome/browser/media/router/discovery/dial/dial_service.cc index 0c27310a..6df061a 100644 --- a/chrome/browser/media/router/discovery/dial/dial_service.cc +++ b/chrome/browser/media/router/discovery/dial/dial_service.cc
@@ -321,9 +321,9 @@ bool DialServiceImpl::DialSocket::ParseResponse(const std::string& response, const base::Time& response_time, DialDeviceData* device) { - int headers_end = + size_t headers_end = HttpUtil::LocateEndOfHeaders(response.c_str(), response.size()); - if (headers_end < 1) { + if (headers_end == 0 || headers_end == std::string::npos) { VLOG(1) << "Headers invalid or empty, ignoring: " << response; return false; }
diff --git a/chrome/browser/metrics/chrome_feature_list_creator.h b/chrome/browser/metrics/chrome_feature_list_creator.h index 8e0f2eff1..1b3434c 100644 --- a/chrome/browser/metrics/chrome_feature_list_creator.h +++ b/chrome/browser/metrics/chrome_feature_list_creator.h
@@ -69,6 +69,10 @@ } const std::string& actual_locale() { return actual_locale_; } + ChromeBrowserFieldTrials* browser_field_trials() { + return browser_field_trials_.get(); + } + private: void CreatePrefService(); void ConvertFlagsToSwitches();
diff --git a/chrome/browser/metrics/chrome_metrics_service_accessor.h b/chrome/browser/metrics/chrome_metrics_service_accessor.h index 4e08bee..a3f2f59 100644 --- a/chrome/browser/metrics/chrome_metrics_service_accessor.h +++ b/chrome/browser/metrics/chrome_metrics_service_accessor.h
@@ -85,7 +85,7 @@ friend class ::CrashesDOMHandler; friend class ::FlashDOMHandler; friend void chrome::AttemptRestart(); - friend void chrome::SetupMobileFieldTrials(); + friend class ChromeBrowserFieldTrials; // For ChromeWinClang. friend class ChromeBrowserMainExtraPartsMetrics; // For StackSamplingConfiguration.
diff --git a/chrome/browser/metrics/ukm_browsertest.cc b/chrome/browser/metrics/ukm_browsertest.cc index 8707e11..fee542cf 100644 --- a/chrome/browser/metrics/ukm_browsertest.cc +++ b/chrome/browser/metrics/ukm_browsertest.cc
@@ -332,9 +332,7 @@ class UkmBrowserTestWithSyncTransport : public UkmBrowserTest { public: UkmBrowserTestWithSyncTransport() { - features_.InitWithFeatures({switches::kSyncStandaloneTransport, - switches::kSyncSupportSecondaryAccount}, - {}); + features_.InitAndEnableFeature(switches::kSyncSupportSecondaryAccount); } void SetUpInProcessBrowserTestFixture() override {
diff --git a/chrome/browser/offline_pages/android/prefetch_test_bridge.cc b/chrome/browser/offline_pages/android/prefetch_test_bridge.cc index d65ea68..3900cd1 100644 --- a/chrome/browser/offline_pages/android/prefetch_test_bridge.cc +++ b/chrome/browser/offline_pages/android/prefetch_test_bridge.cc
@@ -49,9 +49,10 @@ const JavaParamRef<jbyteArray>& j_image_data) { Profile* profile = ProfileManager::GetLastUsedProfile(); DCHECK(profile); + SimpleFactoryKey* simple_factory_key = Profile::GetSimpleFactoryKey(profile); image_fetcher::CachedImageFetcherService* service = - image_fetcher::CachedImageFetcherServiceFactory::GetForBrowserContext( - profile); + image_fetcher::CachedImageFetcherServiceFactory::GetForKey( + simple_factory_key, profile->GetPrefs()); DCHECK(service); scoped_refptr<image_fetcher::ImageCache> cache = service->ImageCacheForTesting();
diff --git a/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc b/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc index c254f63e..8c692f4 100644 --- a/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc +++ b/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc
@@ -47,7 +47,9 @@ BrowserContextDependencyManager::GetInstance()) { DependsOn(DownloadServiceFactory::GetInstance()); DependsOn(OfflinePageModelFactory::GetInstance()); - DependsOn(image_fetcher::CachedImageFetcherServiceFactory::GetInstance()); + // TODO(hanxi): add + // DependsOn(image_fetcher::CachedImageFetcherServiceFactory::GetInstance()); + // when the PrefetchServiceFactory becomes a SimpleKeyedServiceFactory. } // static @@ -104,9 +106,11 @@ suggested_articles_observer = std::make_unique<SuggestedArticlesObserver>(); thumbnail_fetcher = std::make_unique<ThumbnailFetcherImpl>(); } else { + SimpleFactoryKey* simple_factory_key = + Profile::GetSimpleFactoryKey(profile); image_fetcher::CachedImageFetcherService* image_fetcher_service = - image_fetcher::CachedImageFetcherServiceFactory::GetForBrowserContext( - context); + image_fetcher::CachedImageFetcherServiceFactory::GetForKey( + simple_factory_key, profile->GetPrefs()); DCHECK(image_fetcher_service); thumbnail_image_fetcher = image_fetcher_service->GetCachedImageFetcher(); }
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc index 444bc67..04b79c43 100644 --- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc +++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
@@ -149,6 +149,11 @@ RegisterInputEventObserver(new_host); } +void MetricsWebContentsObserver::FrameDeleted(content::RenderFrameHost* rfh) { + if (committed_load_) + committed_load_->FrameDeleted(rfh); +} + void MetricsWebContentsObserver::MediaStartedPlaying( const content::WebContentsObserver::MediaPlayerInfo& video_type, const content::WebContentsObserver::MediaPlayerId& id) {
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h index 395659f..faee044 100644 --- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h +++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
@@ -105,6 +105,7 @@ void RenderProcessGone(base::TerminationStatus status) override; void RenderViewHostChanged(content::RenderViewHost* old_host, content::RenderViewHost* new_host) override; + void FrameDeleted(content::RenderFrameHost* render_frame_host) override; void MediaStartedPlaying( const content::WebContentsObserver::MediaPlayerInfo& video_type, const content::WebContentsObserver::MediaPlayerId& id) override;
diff --git a/chrome/browser/page_load_metrics/observers/amp_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/amp_page_load_metrics_observer.cc index 89cc069..2e3ff51e 100644 --- a/chrome/browser/page_load_metrics/observers/amp_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/amp_page_load_metrics_observer.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/page_load_metrics/observers/amp_page_load_metrics_observer.h" +#include <algorithm> #include <string> #include "base/optional.h" @@ -13,6 +14,8 @@ #include "chrome/common/page_load_metrics/page_load_timing.h" #include "components/google/core/common/google_util.h" #include "content/public/browser/navigation_handle.h" +#include "content/public/browser/render_frame_host.h" +#include "net/base/url_util.h" #include "url/gurl.h" namespace { @@ -33,6 +36,25 @@ const char kHistogramAMPParseStartRedirect[] = "ParseTiming.NavigationToParseStart.RedirectToNonAmpPage"; +const char kHistogramAMPSubframeNavigationToInput[] = + "Experimental.PageTiming.NavigationToInput.Subframe"; +const char kHistogramAMPSubframeInputToNavigation[] = + "Experimental.PageTiming.InputToNavigation.Subframe"; +const char kHistogramAMPSubframeMainFrameToSubFrameNavigation[] = + "Experimental.PageTiming.MainFrameToSubFrameNavigationDelta.Subframe"; +const char kHistogramAMPSubframeFirstContentfulPaint[] = + "PaintTiming.InputToFirstContentfulPaint.Subframe"; +const char kHistogramAMPSubframeFirstContentfulPaintFullNavigation[] = + "PaintTiming.InputToFirstContentfulPaint.Subframe.FullNavigation"; +const char kHistogramAMPSubframeLargestContentPaint[] = + "PaintTiming.InputToLargestContentPaint.Subframe"; +const char kHistogramAMPSubframeLargestContentPaintFullNavigation[] = + "PaintTiming.InputToLargestContentPaint.Subframe.FullNavigation"; +const char kHistogramAMPSubframeFirstInputDelay[] = + "InteractiveTiming.FirstInputDelay3.Subframe"; +const char kHistogramAMPSubframeFirstInputDelayFullNavigation[] = + "InteractiveTiming.FirstInputDelay3.Subframe.FullNavigation"; + // Host pattern for AMP Cache URLs. // See https://developers.google.com/amp/cache/overview#amp-cache-url-format // for a definition of the format of AMP Cache URLs. @@ -77,18 +99,44 @@ return url.ReplaceComponents(replacements); } +// Extracts the AMP viewer URL from an AMP cache URL, as encoded in a fragment +// parameter. +GURL GetViewerUrlFromCacheUrl(const GURL& url) { + // The viewer URL is encoded in the fragment as a query string parameter + // (&viewerURL=<URL>). net::QueryIterator only operates on the query string, + // so we copy the fragment into the query string, then iterate over the + // parameters below. + std::string ref = url.ref(); + GURL::Replacements replacements; + replacements.SetQuery(ref.c_str(), url::Component(0, ref.length())); + GURL modified_url = url.ReplaceComponents(replacements); + for (net::QueryIterator it(modified_url); !it.IsAtEnd(); it.Advance()) { + if (it.GetKey() == "viewerUrl") + return GURL(it.GetUnescapedValue()); + } + return GURL::EmptyGURL(); +} + +base::TimeDelta ClampToZero(base::TimeDelta t) { + return std::max(base::TimeDelta(), t); +} + } // namespace AMPPageLoadMetricsObserver::AMPPageLoadMetricsObserver() {} AMPPageLoadMetricsObserver::~AMPPageLoadMetricsObserver() {} +AMPPageLoadMetricsObserver::SubFrameInfo::SubFrameInfo() = default; +AMPPageLoadMetricsObserver::SubFrameInfo::~SubFrameInfo() = default; + page_load_metrics::PageLoadMetricsObserver::ObservePolicy AMPPageLoadMetricsObserver::OnCommit( content::NavigationHandle* navigation_handle, ukm::SourceId source_id) { current_url_ = navigation_handle->GetURL(); view_type_ = GetAMPViewType(current_url_); + ProcessMainFrameNavigation(navigation_handle, view_type_); return CONTINUE_OBSERVING; } @@ -101,17 +149,71 @@ return; current_url_ = url; + // We're transitioning to a new URL, so record metrics for the previous AMP + // document, if any. + MaybeRecordAmpDocumentMetrics(); + current_main_frame_nav_info_ = nullptr; + AMPViewType same_document_view_type = GetAMPViewType(url); if (same_document_view_type == AMPViewType::NONE) return; - // Though we're not currently able to track page load metrics such as FCP for - // same-document navigations, we can count how often they happen, to better - // understand the relative frequency of same-document vs new-document AMP - // navigations. + // Count how often AMP same-document navigations occur. UMA_HISTOGRAM_ENUMERATION( std::string(kHistogramPrefix).append("SameDocumentView"), same_document_view_type, AMPViewType::AMP_VIEW_TYPE_LAST); + + ProcessMainFrameNavigation(navigation_handle, same_document_view_type); +} + +void AMPPageLoadMetricsObserver::OnDidFinishSubFrameNavigation( + content::NavigationHandle* navigation_handle) { + if (!navigation_handle->HasCommitted()) + return; + + // A new navigation is committing, so ensure any old information associated + // with this frame is discarded. + amp_subframe_info_.erase(navigation_handle->GetRenderFrameHost()); + + // Only track frames that are direct descendents of the main frame. + if (navigation_handle->GetParentFrame() == nullptr || + navigation_handle->GetParentFrame()->GetParent() != nullptr) + return; + + // Only track frames that have AMP cache URLs. + if (GetAMPViewType(navigation_handle->GetURL()) != AMPViewType::AMP_CACHE) + return; + + GURL viewer_url = GetViewerUrlFromCacheUrl(navigation_handle->GetURL()); + if (viewer_url.is_empty()) + return; + + // Record information about the AMP document loaded in this subframe, which we + // may use later to record metrics. + auto& subframe_info = + amp_subframe_info_[navigation_handle->GetRenderFrameHost()]; + subframe_info.viewer_url = viewer_url; + subframe_info.navigation_start = navigation_handle->NavigationStart(); + + // If the current MainFrameNavigationInfo doesn't yet have a subframe + // RenderFrameHost, and its URL matches our viewer URL, then associate the + // MainFrameNavigationInfo with this frame. + if (current_main_frame_nav_info_ && + current_main_frame_nav_info_->subframe_rfh == nullptr && + subframe_info.viewer_url == current_main_frame_nav_info_->url) { + current_main_frame_nav_info_->subframe_rfh = + navigation_handle->GetRenderFrameHost(); + } +} + +void AMPPageLoadMetricsObserver::OnFrameDeleted(content::RenderFrameHost* rfh) { + if (current_main_frame_nav_info_ && + current_main_frame_nav_info_->subframe_rfh == rfh) { + MaybeRecordAmpDocumentMetrics(); + current_main_frame_nav_info_->subframe_rfh = nullptr; + } + + amp_subframe_info_.erase(rfh); } void AMPPageLoadMetricsObserver::OnDomContentLoadedEventStart( @@ -186,7 +288,7 @@ // case in the Google News AMP viewer, for example: when a user loads a news // AMP URL in a non-same-document navigation context, the user is presented // with a redirect prompt which they must click through to continue to the - // canoncial document on the non-AMP origin. + // canonical document on the non-AMP origin. AMPViewType initial_view_type = GetAMPViewType(info.start_url); if (initial_view_type != AMPViewType::NONE) { RECORD_HISTOGRAM_FOR_TYPE(kHistogramAMPParseStartRedirect, @@ -200,6 +302,166 @@ timing.parse_timing->parse_start.value()); } +void AMPPageLoadMetricsObserver::OnTimingUpdate( + content::RenderFrameHost* subframe_rfh, + const page_load_metrics::mojom::PageLoadTiming& timing, + const page_load_metrics::PageLoadExtraInfo& extra_info) { + if (subframe_rfh == nullptr) + return; + + auto it = amp_subframe_info_.find(subframe_rfh); + if (it == amp_subframe_info_.end()) + return; + + it->second.timing = timing.Clone(); +} + +void AMPPageLoadMetricsObserver::OnComplete( + const page_load_metrics::mojom::PageLoadTiming& timing, + const page_load_metrics::PageLoadExtraInfo& info) { + MaybeRecordAmpDocumentMetrics(); + current_main_frame_nav_info_ = nullptr; +} + +void AMPPageLoadMetricsObserver::ProcessMainFrameNavigation( + content::NavigationHandle* navigation_handle, + AMPViewType view_type) { + if (view_type != AMPViewType::GOOGLE_SEARCH_AMP_VIEWER) + return; + + // Find the subframe RenderFrameHost hosting the AMP document for this + // navigation. Note that in some cases, the subframe may not exist yet, in + // which case logic in OnDidFinishSubFrameNavigation will associate the + // subframe with current_main_frame_nav_info_. + content::RenderFrameHost* subframe_rfh = nullptr; + for (const auto& kv : amp_subframe_info_) { + if (navigation_handle->GetURL() == kv.second.viewer_url) { + subframe_rfh = kv.first; + break; + } + } + + current_main_frame_nav_info_ = base::WrapUnique( + new MainFrameNavigationInfo{navigation_handle->GetURL(), subframe_rfh, + navigation_handle->NavigationStart(), + navigation_handle->IsSameDocument()}); +} + +void AMPPageLoadMetricsObserver::MaybeRecordAmpDocumentMetrics() { + if (current_main_frame_nav_info_ == nullptr || + current_main_frame_nav_info_->subframe_rfh == nullptr) + return; + + auto it = amp_subframe_info_.find(current_main_frame_nav_info_->subframe_rfh); + if (it == amp_subframe_info_.end()) + return; + + const SubFrameInfo& subframe_info = it->second; + if (subframe_info.viewer_url != current_main_frame_nav_info_->url) + return; + + // TimeDeltas in subframe_info are relative to the navigation start in the AMP + // subframe. Given that AMP subframes can be prerendered and thus their + // navigation start may be long before a user initiates the navigation to that + // AMP document, we need to adjust the times by the difference between the + // top-level navigation start (which is when the top-level URL was updated to + // reflect the AMP Viewer URL for the AMP document) and the navigation start + // in the AMP subframe. Note that we use the top-level navigation start as our + // best estimate of when the user initiated the navigation. + base::TimeDelta navigation_input_delta = + current_main_frame_nav_info_->navigation_start - + subframe_info.navigation_start; + + if (!current_main_frame_nav_info_->is_same_document_navigation) { + // For non same document navigations, we expect the main frame navigation + // to be before the subframe navigation. This measures the time from main + // frame navigation to the time the AMP subframe is added to the document. + PAGE_LOAD_HISTOGRAM( + std::string(kHistogramPrefix) + .append(kHistogramAMPSubframeMainFrameToSubFrameNavigation), + -navigation_input_delta); + } else { + if (navigation_input_delta >= base::TimeDelta()) { + // Prerender case: subframe navigation happens before main frame + // navigation. + PAGE_LOAD_HISTOGRAM(std::string(kHistogramPrefix) + .append(kHistogramAMPSubframeNavigationToInput), + navigation_input_delta); + } else { + // For same document navigations, if the main frame navigation is + // initiated before the AMP subframe is navigated, + // |navigation_input_delta| will be negative. This happens in the + // non-prerender case. We record this delta to ensure it's consistently a + // small value (the expected case). + PAGE_LOAD_HISTOGRAM(std::string(kHistogramPrefix) + .append(kHistogramAMPSubframeInputToNavigation), + -navigation_input_delta); + } + } + + if (!subframe_info.timing.is_null()) { + if (subframe_info.timing->paint_timing->first_contentful_paint + .has_value()) { + base::TimeDelta first_contentful_paint = ClampToZero( + subframe_info.timing->paint_timing->first_contentful_paint.value() - + navigation_input_delta); + if (current_main_frame_nav_info_->is_same_document_navigation) { + PAGE_LOAD_HISTOGRAM( + std::string(kHistogramPrefix) + .append(kHistogramAMPSubframeFirstContentfulPaint), + first_contentful_paint); + } else { + PAGE_LOAD_HISTOGRAM( + std::string(kHistogramPrefix) + .append( + kHistogramAMPSubframeFirstContentfulPaintFullNavigation), + first_contentful_paint); + } + } + + base::Optional<base::TimeDelta> largest_content_paint_time; + uint64_t largest_content_paint_size; + PageLoadMetricsObserver::LargestContentType largest_content_type; + if (AssignTimeAndSizeForLargestContentfulPaint( + subframe_info.timing->paint_timing, &largest_content_paint_time, + &largest_content_paint_size, &largest_content_type)) { + // Adjust by the navigation_input_delta. + largest_content_paint_time = ClampToZero( + largest_content_paint_time.value() - navigation_input_delta); + if (current_main_frame_nav_info_->is_same_document_navigation) { + PAGE_LOAD_HISTOGRAM( + std::string(kHistogramPrefix) + .append(kHistogramAMPSubframeLargestContentPaint), + largest_content_paint_time.value()); + } else { + PAGE_LOAD_HISTOGRAM( + std::string(kHistogramPrefix) + .append(kHistogramAMPSubframeLargestContentPaintFullNavigation), + largest_content_paint_time.value()); + } + } + + if (subframe_info.timing->interactive_timing->first_input_delay + .has_value()) { + if (current_main_frame_nav_info_->is_same_document_navigation) { + UMA_HISTOGRAM_CUSTOM_TIMES( + std::string(kHistogramPrefix) + .append(kHistogramAMPSubframeFirstInputDelay), + subframe_info.timing->interactive_timing->first_input_delay.value(), + base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromSeconds(60), 50); + } else { + UMA_HISTOGRAM_CUSTOM_TIMES( + std::string(kHistogramPrefix) + .append(kHistogramAMPSubframeFirstInputDelayFullNavigation), + subframe_info.timing->interactive_timing->first_input_delay.value(), + base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromSeconds(60), 50); + } + } + } +} + // static AMPPageLoadMetricsObserver::AMPViewType AMPPageLoadMetricsObserver::GetAMPViewType(const GURL& url) {
diff --git a/chrome/browser/page_load_metrics/observers/amp_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/amp_page_load_metrics_observer.h index 4c6f289..408e969c 100644 --- a/chrome/browser/page_load_metrics/observers/amp_page_load_metrics_observer.h +++ b/chrome/browser/page_load_metrics/observers/amp_page_load_metrics_observer.h
@@ -5,6 +5,9 @@ #ifndef CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_AMP_PAGE_LOAD_METRICS_OBSERVER_H_ #define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_AMP_PAGE_LOAD_METRICS_OBSERVER_H_ +#include <map> +#include <memory> + #include "base/macros.h" #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h" #include "services/metrics/public/cpp/ukm_source.h" @@ -13,12 +16,31 @@ class NavigationHandle; } -// Observer responsible for recording page load metrics relevant to page served -// from the AMP cache. When AMP pages are served in a same page navigation, UMA -// is not recorded; this is typical for AMP pages navigated to from google.com. -// Navigations to AMP pages from the google search app or directly to the amp -// cache page will be tracked. Refreshing an AMP page served from google.com -// will be tracked. +// Observer responsible for recording metrics for AMP documents. This includes +// both AMP documents loaded in the main frame, and AMP documents loaded in a +// subframe (e.g. in an AMP viewer in the main frame). +// +// For AMP documents loaded in a subframe, recording works like so: +// +// * whenever the main frame URL gets updated with an AMP viewer +// URL (e.g. https://www.google.com/amp/...), we track that in +// OnCommitSameDocumentNavigation. we use the time of the main +// frame URL update as the baseline time from which the +// user-perceived performance metrics like FCP are computed. +// +// * whenever an iframe AMP document is loaded, we track that in +// OnDidFinishSubFrameNavigation. we also keep track of the +// performance timing metrics such as FCP reported in the frame. +// +// * we associate the main frame AMP navigation with its associated +// AMP document in an iframe by comparing URLs between the main +// frame and the iframe documents. +// +// * we record AMP metrics at the times when an AMP viewer URL is +// navigated away from. when a user swipes to change the AMP +// document, closes a tab, types a new URL in the URL bar, etc, +// we will record AMP metrics for the AMP doc in an iframe that +// the user is navigating away from. class AMPPageLoadMetricsObserver : public page_load_metrics::PageLoadMetricsObserver { public: @@ -45,6 +67,9 @@ ukm::SourceId source_id) override; void OnCommitSameDocumentNavigation( content::NavigationHandle* navigation_handle) override; + void OnDidFinishSubFrameNavigation( + content::NavigationHandle* navigation_handle) override; + void OnFrameDeleted(content::RenderFrameHost* rfh) override; void OnDomContentLoadedEventStart( const page_load_metrics::mojom::PageLoadTiming& timing, const page_load_metrics::PageLoadExtraInfo& info) override; @@ -58,8 +83,60 @@ const page_load_metrics::PageLoadExtraInfo& info) override; void OnParseStart(const page_load_metrics::mojom::PageLoadTiming& timing, const page_load_metrics::PageLoadExtraInfo& info) override; + void OnTimingUpdate( + content::RenderFrameHost* subframe_rfh, + const page_load_metrics::mojom::PageLoadTiming& timing, + const page_load_metrics::PageLoadExtraInfo& extra_info) override; + void OnComplete(const page_load_metrics::mojom::PageLoadTiming& timing, + const page_load_metrics::PageLoadExtraInfo& info) override; private: + // Information about an AMP navigation in the main frame. Both regular and + // same document navigations are included. + struct MainFrameNavigationInfo { + GURL url; + + // Pointer to the RenderViewHost for the iframe hosting the AMP document + // associated with the main frame AMP navigation. + content::RenderFrameHost* subframe_rfh = nullptr; + + // Navigation start time for the main frame AMP navigation. We use this time + // as an approximation of the time the user initiated the navigation. + base::TimeTicks navigation_start; + + // Whether the main frame navigation is a same document navigation. + bool is_same_document_navigation = false; + }; + + // Information about an AMP subframe. + struct SubFrameInfo { + SubFrameInfo(); + ~SubFrameInfo(); + + // The AMP viewer URL of the currently committed AMP document. Used for + // matching the MainFrameNavigationInfo url. + GURL viewer_url; + + // The navigation start time of the non-same-document navigation in the AMP + // iframe. Timestamps in |timing| below are relative to this value. + base::TimeTicks navigation_start; + + // Timing metrics observed in the AMP iframe. + page_load_metrics::mojom::PageLoadTimingPtr timing; + }; + + void ProcessMainFrameNavigation(content::NavigationHandle* navigation_handle, + AMPViewType view_type); + void MaybeRecordAmpDocumentMetrics(); + + // Information about the currently active AMP navigation in the main + // frame. Will be null if there isn't an active AMP navigation in the main + // frame. + std::unique_ptr<MainFrameNavigationInfo> current_main_frame_nav_info_; + + // Information about each active AMP iframe in the main document. + std::map<content::RenderFrameHost*, SubFrameInfo> amp_subframe_info_; + GURL current_url_; AMPViewType view_type_ = AMPViewType::NONE;
diff --git a/chrome/browser/page_load_metrics/observers/amp_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/amp_page_load_metrics_observer_unittest.cc index 9b7a666..21b2d05d 100644 --- a/chrome/browser/page_load_metrics/observers/amp_page_load_metrics_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/amp_page_load_metrics_observer_unittest.cc
@@ -13,7 +13,9 @@ #include "chrome/browser/page_load_metrics/page_load_tracker.h" #include "chrome/common/page_load_metrics/page_load_timing.h" #include "chrome/common/page_load_metrics/test/page_load_metrics_test_util.h" +#include "content/public/browser/web_contents.h" #include "content/public/test/navigation_simulator.h" +#include "content/public/test/test_utils.h" #include "url/gurl.h" using content::NavigationSimulator; @@ -205,6 +207,18 @@ static_cast<base::HistogramBase::Sample>( AMPViewType::GOOGLE_SEARCH_AMP_VIEWER), 2); + + // Verify that subframe metrics aren't recorded without an AMP subframe. + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.NavigationToInput.Subframe", + 0); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.InputToNavigation.Subframe", + 0); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming." + "MainFrameToSubFrameNavigationDelta.Subframe", + 0); } TEST_F(AMPPageLoadMetricsObserverTest, GoogleNewsAMPCacheRedirect) { @@ -231,3 +245,383 @@ timing_.parse_timing->parse_start.value().InMilliseconds()), 1); } + +TEST_F(AMPPageLoadMetricsObserverTest, SubFrameInputBeforeNavigation) { + // This emulates the AMP subframe non-prerender flow: first we perform a + // same-document navigation in the main frame to the AMP viewer URL, then we + // create and navigate the subframe to an AMP cache URL. + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/search"), main_rfh()) + ->Commit(); + + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/page"), main_rfh()) + ->CommitSameDocument(); + + NavigationSimulator::NavigateAndCommitFromDocument( + GURL("https://cdn.ampproject.org/page" + "#viewerUrl=https%3A%2F%2Fwww.google.com%2Famp%2Fpage"), + content::RenderFrameHostTester::For(web_contents()->GetMainFrame()) + ->AppendChild("subframe")); + + // Navigate the main frame to trigger metrics recording. + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/other"), main_rfh()) + ->CommitSameDocument(); + + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.NavigationToInput.Subframe", + 0); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.InputToNavigation.Subframe", + 1); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming." + "MainFrameToSubFrameNavigationDelta.Subframe", + 0); +} + +TEST_F(AMPPageLoadMetricsObserverTest, SubFrameNavigationBeforeInput) { + // This emulates the AMP subframe prerender flow: first we create and navigate + // the subframe to an AMP cache URL, then we perform a same-document + // navigation in the main frame to the AMP viewer URL. + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/search"), main_rfh()) + ->Commit(); + + NavigationSimulator::NavigateAndCommitFromDocument( + GURL("https://cdn.ampproject.org/page" + "#viewerUrl=https%3A%2F%2Fwww.google.com%2Famp%2Fpage"), + content::RenderFrameHostTester::For(web_contents()->GetMainFrame()) + ->AppendChild("subframe")); + + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/page"), main_rfh()) + ->CommitSameDocument(); + + // Navigate the main frame to trigger metrics recording. + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/other"), main_rfh()) + ->CommitSameDocument(); + + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.NavigationToInput.Subframe", + 1); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.InputToNavigation.Subframe", + 0); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming." + "MainFrameToSubFrameNavigationDelta.Subframe", + 0); +} + +TEST_F(AMPPageLoadMetricsObserverTest, SubFrameMetrics) { + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/search"), main_rfh()) + ->Commit(); + + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/page"), main_rfh()) + ->CommitSameDocument(); + + content::RenderFrameHost* subframe = + NavigationSimulator::NavigateAndCommitFromDocument( + GURL("https://cdn.ampproject.org/page" + "#viewerUrl=https%3A%2F%2Fwww.google.com%2Famp%2Fpage"), + content::RenderFrameHostTester::For(web_contents()->GetMainFrame()) + ->AppendChild("subframe")); + + page_load_metrics::mojom::PageLoadTiming subframe_timing; + page_load_metrics::InitPageLoadTimingForTest(&subframe_timing); + subframe_timing.navigation_start = base::Time::FromDoubleT(2); + subframe_timing.paint_timing->first_contentful_paint = + base::TimeDelta::FromMilliseconds(5); + subframe_timing.paint_timing->largest_image_paint_size = 1; + subframe_timing.paint_timing->largest_image_paint = + base::TimeDelta::FromMilliseconds(10); + subframe_timing.interactive_timing->first_input_timestamp = + base::TimeDelta::FromMilliseconds(20); + subframe_timing.interactive_timing->first_input_delay = + base::TimeDelta::FromMilliseconds(3); + PopulateRequiredTimingFields(&subframe_timing); + + SimulateTimingUpdate(subframe_timing, subframe); + + // Navigate the main frame to trigger metrics recording. + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/other"), main_rfh()) + ->CommitSameDocument(); + + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.PaintTiming.InputToFirstContentfulPaint.Subframe", + 1); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.PaintTiming.InputToLargestContentPaint.Subframe", + 1); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.InteractiveTiming.FirstInputDelay3.Subframe", 1); +} + +TEST_F(AMPPageLoadMetricsObserverTest, SubFrameMetricsFullNavigation) { + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/page"), main_rfh()) + ->Commit(); + + content::RenderFrameHost* subframe = + NavigationSimulator::NavigateAndCommitFromDocument( + GURL("https://cdn.ampproject.org/page" + "#viewerUrl=https%3A%2F%2Fwww.google.com%2Famp%2Fpage"), + content::RenderFrameHostTester::For(web_contents()->GetMainFrame()) + ->AppendChild("subframe")); + + page_load_metrics::mojom::PageLoadTiming subframe_timing; + page_load_metrics::InitPageLoadTimingForTest(&subframe_timing); + subframe_timing.navigation_start = base::Time::FromDoubleT(2); + subframe_timing.paint_timing->first_contentful_paint = + base::TimeDelta::FromMilliseconds(5); + subframe_timing.paint_timing->largest_image_paint_size = 1; + subframe_timing.paint_timing->largest_image_paint = + base::TimeDelta::FromMilliseconds(10); + subframe_timing.interactive_timing->first_input_timestamp = + base::TimeDelta::FromMilliseconds(20); + subframe_timing.interactive_timing->first_input_delay = + base::TimeDelta::FromMilliseconds(3); + PopulateRequiredTimingFields(&subframe_timing); + + SimulateTimingUpdate(subframe_timing, subframe); + + // Navigate the main frame to trigger metrics recording. + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/other"), main_rfh()) + ->CommitSameDocument(); + + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.PaintTiming.InputToFirstContentfulPaint.Subframe." + "FullNavigation", + 1); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.PaintTiming.InputToLargestContentPaint.Subframe." + "FullNavigation", + 1); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.InteractiveTiming.FirstInputDelay3.Subframe." + "FullNavigation", + 1); +} + +TEST_F(AMPPageLoadMetricsObserverTest, SubFrameRecordOnFullNavigation) { + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/search"), main_rfh()) + ->Commit(); + + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/page"), main_rfh()) + ->CommitSameDocument(); + + NavigationSimulator::NavigateAndCommitFromDocument( + GURL("https://cdn.ampproject.org/page" + "#viewerUrl=https%3A%2F%2Fwww.google.com%2Famp%2Fpage"), + content::RenderFrameHostTester::For(web_contents()->GetMainFrame()) + ->AppendChild("subframe")); + + // Navigate the main frame to trigger metrics recording. + NavigationSimulator::CreateRendererInitiated(GURL("https://www.example.com/"), + main_rfh()) + ->Commit(); + + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.InputToNavigation.Subframe", + 1); +} + +TEST_F(AMPPageLoadMetricsObserverTest, SubFrameRecordOnFrameDeleted) { + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/search"), main_rfh()) + ->Commit(); + + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/page"), main_rfh()) + ->CommitSameDocument(); + + content::RenderFrameHost* subframe = + NavigationSimulator::NavigateAndCommitFromDocument( + GURL("https://cdn.ampproject.org/page" + "#viewerUrl=https%3A%2F%2Fwww.google.com%2Famp%2Fpage"), + content::RenderFrameHostTester::For(web_contents()->GetMainFrame()) + ->AppendChild("subframe")); + + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.InputToNavigation.Subframe", + 0); + + // Delete the subframe, which should trigger metrics recording. + content::RenderFrameHostTester::For(subframe)->Detach(); + + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.InputToNavigation.Subframe", + 1); +} + +TEST_F(AMPPageLoadMetricsObserverTest, SubFrameMultipleFrames) { + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/search"), main_rfh()) + ->Commit(); + + // Simulate a prerender. + NavigationSimulator::NavigateAndCommitFromDocument( + GURL("https://cdn.ampproject.org/page2" + "#viewerUrl=https%3A%2F%2Fwww.google.com%2Famp%2Fpage2"), + content::RenderFrameHostTester::For(web_contents()->GetMainFrame()) + ->AppendChild("subframe")); + + // Perform a main-frame navigation to a different AMP document (not the + // prerender). + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/page"), main_rfh()) + ->CommitSameDocument(); + + // Load the associated AMP document in an iframe. + NavigationSimulator::NavigateAndCommitFromDocument( + GURL("https://cdn.ampproject.org/page" + "#viewerUrl=https%3A%2F%2Fwww.google.com%2Famp%2Fpage"), + content::RenderFrameHostTester::For(web_contents()->GetMainFrame()) + ->AppendChild("subframe")); + + // Navigate the main frame to trigger metrics recording - we expect metrics to + // have been recorded for 1 AMP page (the non-prerendered page). + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/other"), main_rfh()) + ->CommitSameDocument(); + + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.NavigationToInput.Subframe", + 0); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.InputToNavigation.Subframe", + 1); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming." + "MainFrameToSubFrameNavigationDelta.Subframe", + 0); + + // Now navigate to the main-frame URL for the prerendered AMP document. This + // should trigger metrics recording for that document. + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/page2"), main_rfh()) + ->CommitSameDocument(); + + // Navigate the main frame to trigger metrics recording. + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/other"), main_rfh()) + ->CommitSameDocument(); + + // We now expect one NavigationToInput (for the prerender) and one + // InputToNavigation (for the non-prerender). + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.NavigationToInput.Subframe", + 1); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.InputToNavigation.Subframe", + 1); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming." + "MainFrameToSubFrameNavigationDelta.Subframe", + 0); +} + +TEST_F(AMPPageLoadMetricsObserverTest, + SubFrameWithNonSameDocumentMainFrameNavigation) { + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/page"), main_rfh()) + ->Commit(); + + // Load the associated AMP document in an iframe. + NavigationSimulator::NavigateAndCommitFromDocument( + GURL("https://cdn.ampproject.org/page" + "#viewerUrl=https%3A%2F%2Fwww.google.com%2Famp%2Fpage"), + content::RenderFrameHostTester::For(web_contents()->GetMainFrame()) + ->AppendChild("subframe")); + + // Navigate the main frame to trigger metrics recording - we expect metrics to + // have been recorded for 1 AMP page (the non-prerendered page). + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/other"), main_rfh()) + ->CommitSameDocument(); + + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.NavigationToInput.Subframe", + 0); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.InputToNavigation.Subframe", + 0); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming." + "MainFrameToSubFrameNavigationDelta.Subframe", + 1); +} + +TEST_F(AMPPageLoadMetricsObserverTest, + NoSubFrameMetricsForSubFrameWithNonAmpUrl) { + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/search"), main_rfh()) + ->Commit(); + + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/page"), main_rfh()) + ->CommitSameDocument(); + + // Create a non-AMP subframe document. + NavigationSimulator::NavigateAndCommitFromDocument( + GURL("https://example.com/"), + content::RenderFrameHostTester::For(web_contents()->GetMainFrame()) + ->AppendChild("subframe")); + + // Navigate the main frame to trigger metrics recording. + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/other"), main_rfh()) + ->CommitSameDocument(); + + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.NavigationToInput.Subframe", + 0); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.InputToNavigation.Subframe", + 0); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming." + "MainFrameToSubFrameNavigationDelta.Subframe", + 0); +} + +TEST_F(AMPPageLoadMetricsObserverTest, + NoSubFrameMetricsForSubFrameWithoutViewerUrl) { + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/search"), main_rfh()) + ->Commit(); + + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/page"), main_rfh()) + ->CommitSameDocument(); + + NavigationSimulator::NavigateAndCommitFromDocument( + GURL("https://cdn.ampproject.org/page"), + content::RenderFrameHostTester::For(web_contents()->GetMainFrame()) + ->AppendChild("subframe")); + + // Navigate the main frame to trigger metrics recording. + NavigationSimulator::CreateRendererInitiated( + GURL("https://www.google.com/amp/other"), main_rfh()) + ->CommitSameDocument(); + + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.NavigationToInput.Subframe", + 0); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming.InputToNavigation.Subframe", + 0); + histogram_tester().ExpectTotalCount( + "PageLoad.Clients.AMP.Experimental.PageTiming." + "MainFrameToSubFrameNavigationDelta.Subframe", + 0); +}
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_observer.h b/chrome/browser/page_load_metrics/page_load_metrics_observer.h index e9afc6f..86d2b9f 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_observer.h +++ b/chrome/browser/page_load_metrics/page_load_metrics_observer.h
@@ -532,6 +532,8 @@ virtual void FrameSizeChanged(content::RenderFrameHost* render_frame_host, const gfx::Size& frame_size) {} + virtual void OnFrameDeleted(content::RenderFrameHost* render_frame_host) {} + // Called when the event corresponding to |event_key| occurs in this page // load. virtual void OnEventOccurred(const void* const event_key) {}
diff --git a/chrome/browser/page_load_metrics/page_load_tracker.cc b/chrome/browser/page_load_metrics/page_load_tracker.cc index b0c3f4b..a64c199a 100644 --- a/chrome/browser/page_load_metrics/page_load_tracker.cc +++ b/chrome/browser/page_load_metrics/page_load_tracker.cc
@@ -325,6 +325,12 @@ INVOKE_AND_PRUNE_OBSERVERS(observers_, OnShown); } +void PageLoadTracker::FrameDeleted(content::RenderFrameHost* rfh) { + for (const auto& observer : observers_) { + observer->OnFrameDeleted(rfh); + } +} + void PageLoadTracker::WillProcessNavigationResponse( content::NavigationHandle* navigation_handle) { DCHECK(!navigation_request_id_.has_value());
diff --git a/chrome/browser/page_load_metrics/page_load_tracker.h b/chrome/browser/page_load_metrics/page_load_tracker.h index 8290dcd..7c898ed 100644 --- a/chrome/browser/page_load_metrics/page_load_tracker.h +++ b/chrome/browser/page_load_metrics/page_load_tracker.h
@@ -200,6 +200,7 @@ base::TimeTicks failed_load_time); void WebContentsHidden(); void WebContentsShown(); + void FrameDeleted(content::RenderFrameHost* rfh); void OnInputEvent(const blink::WebInputEvent& event);
diff --git a/chrome/browser/profiles/profile_downloader.cc b/chrome/browser/profiles/profile_downloader.cc index 6146898..b400d9e 100644 --- a/chrome/browser/profiles/profile_downloader.cc +++ b/chrome/browser/profiles/profile_downloader.cc
@@ -17,6 +17,7 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" +#include "build/build_config.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_downloader_delegate.h" #include "chrome/browser/profiles/profile_manager.h" @@ -120,10 +121,10 @@ if (maybe_account_info.has_value()) account_info_ = maybe_account_info.value(); - if (delegate_->IsPreSignin()) { - AccountFetcherServiceFactory::GetForProfile(delegate_->GetBrowserProfile()) - ->FetchUserInfoBeforeSignin(account_id_); - } +#if defined(OS_ANDROID) + if (delegate_->IsPreSignin()) + identity_manager_->ForceRefreshOfExtendedAccountInfo(account_id_); +#endif if (account_info_.IsValid()) { // FetchImageData might call the delegate's OnProfileDownloadSuccess
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index a1df4ad8..22dcfe3 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -85,8 +85,6 @@ #include "chrome/browser/sessions/session_service_factory.h" #include "chrome/browser/signin/account_tracker_service_factory.h" #include "chrome/browser/signin/identity_manager_factory.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" -#include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/signin/signin_ui_util.h" #include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h" #include "chrome/browser/ssl/chrome_ssl_host_state_delegate_factory.h" @@ -1255,9 +1253,7 @@ if (service_name == identity::mojom::kServiceName) { return std::make_unique<identity::IdentityService>( IdentityManagerFactory::GetForProfile(this), - AccountTrackerServiceFactory::GetForProfile(this), - ProfileOAuth2TokenServiceFactory::GetForProfile(this), - std::move(request)); + AccountTrackerServiceFactory::GetForProfile(this), std::move(request)); } if (service_name == prefs::mojom::kServiceName) {
diff --git a/chrome/browser/resources/pdf/pdf_viewer.js b/chrome/browser/resources/pdf/pdf_viewer.js index 26b71ba..8051b83d 100644 --- a/chrome/browser/resources/pdf/pdf_viewer.js +++ b/chrome/browser/resources/pdf/pdf_viewer.js
@@ -136,6 +136,12 @@ /** @private {boolean} */ this.hasEnteredAnnotationMode_ = false; + /** @private {boolean} */ + this.hadPassword_ = false; + + /** @private {boolean} */ + this.canSerializeDocument_ = false; + PDFMetrics.record(PDFMetrics.UserAction.DOCUMENT_OPENED); // Parse open pdf parameters. @@ -1074,6 +1080,8 @@ // If the password screen isn't up, put it up. Otherwise we're // responding to an incorrect password so deny it. if (!this.passwordScreen_.active) { + this.hadPassword_ = true; + this.updateAnnotationAvailable_(); this.passwordScreen_.show(); } else { this.passwordScreen_.deny(); @@ -1119,8 +1127,9 @@ * Sets document metadata from the current controller. * @param {string} title * @param {Array} bookmarks + * @param {boolean} canSerializeDocument */ - setDocumentMetadata: function(title, bookmarks) { + setDocumentMetadata: function(title, bookmarks, canSerializeDocument) { if (title) { document.title = title; } else { @@ -1131,6 +1140,8 @@ this.toolbar_.docTitle = document.title; this.toolbar_.bookmarks = this.bookmarks; } + this.canSerializeDocument_ = canSerializeDocument; + this.updateAnnotationAvailable_(); }, /** @@ -1227,6 +1238,12 @@ if (this.viewport_.getClockwiseRotations() != 0) { annotationAvailable = false; } + if (this.hadPassword_) { + annotationAvailable = false; + } + if (!this.canSerializeDocument_) { + annotationAvailable = false; + } this.toolbar_.annotationAvailable = annotationAvailable; }, @@ -1563,7 +1580,8 @@ break; case 'metadata': this.viewer_.setDocumentMetadata( - message.data.title, message.data.bookmarks); + message.data.title, message.data.bookmarks, + message.data.canSerializeDocument); break; case 'setIsSelecting': this.viewer_.setIsSelecting(message.data.isSelecting);
diff --git a/chrome/browser/security_events/BUILD.gn b/chrome/browser/security_events/BUILD.gn new file mode 100644 index 0000000..924a1db --- /dev/null +++ b/chrome/browser/security_events/BUILD.gn
@@ -0,0 +1,19 @@ +# Copyright 2019 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. + +static_library("security_events") { + sources = [ + "security_event_recorder.h", + "security_event_recorder_impl.cc", + "security_event_recorder_impl.h", + "security_event_sync_bridge.h", + "security_event_sync_bridge_impl.cc", + "security_event_sync_bridge_impl.h", + ] + + deps = [ + "//components/keyed_service/core", + "//components/sync", + ] +}
diff --git a/chrome/browser/security_events/OWNERS b/chrome/browser/security_events/OWNERS new file mode 100644 index 0000000..13cac5a6 --- /dev/null +++ b/chrome/browser/security_events/OWNERS
@@ -0,0 +1,7 @@ +# For Safebrowsing related reviews +vakh@chromium.org +# For Chrome Sync related reviews +markusheintz@chromium.org + +# COMPONENT: Services>Safebrowsing +
diff --git a/chrome/browser/security_events/README.md b/chrome/browser/security_events/README.md new file mode 100644 index 0000000..3ab93ed --- /dev/null +++ b/chrome/browser/security_events/README.md
@@ -0,0 +1,6 @@ +# Security Event Recorder + +The security event recorder is a service for recording security related events. +Security events are recorded for signed in users and are used to determine the +threat level for a user account. +
diff --git a/chrome/browser/security_events/security_event_recorder.h b/chrome/browser/security_events/security_event_recorder.h new file mode 100644 index 0000000..de9411e --- /dev/null +++ b/chrome/browser/security_events/security_event_recorder.h
@@ -0,0 +1,34 @@ +// Copyright 2019 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_SECURITY_EVENTS_SECURITY_EVENT_RECORDER_H_ +#define CHROME_BROWSER_SECURITY_EVENTS_SECURITY_EVENT_RECORDER_H_ + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "components/keyed_service/core/keyed_service.h" +#include "components/sync/model/model_type_controller_delegate.h" +#include "components/sync/protocol/sync.pb.h" + +// The SecurityEventRecorder class allows to record security events via Chrome +// Sync for signed-in users. +class SecurityEventRecorder : public KeyedService { + public: + SecurityEventRecorder() = default; + ~SecurityEventRecorder() override = default; + + // Records the GaiaPasswordReuse security event for the currently signed-in + // user. The event is recorded via Chrome Sync. + virtual void RecordGaiaPasswordReuse( + const sync_pb::GaiaPasswordReuse& event) = 0; + + // Returns the underlying Sync integration point. + virtual base::WeakPtr<syncer::ModelTypeControllerDelegate> + GetControllerDelegate() = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(SecurityEventRecorder); +}; + +#endif // CHROME_BROWSER_SECURITY_EVENTS_SECURITY_EVENT_RECORDER_H_
diff --git a/chrome/browser/security_events/security_event_recorder_impl.cc b/chrome/browser/security_events/security_event_recorder_impl.cc new file mode 100644 index 0000000..31e9a58 --- /dev/null +++ b/chrome/browser/security_events/security_event_recorder_impl.cc
@@ -0,0 +1,42 @@ +// Copyright 2019 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/security_events/security_event_recorder_impl.h" + +#include <memory> +#include <utility> + +using sync_pb::SecurityEventSpecifics; + +SecurityEventRecorderImpl::SecurityEventRecorderImpl( + std::unique_ptr<SecurityEventSyncBridge> security_event_sync_bridge, + base::Clock* clock) + : security_event_sync_bridge_(std::move(security_event_sync_bridge)), + clock_(clock) { + DCHECK(security_event_sync_bridge_); + DCHECK(clock_); +} + +SecurityEventRecorderImpl::~SecurityEventRecorderImpl() {} + +void SecurityEventRecorderImpl::RecordGaiaPasswordReuse( + const sync_pb::GaiaPasswordReuse& event) { + sync_pb::SecurityEventSpecifics specifics; + specifics.set_event_time_usec(clock_->Now().since_origin().InMicroseconds()); + sync_pb::GaiaPasswordReuse* gaia_password_reuse_event = + specifics.mutable_gaia_password_reuse_event(); + gaia_password_reuse_event->CopyFrom(event); + + security_event_sync_bridge_->RecordSecurityEvent(std::move(specifics)); +} + +base::WeakPtr<syncer::ModelTypeControllerDelegate> +SecurityEventRecorderImpl::GetControllerDelegate() { + if (security_event_sync_bridge_) { + return security_event_sync_bridge_->GetControllerDelegate(); + } + return base::WeakPtr<syncer::ModelTypeControllerDelegate>(); +} + +void SecurityEventRecorderImpl::Shutdown() {}
diff --git a/chrome/browser/security_events/security_event_recorder_impl.h b/chrome/browser/security_events/security_event_recorder_impl.h new file mode 100644 index 0000000..c3e79ee --- /dev/null +++ b/chrome/browser/security_events/security_event_recorder_impl.h
@@ -0,0 +1,40 @@ +// Copyright 2019 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_SECURITY_EVENTS_SECURITY_EVENT_RECORDER_IMPL_H_ +#define CHROME_BROWSER_SECURITY_EVENTS_SECURITY_EVENT_RECORDER_IMPL_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "base/macros.h" +#include "base/time/clock.h" +#include "chrome/browser/security_events/security_event_recorder.h" +#include "chrome/browser/security_events/security_event_sync_bridge.h" + +class SecurityEventRecorderImpl : public SecurityEventRecorder { + public: + SecurityEventRecorderImpl( + std::unique_ptr<SecurityEventSyncBridge> security_event_sync_bridge, + base::Clock* clock); + ~SecurityEventRecorderImpl() override; + + void RecordGaiaPasswordReuse( + const sync_pb::GaiaPasswordReuse& event) override; + + base::WeakPtr<syncer::ModelTypeControllerDelegate> GetControllerDelegate() + override; + + // KeyedService (through SecurityEventRecorder) implementation. + void Shutdown() override; + + private: + std::unique_ptr<SecurityEventSyncBridge> security_event_sync_bridge_; + base::Clock* clock_; + + DISALLOW_COPY_AND_ASSIGN(SecurityEventRecorderImpl); +}; + +#endif // CHROME_BROWSER_SECURITY_EVENTS_SECURITY_EVENT_RECORDER_IMPL_H_
diff --git a/chrome/browser/security_events/security_event_sync_bridge.h b/chrome/browser/security_events/security_event_sync_bridge.h new file mode 100644 index 0000000..5a01860 --- /dev/null +++ b/chrome/browser/security_events/security_event_sync_bridge.h
@@ -0,0 +1,30 @@ +// Copyright 2019 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_SECURITY_EVENTS_SECURITY_EVENT_SYNC_BRIDGE_H_ +#define CHROME_BROWSER_SECURITY_EVENTS_SECURITY_EVENT_SYNC_BRIDGE_H_ + +#include <memory> + +#include "base/memory/weak_ptr.h" +#include "components/sync/model/model_type_controller_delegate.h" +#include "components/sync/protocol/sync.pb.h" + +class SecurityEventSyncBridge { + public: + SecurityEventSyncBridge() = default; + virtual ~SecurityEventSyncBridge() = default; + + virtual void RecordSecurityEvent( + sync_pb::SecurityEventSpecifics specifics) = 0; + + // Returns the delegate for the controller, i.e. sync integration point. + virtual base::WeakPtr<syncer::ModelTypeControllerDelegate> + GetControllerDelegate() = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(SecurityEventSyncBridge); +}; + +#endif // CHROME_BROWSER_SECURITY_EVENTS_SECURITY_EVENT_SYNC_BRIDGE_H_
diff --git a/chrome/browser/security_events/security_event_sync_bridge_impl.cc b/chrome/browser/security_events/security_event_sync_bridge_impl.cc new file mode 100644 index 0000000..26fbfa1e --- /dev/null +++ b/chrome/browser/security_events/security_event_sync_bridge_impl.cc
@@ -0,0 +1,218 @@ +// Copyright 2019 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/security_events/security_event_sync_bridge_impl.h" + +#include <set> +#include <utility> +#include <vector> + +#include "base/big_endian.h" +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/strings/string_number_conversions.h" +#include "build/build_config.h" +#include "components/sync/model/entity_change.h" +#include "components/sync/model/metadata_batch.h" +#include "components/sync/model/mutable_data_batch.h" + +namespace { + +std::string GetStorageKeyFromSpecifics( + const sync_pb::SecurityEventSpecifics& specifics) { + // Force Big Endian, this means newly created keys are last in sort order, + // which allows leveldb to append new writes, which it is best at. + // TODO(markusheintz): Until we force |event_time_usec| to never conflict, + // this has the potential for errors. + std::string key(8, 0); + base::WriteBigEndian(&key[0], specifics.event_time_usec()); + return key; +} + +std::unique_ptr<syncer::EntityData> ToEntityData( + sync_pb::SecurityEventSpecifics specifics) { + auto entity_data = std::make_unique<syncer::EntityData>(); + entity_data->non_unique_name = + base::NumberToString(specifics.event_time_usec()); + entity_data->specifics.set_allocated_security_event(&specifics); + return entity_data; +} + +} // namespace + +SecurityEventSyncBridgeImpl::SecurityEventSyncBridgeImpl( + syncer::OnceModelTypeStoreFactory store_factory, + std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor) + : syncer::ModelTypeSyncBridge(std::move(change_processor)), + weak_ptr_factory_(this) { + std::move(store_factory) + .Run(syncer::SECURITY_EVENTS, + base::BindOnce(&SecurityEventSyncBridgeImpl::OnStoreCreated, + weak_ptr_factory_.GetWeakPtr())); +} + +SecurityEventSyncBridgeImpl::~SecurityEventSyncBridgeImpl() {} + +void SecurityEventSyncBridgeImpl::RecordSecurityEvent( + sync_pb::SecurityEventSpecifics specifics) { + if (!store_) { + return; + } + if (!change_processor()->IsTrackingMetadata()) { + return; + } + + std::string storage_key = GetStorageKeyFromSpecifics(specifics); + + std::unique_ptr<syncer::ModelTypeStore::WriteBatch> write_batch = + store_->CreateWriteBatch(); + write_batch->WriteData(storage_key, specifics.SerializeAsString()); + + change_processor()->Put(storage_key, ToEntityData(std::move(specifics)), + write_batch->GetMetadataChangeList()); + + store_->CommitWriteBatch( + std::move(write_batch), + base::BindOnce(&SecurityEventSyncBridgeImpl::OnCommit, + weak_ptr_factory_.GetWeakPtr())); +} + +base::WeakPtr<syncer::ModelTypeControllerDelegate> +SecurityEventSyncBridgeImpl::GetControllerDelegate() { + return change_processor()->GetControllerDelegate(); +} + +std::unique_ptr<syncer::MetadataChangeList> +SecurityEventSyncBridgeImpl::CreateMetadataChangeList() { + return syncer::ModelTypeStore::WriteBatch::CreateMetadataChangeList(); +} + +base::Optional<syncer::ModelError> SecurityEventSyncBridgeImpl::MergeSyncData( + std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, + syncer::EntityChangeList entity_data) { + DCHECK(entity_data.empty()); + DCHECK(change_processor()->IsTrackingMetadata()); + DCHECK(!change_processor()->TrackedAccountId().empty()); + return ApplySyncChanges(std::move(metadata_change_list), + std::move(entity_data)); +} + +base::Optional<syncer::ModelError> +SecurityEventSyncBridgeImpl::ApplySyncChanges( + std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, + syncer::EntityChangeList entity_changes) { + std::unique_ptr<syncer::ModelTypeStore::WriteBatch> write_batch = + store_->CreateWriteBatch(); + for (syncer::EntityChange& change : entity_changes) { + DCHECK_EQ(syncer::EntityChange::ACTION_DELETE, change.type()); + write_batch->DeleteData(change.storage_key()); + } + + write_batch->TakeMetadataChangesFrom(std::move(metadata_change_list)); + store_->CommitWriteBatch( + std::move(write_batch), + base::BindOnce(&SecurityEventSyncBridgeImpl::OnCommit, + weak_ptr_factory_.GetWeakPtr())); + return {}; +} + +void SecurityEventSyncBridgeImpl::GetData(StorageKeyList storage_keys, + DataCallback callback) { + store_->ReadData( + storage_keys, + base::BindOnce(&SecurityEventSyncBridgeImpl::OnReadData, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); +} + +void SecurityEventSyncBridgeImpl::GetAllDataForDebugging( + DataCallback callback) { + store_->ReadAllData( + base::BindOnce(&SecurityEventSyncBridgeImpl::OnReadAllData, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); +} + +std::string SecurityEventSyncBridgeImpl::GetClientTag( + const syncer::EntityData& entity_data) { + return GetStorageKey(entity_data); +} + +std::string SecurityEventSyncBridgeImpl::GetStorageKey( + const syncer::EntityData& entity_data) { + return GetStorageKeyFromSpecifics(entity_data.specifics.security_event()); +} + +void SecurityEventSyncBridgeImpl::ApplyStopSyncChanges( + std::unique_ptr<syncer::MetadataChangeList> delete_metadata_change_list) { + if (delete_metadata_change_list) { + store_->DeleteAllDataAndMetadata( + base::BindOnce(&SecurityEventSyncBridgeImpl::OnCommit, + weak_ptr_factory_.GetWeakPtr())); + } +} + +void SecurityEventSyncBridgeImpl::OnStoreCreated( + const base::Optional<syncer::ModelError>& error, + std::unique_ptr<syncer::ModelTypeStore> store) { + if (error) { + change_processor()->ReportError(*error); + return; + } + + store_ = std::move(store); + store_->ReadAllMetadata( + base::BindOnce(&SecurityEventSyncBridgeImpl::OnReadAllMetadata, + weak_ptr_factory_.GetWeakPtr())); +} + +void SecurityEventSyncBridgeImpl::OnReadData( + DataCallback callback, + const base::Optional<syncer::ModelError>& error, + std::unique_ptr<syncer::ModelTypeStore::RecordList> data_records, + std::unique_ptr<syncer::ModelTypeStore::IdList> missing_id_list) { + OnReadAllData(std::move(callback), error, std::move(data_records)); +} + +void SecurityEventSyncBridgeImpl::OnReadAllData( + DataCallback callback, + const base::Optional<syncer::ModelError>& error, + std::unique_ptr<syncer::ModelTypeStore::RecordList> data_records) { + if (error) { + change_processor()->ReportError(*error); + return; + } + + auto batch = std::make_unique<syncer::MutableDataBatch>(); + for (const syncer::ModelTypeStore::Record& r : *data_records) { + sync_pb::SecurityEventSpecifics specifics; + + if (specifics.ParseFromString(r.value)) { + DCHECK_EQ(r.id, GetStorageKeyFromSpecifics(specifics)); + batch->Put(r.id, ToEntityData(std::move(specifics))); + } else { + change_processor()->ReportError( + {FROM_HERE, "Failed deserializing security events."}); + return; + } + } + std::move(callback).Run(std::move(batch)); +} + +void SecurityEventSyncBridgeImpl::OnReadAllMetadata( + const base::Optional<syncer::ModelError>& error, + std::unique_ptr<syncer::MetadataBatch> metadata_batch) { + if (error) { + change_processor()->ReportError(*error); + } else { + change_processor()->ModelReadyToSync(std::move(metadata_batch)); + } +} + +void SecurityEventSyncBridgeImpl::OnCommit( + const base::Optional<syncer::ModelError>& error) { + if (error) { + change_processor()->ReportError(*error); + } +}
diff --git a/chrome/browser/security_events/security_event_sync_bridge_impl.h b/chrome/browser/security_events/security_event_sync_bridge_impl.h new file mode 100644 index 0000000..8708b143 --- /dev/null +++ b/chrome/browser/security_events/security_event_sync_bridge_impl.h
@@ -0,0 +1,76 @@ +// Copyright 2019 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_SECURITY_EVENTS_SECURITY_EVENT_SYNC_BRIDGE_IMPL_H_ +#define CHROME_BROWSER_SECURITY_EVENTS_SECURITY_EVENT_SYNC_BRIDGE_IMPL_H_ + +#include <memory> +#include <string> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/optional.h" +#include "chrome/browser/security_events/security_event_sync_bridge.h" +#include "components/sync/model/model_type_change_processor.h" +#include "components/sync/model/model_type_store.h" +#include "components/sync/model/model_type_sync_bridge.h" +#include "components/sync/protocol/sync.pb.h" + +class SecurityEventSyncBridgeImpl : public SecurityEventSyncBridge, + public syncer::ModelTypeSyncBridge { + public: + SecurityEventSyncBridgeImpl( + syncer::OnceModelTypeStoreFactory store_factory, + std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor); + ~SecurityEventSyncBridgeImpl() override; + + void RecordSecurityEvent(sync_pb::SecurityEventSpecifics specifics) override; + + base::WeakPtr<syncer::ModelTypeControllerDelegate> GetControllerDelegate() + override; + + // ModelTypeSyncBridge implementation. + std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList() + override; + base::Optional<syncer::ModelError> MergeSyncData( + std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, + syncer::EntityChangeList entity_data) override; + base::Optional<syncer::ModelError> ApplySyncChanges( + std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, + syncer::EntityChangeList entity_changes) override; + void GetData(StorageKeyList storage_keys, DataCallback callback) override; + void GetAllDataForDebugging(DataCallback callback) override; + std::string GetClientTag(const syncer::EntityData& entity_data) override; + std::string GetStorageKey(const syncer::EntityData& entity_data) override; + void ApplyStopSyncChanges(std::unique_ptr<syncer::MetadataChangeList> + delete_metadata_change_list) override; + + private: + void OnStoreCreated(const base::Optional<syncer::ModelError>& error, + std::unique_ptr<syncer::ModelTypeStore> store); + + void OnReadData( + DataCallback callback, + const base::Optional<syncer::ModelError>& error, + std::unique_ptr<syncer::ModelTypeStore::RecordList> data_records, + std::unique_ptr<syncer::ModelTypeStore::IdList> missing_id_list); + + void OnReadAllData( + DataCallback callback, + const base::Optional<syncer::ModelError>& error, + std::unique_ptr<syncer::ModelTypeStore::RecordList> data_records); + + void OnReadAllMetadata(const base::Optional<syncer::ModelError>& error, + std::unique_ptr<syncer::MetadataBatch> metadata_batch); + + void OnCommit(const base::Optional<syncer::ModelError>& error); + + std::unique_ptr<syncer::ModelTypeStore> store_; + + base::WeakPtrFactory<SecurityEventSyncBridgeImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(SecurityEventSyncBridgeImpl); +}; + +#endif // CHROME_BROWSER_SECURITY_EVENTS_SECURITY_EVENT_SYNC_BRIDGE_IMPL_H_
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc index 22ee0f5..84a82ce 100644 --- a/chrome/browser/signin/chrome_signin_client.cc +++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -303,7 +303,8 @@ void ChromeSigninClient::VerifySyncToken() { #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) - if (signin_util::IsForceSigninEnabled()) + // We only verifiy the token once when Profile is just created. + if (signin_util::IsForceSigninEnabled() && !force_signin_verifier_) force_signin_verifier_ = std::make_unique<ForceSigninVerifier>(profile_); #endif }
diff --git a/chrome/browser/signin/chrome_signin_helper.cc b/chrome/browser/signin/chrome_signin_helper.cc index 8af64b9a..496c28c6 100644 --- a/chrome/browser/signin/chrome_signin_helper.cc +++ b/chrome/browser/signin/chrome_signin_helper.cc
@@ -51,6 +51,7 @@ #if defined(OS_ANDROID) #include "chrome/browser/android/signin/account_management_screen_helper.h" +#include "ui/android/view_android.h" #else #include "chrome/browser/ui/browser_commands.h" #include "extensions/browser/guest_view/web_view/web_view_renderer_state.h" @@ -235,7 +236,8 @@ } else { signin_metrics::LogAccountReconcilorStateOnGaiaResponse( account_reconcilor->GetState()); - AccountManagementScreenHelper::OpenAccountManagementScreen(profile, + auto* window = web_contents->GetNativeView()->GetWindowAndroid(); + AccountManagementScreenHelper::OpenAccountManagementScreen(window, service_type); } #endif // defined(OS_CHROMEOS)
diff --git a/chrome/browser/sync/sync_ui_util.cc b/chrome/browser/sync/sync_ui_util.cc index 51872bf..978acbda 100644 --- a/chrome/browser/sync/sync_ui_util.cc +++ b/chrome/browser/sync/sync_ui_util.cc
@@ -33,8 +33,7 @@ // User is signed in, but sync is disabled. return l10n_util::GetStringUTF16(IDS_SIGNED_IN_WITH_SYNC_DISABLED); } - if (service->HasDisableReason( - syncer::SyncService::DISABLE_REASON_USER_CHOICE)) { + if (!service->GetUserSettings()->IsSyncRequested()) { // User is signed in, but sync has been stopped. return l10n_util::GetStringUTF16(IDS_SIGNED_IN_WITH_SYNC_SUPPRESSED); } @@ -49,26 +48,34 @@ : IDS_SYNC_ACCOUNT_SYNCING_CUSTOM_DATA_TYPES); } -void GetStatusForActionableError(syncer::ClientAction action, +// Returns whether there is a non-empty status for the given |action|. +bool GetStatusForActionableError(syncer::ClientAction action, base::string16* status_label, base::string16* link_label, ActionType* action_type) { - DCHECK(status_label); - DCHECK(link_label); + DCHECK(action_type); switch (action) { case syncer::UPGRADE_CLIENT: - *status_label = l10n_util::GetStringUTF16(IDS_SYNC_UPGRADE_CLIENT); - *link_label = - l10n_util::GetStringUTF16(IDS_SYNC_UPGRADE_CLIENT_LINK_LABEL); + if (status_label) { + *status_label = l10n_util::GetStringUTF16(IDS_SYNC_UPGRADE_CLIENT); + } + if (link_label) { + *link_label = + l10n_util::GetStringUTF16(IDS_SYNC_UPGRADE_CLIENT_LINK_LABEL); + } *action_type = UPGRADE_CLIENT; - break; + return true; case syncer::ENABLE_SYNC_ON_ACCOUNT: - *status_label = - l10n_util::GetStringUTF16(IDS_SYNC_STATUS_ENABLE_SYNC_ON_ACCOUNT); - break; + if (status_label) { + *status_label = + l10n_util::GetStringUTF16(IDS_SYNC_STATUS_ENABLE_SYNC_ON_ACCOUNT); + } + return true; default: - *status_label = base::string16(); - break; + if (status_label) { + *status_label = base::string16(); + } + return false; } } @@ -80,8 +87,8 @@ // Unrecoverable error is sometimes accompanied by actionable error. // If status message is set display that message, otherwise show generic // unrecoverable error message. - GetStatusForActionableError(action, status_label, link_label, action_type); - if (status_label->empty()) { + if (!GetStatusForActionableError(action, status_label, link_label, + action_type)) { *action_type = REAUTHENTICATE; *link_label = l10n_util::GetStringUTF16(IDS_SYNC_RELOGIN_LINK_LABEL); @@ -148,6 +155,10 @@ return PRE_SYNCED; } + // If local Sync were enabled, then the SyncService shouldn't report having a + // primary (or any) account. + DCHECK(!service->IsLocalSyncEnabled()); + syncer::SyncStatus status; service->QueryDetailedSyncStatus(&status); @@ -164,10 +175,9 @@ // TODO(crbug.com/911153): What's the intended meaning of this condition? // Should other disable reasons also be checked? if (service->GetUserSettings()->IsFirstSetupComplete() || + !service->GetUserSettings()->IsSyncRequested() || service->HasDisableReason( - syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY) || - service->HasDisableReason( - syncer::SyncService::DISABLE_REASON_USER_CHOICE)) { + syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY)) { // The order or priority is going to be: // 1. Auth errors. 2. Actionable protocol errors. 3. Passphrase errors. @@ -181,14 +191,9 @@ } // We don't have an auth error. Check for an actionable protocol error. - // TODO(crbug.com/911153): Here the behavior (returned value) depends on - // whether the |status_label| param is null. That seems like a bug. - if (status_label && link_label) { - GetStatusForActionableError(status.sync_protocol_error.action, - status_label, link_label, action_type); - if (!status_label->empty()) { - return SYNC_ERROR; - } + if (GetStatusForActionableError(status.sync_protocol_error.action, + status_label, link_label, action_type)) { + return SYNC_ERROR; } // Check for a passphrase error. @@ -209,8 +214,7 @@ // Check to see if sync has been disabled via the dasboard and needs to be // set up once again. - if (service->HasDisableReason( - syncer::SyncService::DISABLE_REASON_USER_CHOICE) && + if (!service->GetUserSettings()->IsSyncRequested() && status.sync_protocol_error.error_type == syncer::NOT_MY_BIRTHDAY) { return PRE_SYNCED; } @@ -236,27 +240,16 @@ return PRE_SYNCED; } - if (ShouldRequestSyncConfirmation(service)) { - if (status_label && link_label) { - *status_label = - l10n_util::GetStringUTF16(IDS_SYNC_SETTINGS_NOT_CONFIRMED); - *link_label = l10n_util::GetStringUTF16( - IDS_SYNC_ERROR_USER_MENU_CONFIRM_SYNC_SETTINGS_BUTTON); - } - *action_type = CONFIRM_SYNC_SETTINGS; - return SYNC_ERROR; + // At this point we've ruled out all other cases - all that's left is a + // missing Sync confirmation. + DCHECK(ShouldRequestSyncConfirmation(service)); + if (status_label && link_label) { + *status_label = l10n_util::GetStringUTF16(IDS_SYNC_SETTINGS_NOT_CONFIRMED); + *link_label = l10n_util::GetStringUTF16( + IDS_SYNC_ERROR_USER_MENU_CONFIRM_SYNC_SETTINGS_BUTTON); } - - // TODO(crbug.com/906995): This code is only reachable if IsLocalSyncEnabled() - // is true. That should probably be handled more explicitly, and anyway this - // doesn't seem like an appropriate message for that case. - // The user is signed in, but sync has been stopped. - if (status_label) { - *status_label = - l10n_util::GetStringUTF16(IDS_SIGNED_IN_WITH_SYNC_SUPPRESSED); - } - - return PRE_SYNCED; + *action_type = CONFIRM_SYNC_SETTINGS; + return SYNC_ERROR; } } // namespace
diff --git a/chrome/browser/sync/test/integration/enable_disable_test.cc b/chrome/browser/sync/test/integration/enable_disable_test.cc index 6c0c500a..46c20484 100644 --- a/chrome/browser/sync/test/integration/enable_disable_test.cc +++ b/chrome/browser/sync/test/integration/enable_disable_test.cc
@@ -396,15 +396,28 @@ // exact count. ASSERT_GT(GetNumUpdatesDownloadedInLastCycle(), 0); - // Stop and restart Sync. + // Stop Sync and let it start up again in standalone transport mode. GetClient(0)->StopSyncServiceWithoutClearingData(); + ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive()); + ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE, + GetSyncService(0)->GetTransportState()); + ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureActive()); + + // Now start full Sync again. + base::HistogramTester histogram_tester; GetClient(0)->StartSyncService(); ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureActive()); // The bookmark should still be there, *without* having been redownloaded. + ASSERT_TRUE(SetupSync()); ASSERT_TRUE(bookmarks_helper::GetBookmarkModel(0)->IsBookmarked( GURL(kSyncedBookmarkURL))); - EXPECT_EQ(0, GetNumUpdatesDownloadedInLastCycle()); + EXPECT_EQ( + 0, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.BOOKMARK", + /*REMOTE_NON_INITIAL_UPDATE=*/4)); + EXPECT_EQ( + 0, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.BOOKMARK", + /*REMOTE_INITIAL_UPDATE=*/5)); } IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, ClearsPrefsIfClearData) { @@ -456,57 +469,4 @@ EXPECT_EQ(kTestServerChips, message.bag_of_chips().server_chips()); } -class EnableDisableSingleClientWithStandaloneTransportTest - : public EnableDisableSingleClientTest { - public: - EnableDisableSingleClientWithStandaloneTransportTest() { - features_.InitAndEnableFeature(switches::kSyncStandaloneTransport); - } - - private: - base::test::ScopedFeatureList features_; -}; - -IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientWithStandaloneTransportTest, - DoesNotRedownloadAfterKeepDataWithStandaloneTransport) { - ASSERT_TRUE(SetupClients()); - ASSERT_FALSE(bookmarks_helper::GetBookmarkModel(0)->IsBookmarked( - GURL(kSyncedBookmarkURL))); - - // Create a bookmark on the server, then turn on Sync on the client. - InjectSyncedBookmark(); - ASSERT_TRUE(GetClient(0)->SetupSync()); - ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureActive()); - - // Make sure the bookmark got synced down. - ASSERT_TRUE(bookmarks_helper::GetBookmarkModel(0)->IsBookmarked( - GURL(kSyncedBookmarkURL))); - // Note: The response may also contain permanent nodes, so we can't check the - // exact count. - ASSERT_GT(GetNumUpdatesDownloadedInLastCycle(), 0); - - // Stop Sync and let it start up again in standalone transport mode. - GetClient(0)->StopSyncServiceWithoutClearingData(); - ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive()); - ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE, - GetSyncService(0)->GetTransportState()); - ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureActive()); - - // Now start full Sync again. - base::HistogramTester histogram_tester; - GetClient(0)->StartSyncService(); - ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureActive()); - - // The bookmark should still be there, *without* having been redownloaded. - ASSERT_TRUE(SetupSync()); - ASSERT_TRUE(bookmarks_helper::GetBookmarkModel(0)->IsBookmarked( - GURL(kSyncedBookmarkURL))); - EXPECT_EQ( - 0, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.BOOKMARK", - /*REMOTE_NON_INITIAL_UPDATE=*/4)); - EXPECT_EQ( - 0, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.BOOKMARK", - /*REMOTE_INITIAL_UPDATE=*/5)); -} - } // namespace
diff --git a/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc b/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc index 0059c984..5d3faa29 100644 --- a/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc
@@ -30,10 +30,7 @@ class SingleClientSecondaryAccountSyncTest : public SyncTest { public: SingleClientSecondaryAccountSyncTest() : SyncTest(SINGLE_CLIENT) { - features_.InitWithFeatures( - /*enabled_features=*/{switches::kSyncStandaloneTransport, - switches::kSyncSupportSecondaryAccount}, - /*disabled_features=*/{}); + features_.InitAndEnableFeature(switches::kSyncSupportSecondaryAccount); } ~SingleClientSecondaryAccountSyncTest() override {} @@ -60,30 +57,6 @@ DISALLOW_COPY_AND_ASSIGN(SingleClientSecondaryAccountSyncTest); }; -class SingleClientSecondaryAccountWithoutStandaloneTransportSyncTest - : public SingleClientSecondaryAccountSyncTest { - public: - SingleClientSecondaryAccountWithoutStandaloneTransportSyncTest() { - features_.InitAndDisableFeature(switches::kSyncStandaloneTransport); - } - - private: - base::test::ScopedFeatureList features_; -}; - -IN_PROC_BROWSER_TEST_F( - SingleClientSecondaryAccountWithoutStandaloneTransportSyncTest, - DoesNotStartSyncWithStandaloneTransportDisabled) { - ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; - - // Since standalone transport is disabled, just signing in (without making the - // account Chrome's primary one) should *not* start the Sync machinery. - secondary_account_helper::SignInSecondaryAccount( - profile(), &test_url_loader_factory_, "user@email.com"); - EXPECT_EQ(syncer::SyncService::TransportState::DISABLED, - GetSyncService(0)->GetTransportState()); -} - class SingleClientSecondaryAccountWithoutSecondaryAccountSupportSyncTest : public SingleClientSecondaryAccountSyncTest { public:
diff --git a/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc b/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc index dd8baab8..4553e441 100644 --- a/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc
@@ -42,39 +42,13 @@ class SingleClientStandaloneTransportSyncTest : public SyncTest { public: - SingleClientStandaloneTransportSyncTest() : SyncTest(SINGLE_CLIENT) { - features_.InitAndEnableFeature(switches::kSyncStandaloneTransport); - } + SingleClientStandaloneTransportSyncTest() : SyncTest(SINGLE_CLIENT) {} ~SingleClientStandaloneTransportSyncTest() override {} private: - base::test::ScopedFeatureList features_; - DISALLOW_COPY_AND_ASSIGN(SingleClientStandaloneTransportSyncTest); }; -class SingleClientStandaloneTransportFeatureDisabledSyncTest : public SyncTest { - public: - SingleClientStandaloneTransportFeatureDisabledSyncTest() - : SyncTest(SINGLE_CLIENT) { - features_.InitAndDisableFeature(switches::kSyncStandaloneTransport); - } - - private: - base::test::ScopedFeatureList features_; -}; - -IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportFeatureDisabledSyncTest, - DoesNotStartSyncWithFeatureDisabled) { - ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; - - // Since standalone transport is disabled, signing in should *not* start the - // Sync machinery. - ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount()); - EXPECT_EQ(syncer::SyncService::TransportState::WAITING_FOR_START_REQUEST, - GetSyncService(0)->GetTransportState()); -} - #if defined(OS_CHROMEOS) || defined(OS_ANDROID) IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportSyncTest, StartsSyncFeatureOnSignin) {
diff --git a/chrome/browser/sync/test/integration/single_client_user_consents_sync_test.cc b/chrome/browser/sync/test/integration/single_client_user_consents_sync_test.cc index 45d86bd..4ff01a0d 100644 --- a/chrome/browser/sync/test/integration/single_client_user_consents_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_user_consents_sync_test.cc
@@ -186,21 +186,10 @@ EXPECT_TRUE(ExpectUserConsents({specifics1, specifics2})); } -class SingleClientUserConsentsWithStandaloneTransportSyncTest - : public SingleClientUserConsentsSyncTest { - public: - SingleClientUserConsentsWithStandaloneTransportSyncTest() { - features_.InitAndEnableFeature(switches::kSyncStandaloneTransport); - } - - private: - base::test::ScopedFeatureList features_; -}; - // ChromeOS does not support late signin after profile creation, so the test // below does not apply, at least in the current form. #if !defined(OS_CHROMEOS) -IN_PROC_BROWSER_TEST_F(SingleClientUserConsentsWithStandaloneTransportSyncTest, +IN_PROC_BROWSER_TEST_F(SingleClientUserConsentsSyncTest, ShouldSubmitIfSignedInAlthoughFullSyncNotEnabled) { // We avoid calling SetupSync(), because we don't want to turn on full sync, // only sign in such that the standalone transport starts.
diff --git a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc index 491f6d3..fc6a58f 100644 --- a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
@@ -312,8 +312,7 @@ public: SingleClientWalletWithAccountStorageSyncTest() { InitWithFeatures( - /*enabled_features=*/{switches::kSyncStandaloneTransport, - switches::kSyncUSSAutofillWalletData, + /*enabled_features=*/{switches::kSyncUSSAutofillWalletData, autofill::features:: kAutofillEnableAccountWalletStorage}, /*disabled_features=*/{}); @@ -1092,8 +1091,7 @@ public: SingleClientWalletSecondaryAccountSyncTest() { InitWithFeatures( - /*enabled_features=*/{switches::kSyncStandaloneTransport, - switches::kSyncSupportSecondaryAccount, + /*enabled_features=*/{switches::kSyncSupportSecondaryAccount, switches::kSyncUSSAutofillWalletData, autofill::features:: kAutofillEnableAccountWalletStorage},
diff --git a/chrome/browser/ui/webui/certificate_viewer_webui.cc b/chrome/browser/ui/webui/certificate_viewer_webui.cc index d0ece31..923fa172 100644 --- a/chrome/browser/ui/webui/certificate_viewer_webui.cc +++ b/chrome/browser/ui/webui/certificate_viewer_webui.cc
@@ -15,6 +15,7 @@ #include "base/memory/ptr_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/certificate_viewer.h" @@ -204,14 +205,7 @@ // Certificate usage. std::vector<std::string> usages; x509_certificate_model::GetUsageStrings(cert_hnd, &usages); - std::string usagestr; - for (auto it = usages.begin(); it != usages.end(); ++it) { - if (usagestr.length() > 0) { - usagestr += "\n"; - } - usagestr += *it; - } - cert_info.SetString("general.usages", usagestr); + cert_info.SetString("general.usages", base::JoinString(usages, "\n")); // Standard certificate details. const std::string alternative_text = @@ -260,25 +254,24 @@ x509_certificate_model::HashCertSHA1(cert_hnd)); // Certificate hierarchy is constructed from bottom up. - std::unique_ptr<base::ListValue> children; + base::Value children; int index = 0; - for (auto i = nss_certs_.begin(); i != nss_certs_.end(); ++i, ++index) { - std::unique_ptr<base::DictionaryValue> cert_node( - new base::DictionaryValue()); - base::ListValue cert_details; - cert_node->SetString("label", - x509_certificate_model::GetTitle(i->get()).c_str()); - cert_node->SetDouble("payload.index", index); + for (const auto& cert : nss_certs_) { + base::Value cert_node(base::Value::Type::DICTIONARY); + cert_node.SetKey("label", + base::Value(x509_certificate_model::GetTitle(cert.get()))); + cert_node.SetPath({"payload", "index"}, base::Value(index)); // Add the child from the previous iteration. - if (children) - cert_node->Set("children", std::move(children)); + if (!children.is_none()) + cert_node.SetKey("children", std::move(children)); // Add this node to the children list for the next iteration. - children = std::make_unique<base::ListValue>(); - children->Append(std::move(cert_node)); + children = base::Value(base::Value::Type::LIST); + children.GetList().push_back(std::move(cert_node)); + ++index; } // Set the last node as the top of the certificate hierarchy. - cert_info.Set("hierarchy", std::move(children)); + cert_info.SetKey("hierarchy", std::move(children)); base::JSONWriter::Write(cert_info, &data);
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc b/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc index 5d97e891..8b85f10 100644 --- a/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc +++ b/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc
@@ -12,7 +12,6 @@ #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/ui/webui/signin/inline_login_handler.h" #include "chromeos/account_manager/account_manager.h" #include "chromeos/account_manager/account_manager_factory.h" @@ -33,15 +32,13 @@ class SigninHelper : public GaiaAuthConsumer { public: SigninHelper( - Profile* profile, chromeos::AccountManager* account_manager, const base::RepeatingClosure& close_dialog_closure, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const std::string& gaia_id, const std::string& email, const std::string& auth_code) - : profile_(profile), - account_manager_(account_manager), + : account_manager_(account_manager), close_dialog_closure_(close_dialog_closure), email_(email), gaia_auth_fetcher_(this, @@ -57,22 +54,18 @@ // GaiaAuthConsumer overrides. void OnClientOAuthSuccess(const ClientOAuthResult& result) override { - // TODO(sinhak): Do not depend on Profile unnecessarily. A Profile should - // call |IdentityManagerFactory| for the list of accounts it wants to - // pull from |AccountManager|, not the other way round. Remove this when we - // release multi Profile on Chrome OS and have the infra in place to do - // this. - // Account info needs to be seeded before the OAuth2TokenService chain can - // use it. Do this before anything else. - AccountInfo account_info; - account_info.gaia = account_key_.id; - account_info.email = email_; - // TODO(crbug.com/922026): SigninHelper and InlineLoginHandlerChromeOS - // must be refactored to remove this use of LegacySeedAccountInfo. It should - // be possible to replace these two calls with a call to - // |AccountsMutator::AddOrUpdateAccount()|. - IdentityManagerFactory::GetForProfile(profile_)->LegacySeedAccountInfo( - account_info); + // Flow of control after this call: + // |AccountManager::UpsertAccount| updates / inserts the account and calls + // its |Observer|s, one of which is |ChromeOSOAuth2TokenServiceDelegate|. + // |ChromeOSOAuth2TokenServiceDelegate::OnTokenUpserted| seeds the Gaia id + // and email id for this account in |AccountTrackerService| and invokes + // |FireRefreshTokenAvailable|. This causes the account to propagate + // throughout the Identity Service chain, including in + // |AccountFetcherService|. |AccountFetcherService::OnRefreshTokenAvailable| + // invokes |AccountTrackerService::StartTrackingAccount|, triggers a fetch + // for the account information from Gaia and updates this information into + // |AccountTrackerService|. At this point the account will be fully added to + // the system. account_manager_->UpsertAccount(account_key_, email_, result.refresh_token); close_dialog_closure_.Run(); @@ -86,8 +79,6 @@ } private: - // A non-owning pointer to Profile. - Profile* const profile_; // A non-owning pointer to Chrome OS AccountManager. chromeos::AccountManager* const account_manager_; // A closure to close the hosting dialog window. @@ -147,7 +138,7 @@ ->GetAccountManager(profile->GetPath().value()); // SigninHelper deletes itself after its work is done. - new SigninHelper(profile, account_manager, close_dialog_closure_, + new SigninHelper(account_manager, close_dialog_closure_, account_manager->GetUrlLoaderFactory(), gaia_id, email, auth_code); }
diff --git a/chrome/browser/ui/webui/sync_internals_browsertest.js b/chrome/browser/ui/webui/sync_internals_browsertest.js index 4c48fa8..11b09ea 100644 --- a/chrome/browser/ui/webui/sync_internals_browsertest.js +++ b/chrome/browser/ui/webui/sync_internals_browsertest.js
@@ -61,22 +61,6 @@ } }; -function SyncInternalsWebUITestWithStandaloneTransport() {} - -SyncInternalsWebUITestWithStandaloneTransport.prototype = { - __proto__: SyncInternalsWebUITest.prototype, - - featureList: ['switches::kSyncStandaloneTransport', ''], -}; - -function SyncInternalsWebUITestWithoutStandaloneTransport() {} - -SyncInternalsWebUITestWithoutStandaloneTransport.prototype = { - __proto__: SyncInternalsWebUITest.prototype, - - featureList: ['', 'switches::kSyncStandaloneTransport'], -}; - /** * Constant hard-coded value to return from mock getAllNodes. * @const
diff --git a/chrome/browser/vr/text_perftest.cc b/chrome/browser/vr/text_perftest.cc index 172d674..e24071e 100644 --- a/chrome/browser/vr/text_perftest.cc +++ b/chrome/browser/vr/text_perftest.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. #include "base/strings/utf_string_conversions.h" -#include "cc/base/lap_timer.h" +#include "base/timer/lap_timer.h" #include "chrome/browser/vr/elements/text.h" #include "chrome/browser/vr/skia_surface_provider_factory.h" #include "chrome/browser/vr/test/constants.h" @@ -43,7 +43,7 @@ protected: void PrintResults(const std::string& name) { perf_test::PrintResult("TextPerfTest", ".render_time_avg", name, - timer_.MsPerLap(), "ms", true); + timer_.TimePerLap().InMillisecondsF(), "ms", true); perf_test::PrintResult("TextPerfTest", ".number_of_runs", name, static_cast<size_t>(timer_.NumLaps()), "runs", true); } @@ -57,7 +57,7 @@ } std::unique_ptr<Text> text_element_; - cc::LapTimer timer_; + base::LapTimer timer_; private: std::unique_ptr<SkiaSurfaceProvider> provider_;
diff --git a/chrome/common/extensions/docs/templates/intros/browsingData.html b/chrome/common/extensions/docs/templates/intros/browsingData.html index d8bf735..0489daa 100644 --- a/chrome/common/extensions/docs/templates/intros/browsingData.html +++ b/chrome/common/extensions/docs/templates/intros/browsingData.html
@@ -91,6 +91,37 @@ to keep your users up to date on the removal's status. </p> + +<h2 id="specific_origins">Specific Origins</h2> + +<p>To remove data for a specific origin or to exclude a set of origins from +deletion, you can use the <code>RemovalOptions.origins</code> and +<code>RemovalOptions.excludeOrigins</code> parameters. They can only be applied +to cookies, cache, and storage (CacheStorage, FileSystems, IndexedDB, +LocalStorage, PluginData, ServiceWorkers, and WebSQL). +</p> + +<pre>chrome.browsingData.remove({ + "origins": ["https://www.example.com"] +}, { + "cacheStorage": true, + "cookies": true, + "fileSystems": true, + "indexedDB": true, + "localStorage": true, + "pluginData": true, + "serviceWorkers": true, + "webSQL": true +}, callback);</pre> + +<p class="caution"> + <strong>Important</strong>: As cookies are scoped more broadly than other + types of storage, deleting cookies for an origin will delete all cookies of + the registrable domain. For example, deleting data for + <code>https://www.example.com</code> will delete cookies with a domain of + <code>.example.com</code> as well. +</p> + <h2 id="origin_types">Origin Types</h2> <p>
diff --git a/chrome/credential_provider/gaiacp/associated_user_validator.cc b/chrome/credential_provider/gaiacp/associated_user_validator.cc index fc6f523..44a9a9bd 100644 --- a/chrome/credential_provider/gaiacp/associated_user_validator.cc +++ b/chrome/credential_provider/gaiacp/associated_user_validator.cc
@@ -122,39 +122,6 @@ return token_handle_validity; } -HRESULT CleanupStaleUsersAndGetTokenHandles( - std::map<base::string16, base::string16>* sid_to_handle) { - DCHECK(sid_to_handle); - std::map<base::string16, UserTokenHandleInfo> sids_to_handle_info; - - HRESULT hr = GetUserTokenHandles(&sids_to_handle_info); - if (FAILED(hr)) { - LOGFN(ERROR) << "GetUserAssociationInfo hr=" << putHR(hr); - return hr; - } - - OSUserManager* manager = OSUserManager::Get(); - for (const auto& sid_to_association : sids_to_handle_info) { - const base::string16& sid = sid_to_association.first; - const UserTokenHandleInfo& info = sid_to_association.second; - if (info.gaia_id.empty()) { - RemoveAllUserProperties(sid); - continue; - } - HRESULT hr = manager->FindUserBySID(sid.c_str(), nullptr, 0, nullptr, 0); - if (hr == HRESULT_FROM_WIN32(ERROR_NONE_MAPPED)) { - RemoveAllUserProperties(sid); - continue; - } else if (FAILED(hr)) { - LOGFN(ERROR) << "manager->FindUserBySID hr=" << putHR(hr); - } - - sid_to_handle->emplace(sid, info.token_handle); - } - - return S_OK; -} - HRESULT ModifyUserAccess(const std::unique_ptr<ScopedLsaPolicy>& policy, const base::string16& sid, bool allow) { @@ -242,13 +209,53 @@ return InternetAvailabilityChecker::Get()->HasInternetConnection(); } -void AssociatedUserValidator::GetAssociatedSids( - std::set<base::string16>* associated_sids) { - DCHECK(associated_sids); +HRESULT AssociatedUserValidator::UpdateAssociatedSids( + std::map<base::string16, base::string16>* sid_to_handle) { + std::map<base::string16, UserTokenHandleInfo> sids_to_handle_info; - associated_sids->clear(); + HRESULT hr = GetUserTokenHandles(&sids_to_handle_info); + if (FAILED(hr)) { + LOGFN(ERROR) << "GetUserTokenHandles hr=" << putHR(hr); + return hr; + } + + std::set<base::string16> users_to_delete; + OSUserManager* manager = OSUserManager::Get(); + for (const auto& sid_to_association : sids_to_handle_info) { + const base::string16& sid = sid_to_association.first; + const UserTokenHandleInfo& info = sid_to_association.second; + if (info.gaia_id.empty()) { + users_to_delete.insert(sid_to_association.first); + continue; + } + HRESULT hr = manager->FindUserBySID(sid.c_str(), nullptr, 0, nullptr, 0); + if (hr == HRESULT_FROM_WIN32(ERROR_NONE_MAPPED)) { + users_to_delete.insert(sid_to_association.first); + continue; + } else if (FAILED(hr)) { + LOGFN(ERROR) << "manager->FindUserBySID hr=" << putHR(hr); + } + + if (sid_to_handle) + sid_to_handle->emplace(sid, info.token_handle); + } + + for (const auto& to_delete : users_to_delete) { + user_to_token_handle_info_.erase(to_delete); + RemoveAllUserProperties(to_delete); + } + + return S_OK; +} + +std::set<base::string16> AssociatedUserValidator::GetUpdatedAssociatedSids() { + UpdateAssociatedSids(nullptr); + + std::set<base::string16> associated_sids; for (const auto& it : user_to_token_handle_info_) - associated_sids->insert(it.first); + associated_sids.insert(it.first); + + return associated_sids; } bool AssociatedUserValidator::IsUserAccessBlockingEnforced( @@ -270,18 +277,16 @@ if (!IsUserAccessBlockingEnforced(cpus)) return; - std::map<base::string16, UserTokenHandleInfo> sids_to_association; - - HRESULT hr = GetUserTokenHandles(&sids_to_association); + HRESULT hr = UpdateAssociatedSids(nullptr); if (FAILED(hr)) { - LOGFN(ERROR) << "GetUserAssociationInfo hr=" << putHR(hr); + LOGFN(ERROR) << "GetUserTokenHandles hr=" << putHR(hr); return; } auto policy = ScopedLsaPolicy::Create(POLICY_ALL_ACCESS); - for (const auto& sid_to_association : sids_to_association) { - const base::string16& sid = sid_to_association.first; + for (const auto& user_info : user_to_token_handle_info_) { + const base::string16& sid = user_info.first; if (locked_user_sids_.find(sid) != locked_user_sids_.end()) continue; @@ -319,10 +324,10 @@ void AssociatedUserValidator::StartRefreshingTokenHandleValidity() { std::map<base::string16, base::string16> sid_to_handle; - HRESULT hr = CleanupStaleUsersAndGetTokenHandles(&sid_to_handle); + HRESULT hr = UpdateAssociatedSids(&sid_to_handle); if (FAILED(hr)) { - LOGFN(ERROR) << "CleanupStaleUsersAndGetTokenHandles hr=" << putHR(hr); + LOGFN(ERROR) << "UpdateAssociatedSids hr=" << putHR(hr); return; }
diff --git a/chrome/credential_provider/gaiacp/associated_user_validator.h b/chrome/credential_provider/gaiacp/associated_user_validator.h index 070122e..7818c1f 100644 --- a/chrome/credential_provider/gaiacp/associated_user_validator.h +++ b/chrome/credential_provider/gaiacp/associated_user_validator.h
@@ -68,7 +68,8 @@ // Fills |associated_sids| with the sids of all valid associated users // found on this system. - void GetAssociatedSids(std::set<base::string16>* associated_sids); + std::set<base::string16> GetUpdatedAssociatedSids(); + size_t GetAssociatedUsersCount() { return GetUpdatedAssociatedSids().size(); } protected: explicit AssociatedUserValidator(base::TimeDelta validation_timeout); @@ -80,6 +81,8 @@ void StartTokenValidityQuery(const base::string16& sid, const base::string16& token_handle, base::TimeDelta timeout); + HRESULT UpdateAssociatedSids( + std::map<base::string16, base::string16>* sid_to_handle); // Returns the storage used for the instance pointer. static AssociatedUserValidator** GetInstanceStorage();
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_base.cc b/chrome/credential_provider/gaiacp/gaia_credential_base.cc index abee88b9..3498201 100644 --- a/chrome/credential_provider/gaiacp/gaia_credential_base.cc +++ b/chrome/credential_provider/gaiacp/gaia_credential_base.cc
@@ -32,6 +32,7 @@ #include "chrome/credential_provider/common/gcp_strings.h" #include "chrome/credential_provider/gaiacp/associated_user_validator.h" #include "chrome/credential_provider/gaiacp/auth_utils.h" +#include "chrome/credential_provider/gaiacp/gaia_credential_provider.h" #include "chrome/credential_provider/gaiacp/gaia_credential_provider_i.h" #include "chrome/credential_provider/gaiacp/gaia_resources.h" #include "chrome/credential_provider/gaiacp/gcp_utils.h" @@ -1573,11 +1574,18 @@ // New users creation is not allowed during work station unlock. This code // prevents users from being created when the "Other User" tile appears on the - // lock screen through a combination of system policy. In this situation only + // lock screen through certain system policy settings. In this situation only // the user who locked the computer is allowed to sign in. if (cpus == CPUS_UNLOCK_WORKSTATION) { *error_text = AllocErrorString(IDS_INVALID_UNLOCK_WORKSTATION_USER_BASE); return HRESULT_FROM_WIN32(ERROR_LOGON_TYPE_NOT_GRANTED); + // This code prevents users from being created when the "Other User" tile + // appears on the sign in scenario and only 1 user is allowed to use this + // system. + } else if (!CGaiaCredentialProvider::CanNewUsersBeCreated( + static_cast<CREDENTIAL_PROVIDER_USAGE_SCENARIO>(cpus))) { + *error_text = AllocErrorString(IDS_ADD_USER_DISALLOWED_BASE); + return HRESULT_FROM_WIN32(ERROR_LOGON_TYPE_NOT_GRANTED); } base::string16 local_fullname = GetDictString(result, kKeyFullname);
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc b/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc index 84210d0..90aebea 100644 --- a/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc +++ b/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc
@@ -543,6 +543,52 @@ GetStringResource(IDS_INVALID_UNLOCK_WORKSTATION_USER_BASE).c_str()); } +TEST_F(GcpGaiaCredentialBaseTest, NewUserDisabledThroughMdm) { + USES_CONVERSION; + FakeAssociatedUserValidator validator; + FakeInternetAvailabilityChecker internet_checker; + + // Enforce single user mode for MDM. + ASSERT_EQ(S_OK, SetGlobalFlagForTesting(kRegMdmUrl, L"https://mdm.com")); + ASSERT_EQ(S_OK, SetGlobalFlagForTesting(kRegMdmSupportsMultiUser, 0)); + GoogleMdmEnrolledStatusForTesting force_success(true); + + // Create a fake user that is already associated so when the user tries to + // sign on and create a new user, it fails. + CComBSTR sid; + ASSERT_EQ(S_OK, fake_os_user_manager()->CreateTestOSUser( + L"foo_registered", L"password", L"name", L"comment", + L"gaia-id-registered", base::string16(), &sid)); + + FakeGaiaCredentialProvider provider; + + // Populate the associated users list, token handle validity does not matter + // in this test. + validator.StartRefreshingTokenHandleValidity(); + + // Start logon. + CComPtr<IGaiaCredential> gaia_cred; + CComPtr<ICredentialProviderCredential> cred; + ASSERT_EQ(S_OK, CreateCredentialWithProvider(&provider, &gaia_cred, &cred)); + + CComPtr<ITestCredential> test; + ASSERT_EQ(S_OK, cred.QueryInterface(&test)); + + ASSERT_EQ(S_OK, run_helper()->StartLogonProcessAndWait(cred)); + + ASSERT_EQ(S_OK, gaia_cred->Terminate()); + + // Check that values were not propagated to the provider. + EXPECT_EQ(0u, provider.username().Length()); + EXPECT_EQ(0u, provider.password().Length()); + EXPECT_EQ(0u, provider.sid().Length()); + EXPECT_EQ(FALSE, provider.credentials_changed_fired()); + + // Sign in should fail with an error stating that no new users can be created. + ASSERT_STREQ(test->GetErrorText(), + GetStringResource(IDS_ADD_USER_DISALLOWED_BASE).c_str()); +} + TEST_F(GcpGaiaCredentialBaseTest, InvalidUserUnlockedAfterSignin) { // Enforce token handle verification with user locking when the token handle // is not valid.
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_provider.cc b/chrome/credential_provider/gaiacp/gaia_credential_provider.cc index 5838c6e..03946f0 100644 --- a/chrome/credential_provider/gaiacp/gaia_credential_provider.cc +++ b/chrome/credential_provider/gaiacp/gaia_credential_provider.cc
@@ -112,29 +112,6 @@ AssociatedUserValidator::Get()->AllowSigninForUsersWithInvalidTokenHandles(); } -bool CGaiaCredentialProvider::ShouldCreateAnonymousCredential() { - // When in an unlock usage, only the user that locked the computer will be - // allowed to sign in, so no new users can be added. - if (cpus_ == CPUS_UNLOCK_WORKSTATION) - return false; - - // If MDM enrollment is required and multiple users is not supported, only - // create the Gaia credential if there does not yet exist an OS user created - // from a Google account. Otherwise we always create the Gaia credential. - if (MdmEnrollmentEnabled()) { - DWORD multi_user_supported = 0; - HRESULT hr = GetGlobalFlag(kRegMdmSupportsMultiUser, &multi_user_supported); - if (FAILED(hr) || multi_user_supported == 0) { - DWORD user_count; - hr = GetUserCount(&user_count); - if (SUCCEEDED(hr) && user_count > 0) - return false; - } - } - - return true; -} - bool CGaiaCredentialProvider::ShouldCreateAnonymousReauthCredential( bool other_user_credential_exists) { // If user lockout is not enforced, no need to create anonymous reauth @@ -197,7 +174,7 @@ if (showing_other_user) { hr = CComCreator<CComObject<COtherUserGaiaCredential>>::CreateInstance( nullptr, IID_IGaiaCredential, reinterpret_cast<void**>(&cred)); - } else if (ShouldCreateAnonymousCredential()) { + } else if (CanNewUsersBeCreated(cpus_)) { hr = CComCreator<CComObject<CGaiaCredential>>::CreateInstance( nullptr, IID_IGaiaCredential, reinterpret_cast<void**>(&cred)); } else { @@ -308,8 +285,8 @@ if (!ShouldCreateAnonymousReauthCredential(showing_other_user)) return S_OK; - std::set<base::string16> associated_sids; - AssociatedUserValidator::Get()->GetAssociatedSids(&associated_sids); + std::set<base::string16> associated_sids = + AssociatedUserValidator::Get()->GetUpdatedAssociatedSids(); OSUserManager* manager = OSUserManager::Get(); @@ -368,6 +345,29 @@ return cpus == CPUS_LOGON || cpus == CPUS_UNLOCK_WORKSTATION; } +// Static. +bool CGaiaCredentialProvider::CanNewUsersBeCreated( + CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus) { + // When in an unlock usage, only the user that locked the computer will be + // allowed to sign in, so no new users can be added. + if (cpus == CPUS_UNLOCK_WORKSTATION) + return false; + + // If MDM enrollment is required and multiple users is not supported, only + // allow a new associated user to be created if there does not yet exist an + // OS user created from a Google account. + if (MdmEnrollmentEnabled()) { + DWORD multi_user_supported = 0; + HRESULT hr = GetGlobalFlag(kRegMdmSupportsMultiUser, &multi_user_supported); + if (FAILED(hr) || multi_user_supported == 0) { + if (AssociatedUserValidator::Get()->GetAssociatedUsersCount() > 0) + return false; + } + } + + return true; +} + // IGaiaCredentialProvider //////////////////////////////////////////////////// HRESULT CGaiaCredentialProvider::GetUsageScenario(DWORD* cpus) {
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_provider.h b/chrome/credential_provider/gaiacp/gaia_credential_provider.h index 0e601a23..3da35afa4 100644 --- a/chrome/credential_provider/gaiacp/gaia_credential_provider.h +++ b/chrome/credential_provider/gaiacp/gaia_credential_provider.h
@@ -43,12 +43,16 @@ HRESULT FinalConstruct(); void FinalRelease(); + // Returns true if the given usage scenario is supported by GCPW. Currently + // only CPUS_LOGON and CPUS_UNLOCK_WORKSTATION are supported. static bool IsUsageScenarioSupported(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus); - private: - // Checks whether an anonymous credential (CGaiaCredential) should be created. - bool ShouldCreateAnonymousCredential(); + // Returns true if a new user can be added in the current usage scenario. This + // function also checks other settings controlled by registry settings to + // determine the result of this query. + static bool CanNewUsersBeCreated(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus); + private: // Checks whether anonymous reauth credentials should be created given the // usage scenario and also whether an "Other User" tile exists on the sign on // screen.
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_provider_unittests.cc b/chrome/credential_provider/gaiacp/gaia_credential_provider_unittests.cc index 147f828..f6d236d 100644 --- a/chrome/credential_provider/gaiacp/gaia_credential_provider_unittests.cc +++ b/chrome/credential_provider/gaiacp/gaia_credential_provider_unittests.cc
@@ -181,6 +181,7 @@ // exists. ASSERT_EQ(S_OK, SetGlobalFlagForTesting(kRegMdmUrl, L"https://mdm.com")); ASSERT_EQ(S_OK, SetGlobalFlagForTesting(kRegMdmSupportsMultiUser, 0)); + GoogleMdmEnrolledStatusForTesting forced_status(true); const wchar_t kDummyUsername[] = L"username"; const wchar_t kDummyPassword[] = L"password"; @@ -188,6 +189,9 @@ CreateGCPWUser(kDummyUsername, L"foo@gmail.com", kDummyPassword, L"Full Name", L"Comment", L"gaia-id", &sid); + // Start token handle refresh threads. + associated_user_validator.StartRefreshingTokenHandleValidity(); + { CComPtr<ICredentialProvider> provider; ASSERT_EQ(S_OK, @@ -216,8 +220,6 @@ ASSERT_EQ(S_OK, fake_os_user_manager()->RemoveUser(kDummyUsername, kDummyPassword)); - // Start token handle refresh threads. - associated_user_validator.StartRefreshingTokenHandleValidity(); { CComPtr<ICredentialProvider> provider; ASSERT_EQ(S_OK, @@ -263,8 +265,13 @@ const DWORD expected_credential_count = config_mdm_url && supports_multi_users != 1 && user_exists ? 0 : 1; - if (config_mdm_url) + bool mdm_enrolled = false; + if (config_mdm_url) { ASSERT_EQ(S_OK, SetGlobalFlagForTesting(kRegMdmUrl, L"https://mdm.com")); + mdm_enrolled = true; + } + + GoogleMdmEnrolledStatusForTesting forced_status(mdm_enrolled); if (supports_multi_users != 2) { ASSERT_EQ(S_OK, SetGlobalFlagForTesting(kRegMdmSupportsMultiUser, @@ -282,6 +289,8 @@ GURL(AssociatedUserValidator::kTokenInfoUrl), FakeWinHttpUrlFetcher::Headers(), "{\"expires_in\":1}"); + associated_user_validator.StartRefreshingTokenHandleValidity(); + CComPtr<ICredentialProvider> provider; ASSERT_EQ(S_OK, CComCreator<CComObject<CGaiaCredentialProvider>>::CreateInstance(
diff --git a/chrome/credential_provider/gaiacp/gaia_resources.grd b/chrome/credential_provider/gaiacp/gaia_resources.grd index 4d6932ec..a18c84c 100644 --- a/chrome/credential_provider/gaiacp/gaia_resources.grd +++ b/chrome/credential_provider/gaiacp/gaia_resources.grd
@@ -115,6 +115,9 @@ <message name="IDS_INVALID_UNLOCK_WORKSTATION_USER" desc=""> Only the user that locked this workstation is currently allowed sign in to the system. </message> + <message name="IDS_ADD_USER_DISALLOWED" desc=""> + Failed to create new registered Google user. This system only allows one registered Google user to be created. + </message> </messages> </release> </grit>
diff --git a/chrome/credential_provider/gaiacp/gaia_resources_grd/IDS_ADD_USER_DISALLOWED.png.sha1 b/chrome/credential_provider/gaiacp/gaia_resources_grd/IDS_ADD_USER_DISALLOWED.png.sha1 new file mode 100644 index 0000000..2041fe7 --- /dev/null +++ b/chrome/credential_provider/gaiacp/gaia_resources_grd/IDS_ADD_USER_DISALLOWED.png.sha1
@@ -0,0 +1 @@ +7df62d83b544821330f561da0039a33f586ae389 \ No newline at end of file
diff --git a/chrome/credential_provider/gaiacp/reg_utils.cc b/chrome/credential_provider/gaiacp/reg_utils.cc index d92b0ee..e65dcaa 100644 --- a/chrome/credential_provider/gaiacp/reg_utils.cc +++ b/chrome/credential_provider/gaiacp/reg_utils.cc
@@ -177,17 +177,6 @@ return SetMachineRegDWORD(kGcpRootKeyName, name, value); } -HRESULT GetUserCount(DWORD* count) { - DCHECK(count); - - wchar_t key_name[128]; - swprintf_s(key_name, base::size(key_name), L"%s\\Users", kGcpRootKeyName); - - base::win::RegistryKeyIterator iter(HKEY_LOCAL_MACHINE, key_name); - *count = iter.SubkeyCount(); - return S_OK; -} - HRESULT GetUserProperty(const base::string16& sid, const base::string16& name, DWORD* value) {
diff --git a/chrome/credential_provider/gaiacp/reg_utils.h b/chrome/credential_provider/gaiacp/reg_utils.h index c73d106..641ab377 100644 --- a/chrome/credential_provider/gaiacp/reg_utils.h +++ b/chrome/credential_provider/gaiacp/reg_utils.h
@@ -51,9 +51,6 @@ const base::string16& value); HRESULT SetGlobalFlagForTesting(const base::string16& name, DWORD value); -// Gets the number of users assoicated with this credential provider. -HRESULT GetUserCount(DWORD* count); - // Gets DWORD property set for the given user. HRESULT GetUserProperty(const base::string16& sid, const base::string16& name,
diff --git a/chrome/test/chromedriver/net/websocket.cc b/chrome/test/chromedriver/net/websocket.cc index 1eacaf3..e5f7df07 100644 --- a/chrome/test/chromedriver/net/websocket.cc +++ b/chrome/test/chromedriver/net/websocket.cc
@@ -246,9 +246,9 @@ void WebSocket::OnReadDuringHandshake(const char* data, int len) { VLOG(4) << "WebSocket::OnReadDuringHandshake\n" << std::string(data, len); handshake_response_ += std::string(data, len); - int headers_end = net::HttpUtil::LocateEndOfHeaders( + size_t headers_end = net::HttpUtil::LocateEndOfHeaders( handshake_response_.data(), handshake_response_.size(), 0); - if (headers_end == -1) + if (headers_end == std::string::npos) return; const char kMagicKey[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
diff --git a/components/autofill/core/browser/phone_number_i18n_unittest.cc b/components/autofill/core/browser/phone_number_i18n_unittest.cc index 16269c3c..a65481ec 100644 --- a/components/autofill/core/browser/phone_number_i18n_unittest.cc +++ b/components/autofill/core/browser/phone_number_i18n_unittest.cc
@@ -272,6 +272,37 @@ i18n::FormatPhoneForResponse("(1) 515-123-1234", "US")); } +// Tests that phone numbers are correctly formatted in a national format. +TEST(PhoneNumberUtilTest, FormatPhoneNationallyForDisplay) { + // Invalid US and Brazilian numbers are not formatted. + EXPECT_EQ("1234567890", + i18n::FormatPhoneNationallyForDisplay("1234567890", "US")); + EXPECT_EQ("(11) 13333-4444", + i18n::FormatPhoneNationallyForDisplay("(11) 13333-4444", "BR")); + EXPECT_EQ("(11) 13333-4444", + i18n::FormatPhoneNationallyForDisplay("(11) 13333-4444", "IN")); + + // Valid US, Canadian, UK, and Brazilian numbers are nationally formatted. + EXPECT_EQ("(202) 444-0000", + i18n::FormatPhoneNationallyForDisplay("2024440000", "US")); + EXPECT_EQ("(202) 444-0000", + i18n::FormatPhoneNationallyForDisplay("+1(202)4440000", "US")); + EXPECT_EQ("(202) 444-0000", + i18n::FormatPhoneNationallyForDisplay("12024440000", "US")); + EXPECT_EQ("(202) 444-0000", + i18n::FormatPhoneNationallyForDisplay("(202)4440000", "US")); + EXPECT_EQ("(202) 444-0000", + i18n::FormatPhoneNationallyForDisplay("202-444-0000", "US")); + EXPECT_EQ("(819) 555-9999", + i18n::FormatPhoneNationallyForDisplay("+1(819)555 9999", "CA")); + EXPECT_EQ("(819) 555-9999", + i18n::FormatPhoneNationallyForDisplay("18195559999", "CA")); + EXPECT_EQ("020 7601 4444", + i18n::FormatPhoneNationallyForDisplay("+4402076014444", "UK")); + EXPECT_EQ("(21) 3883-5600", + i18n::FormatPhoneNationallyForDisplay("2138835600", "BR")); +} + // Tests that the phone numbers are correctly formatted to display to the user. TEST(PhoneNumberUtilTest, FormatPhoneForDisplay) { // Invalid number is not formatted.
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc index 98721d9..5f511af4a 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc
@@ -320,7 +320,9 @@ LoadDataCacheAndMetadata(); } -AutofillWalletMetadataSyncBridge::~AutofillWalletMetadataSyncBridge() {} +AutofillWalletMetadataSyncBridge::~AutofillWalletMetadataSyncBridge() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} void AutofillWalletMetadataSyncBridge::OnWalletDataTrackingStateChanged( bool is_tracking) { @@ -338,6 +340,7 @@ AutofillWalletMetadataSyncBridge::MergeSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // First upload local entities that are not mentioned in |entity_data|. UploadInitialLocalData(metadata_change_list.get(), entity_data); @@ -349,6 +352,7 @@ AutofillWalletMetadataSyncBridge::ApplySyncChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return MergeRemoteChanges(std::move(metadata_change_list), std::move(entity_data)); } @@ -369,6 +373,7 @@ std::string AutofillWalletMetadataSyncBridge::GetClientTag( const syncer::EntityData& entity_data) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); const WalletMetadataSpecifics& remote_metadata = entity_data.specifics.wallet_metadata(); return GetClientTagForSpecificsId(remote_metadata.type(), @@ -377,6 +382,7 @@ std::string AutofillWalletMetadataSyncBridge::GetStorageKey( const syncer::EntityData& entity_data) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return GetStorageKeyForWalletMetadataTypeAndSpecificsId( entity_data.specifics.wallet_metadata().type(), entity_data.specifics.wallet_metadata().id());
diff --git a/components/autofill_assistant/browser/details.cc b/components/autofill_assistant/browser/details.cc index 9cef1232..b231dada 100644 --- a/components/autofill_assistant/browser/details.cc +++ b/components/autofill_assistant/browser/details.cc
@@ -63,6 +63,10 @@ bool Details::UpdateFromParameters( const std::map<std::string, std::string>& parameters) { + // Whenever details are updated from parameters we want to animate missing + // data. + proto_.mutable_details()->set_animate_placeholders(true); + proto_.mutable_details()->set_show_image_placeholder(true); if (MaybeUpdateFromDetailsParameters(parameters)) { return true; } @@ -136,7 +140,6 @@ continue; } } - return details_updated; }
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto index 46d80c2..057da29c 100644 --- a/components/autofill_assistant/browser/service.proto +++ b/components/autofill_assistant/browser/service.proto
@@ -707,7 +707,11 @@ message DetailsProto { optional string title = 1; - optional string image_url = 2; + oneof image { + string image_url = 2; + // When set to true shows placeholder in place of an image. + bool show_image_placeholder = 10; + } // Optional label to provide additional price information. optional string total_price_label = 9; @@ -723,6 +727,15 @@ optional DateTimeProto datetime = 3; optional string description = 4; + // Asks the UI to show animated placeholders for missing fields. + // The placeholder will be shown on effectively missing: + // * title + // * image + // * description line (1 or 2) + // TODO(crbug.com/806868): Make the fields for displaying placeholders + // configurable by the server. + optional bool animate_placeholders = 11; + // Deprecated, no longer supported. reserved 5; }
diff --git a/components/browser_sync/browser_sync_switches.cc b/components/browser_sync/browser_sync_switches.cc index 39d8763b..35e898c 100644 --- a/components/browser_sync/browser_sync_switches.cc +++ b/components/browser_sync/browser_sync_switches.cc
@@ -26,6 +26,11 @@ // flag is present. const char kLocalSyncBackendDir[] = "local-sync-backend-dir"; +// If enabled, the sync engine will be shut down in the "paused" state. +// TODO(crbug.com/938819): Remove this after M74 has fully rolled out. +const base::Feature kStopSyncInPausedState{"StopSyncInPausedState", + base::FEATURE_ENABLED_BY_DEFAULT}; + bool IsSyncAllowedByFlag() { return !base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableSync);
diff --git a/components/browser_sync/browser_sync_switches.h b/components/browser_sync/browser_sync_switches.h index de0323c..8722853 100644 --- a/components/browser_sync/browser_sync_switches.h +++ b/components/browser_sync/browser_sync_switches.h
@@ -7,6 +7,8 @@ #ifndef COMPONENTS_BROWSER_SYNC_BROWSER_SYNC_SWITCHES_H_ #define COMPONENTS_BROWSER_SYNC_BROWSER_SYNC_SWITCHES_H_ +#include "base/feature_list.h" + namespace switches { extern const char kDisableSync[]; @@ -14,6 +16,8 @@ extern const char kEnableLocalSyncBackend[]; extern const char kLocalSyncBackendDir[]; +extern const base::Feature kStopSyncInPausedState; + // Returns whether sync is allowed to run based on command-line switches. // Profile::IsSyncAllowed() is probably a better signal than this function. // This function can be called from any thread, and the implementation doesn't
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc index 8aaf8a7..04e4836 100644 --- a/components/browser_sync/profile_sync_service.cc +++ b/components/browser_sync/profile_sync_service.cc
@@ -134,10 +134,6 @@ return type_map; } -bool IsStandaloneTransportEnabled() { - return base::FeatureList::IsEnabled(switches::kSyncStandaloneTransport); -} - } // namespace ProfileSyncService::InitParams::InitParams() = default; @@ -206,7 +202,7 @@ startup_controller_ = std::make_unique<syncer::StartupController>( base::BindRepeating(&ProfileSyncService::GetPreferredDataTypes, base::Unretained(this)), - base::BindRepeating(&ProfileSyncService::ShouldStartEngine, + base::BindRepeating(&ProfileSyncService::IsEngineAllowedToStart, base::Unretained(this)), base::BindRepeating(&ProfileSyncService::StartUpSlowEngineComponents, base::Unretained(this))); @@ -375,34 +371,12 @@ } bool ProfileSyncService::IsEngineAllowedToStart() const { - int disable_reasons = GetDisableReasons(); - if (IsStandaloneTransportEnabled()) { - // USER_CHOICE (i.e. the Sync feature toggle) and PLATFORM_OVERRIDE (i.e. - // Android's "MasterSync" toggle) do not prevent starting up the Sync - // transport. - const int kDisableReasonMask = - ~(DISABLE_REASON_USER_CHOICE | DISABLE_REASON_PLATFORM_OVERRIDE); - disable_reasons &= kDisableReasonMask; - } - return disable_reasons == DISABLE_REASON_NONE; -} - -bool ProfileSyncService::ShouldStartEngine( - bool bypass_first_setup_check) const { - if (!IsEngineAllowedToStart()) { - return false; - } - // If standalone transport is enabled, we always start the engine as soon as - // we can. - if (IsStandaloneTransportEnabled()) { - return true; - } - // Without standalone transport, we generally wait for first-time setup to be - // complete before starting the engine (because if it isn't, we can't - // configure the DataTypeManager anyway). Note that if a setup is currently in - // progress (which requires the engine to be initialized), then - // |bypass_first_setup_check| will be set to true. - return bypass_first_setup_check || IsFirstSetupComplete(); + // USER_CHOICE (i.e. the Sync feature toggle) and PLATFORM_OVERRIDE (i.e. + // Android's "MasterSync" toggle) do not prevent starting up the Sync + // transport. + const int kDisableReasonMask = + ~(DISABLE_REASON_USER_CHOICE | DISABLE_REASON_PLATFORM_OVERRIDE); + return (GetDisableReasons() & kDisableReasonMask) == DISABLE_REASON_NONE; } bool ProfileSyncService::IsEncryptedDatatypeEnabled() const { @@ -707,8 +681,10 @@ if (unrecoverable_error_reason_ != ERROR_REASON_UNSET) { result = result | DISABLE_REASON_UNRECOVERABLE_ERROR; } - if (auth_manager_->IsSyncPaused()) { - result = result | DISABLE_REASON_PAUSED; + if (base::FeatureList::IsEnabled(switches::kStopSyncInPausedState)) { + if (auth_manager_->IsSyncPaused()) { + result = result | DISABLE_REASON_PAUSED; + } } return result; } @@ -751,11 +727,6 @@ return TransportState::PENDING_DESIRED_CONFIGURATION; } - // Unless standalone transport is enabled, the DataTypeManager shouldn't get - // configured (i.e. leave the STOPPED state) before the initial setup is - // complete. - DCHECK(IsStandaloneTransportEnabled() || IsFirstSetupComplete()); - // Note that if a setup is started after the data types have been configured, // then they'll stay configured even though CanConfigureDataTypes will be // false. @@ -1196,7 +1167,6 @@ // easier to keep it like this. Changing this will likely require changes to // the setup UI flow. return data_type_manager_ && - (IsFirstSetupComplete() || IsStandaloneTransportEnabled()) && (bypass_setup_in_progress_check || !IsSetupInProgress()); } @@ -1317,9 +1287,7 @@ // TODO(crbug.com/856179): Evaluate whether we can get away without a full // restart (i.e. just reconfigure plus whatever cleanup is necessary). See // also similar comment in OnSyncRequestedPrefChange(). - if (IsStandaloneTransportEnabled()) { - startup_controller_->TryStart(/*force_immediate=*/false); - } + startup_controller_->TryStart(/*force_immediate=*/false); } } @@ -1364,7 +1332,6 @@ syncer::ModelTypeSet types = GetPreferredDataTypes(); // In transport-only mode, only a subset of data types is supported. if (use_transport_only_mode) { - DCHECK(IsStandaloneTransportEnabled()); syncer::ModelTypeSet allowed_types = {syncer::USER_CONSENTS}; if (base::FeatureList::IsEnabled( @@ -1560,7 +1527,7 @@ // If the Sync engine was already initialized (probably running in transport // mode), just reconfigure. - if (IsStandaloneTransportEnabled() && engine_initialized_) { + if (engine_initialized_) { ReconfigureDatatypeManager(/*bypass_setup_in_progress_check=*/false); } else { // Otherwise try to start up. Note that there might still be other disable @@ -1580,9 +1547,7 @@ // restart (i.e. just reconfigure plus whatever cleanup is necessary). // Especially in the CLEAR_DATA case, StopImpl does a lot of cleanup that // might still be required. - if (IsStandaloneTransportEnabled()) { - startup_controller_->TryStart(/*force_immediate=*/false); - } + startup_controller_->TryStart(/*force_immediate=*/false); } }
diff --git a/components/browser_sync/profile_sync_service.h b/components/browser_sync/profile_sync_service.h index f33128894..6c01395b 100644 --- a/components/browser_sync/profile_sync_service.h +++ b/components/browser_sync/profile_sync_service.h
@@ -373,9 +373,6 @@ bool IsEngineAllowedToStart() const; - // Callback for StartupController. - bool ShouldStartEngine(bool bypass_first_setup_check) const; - enum UnrecoverableErrorReason { ERROR_REASON_UNSET, ERROR_REASON_SYNCER,
diff --git a/components/browser_sync/profile_sync_service_startup_unittest.cc b/components/browser_sync/profile_sync_service_startup_unittest.cc index 4d17637e..45a649b7 100644 --- a/components/browser_sync/profile_sync_service_startup_unittest.cc +++ b/components/browser_sync/profile_sync_service_startup_unittest.cc
@@ -156,110 +156,10 @@ std::unique_ptr<ProfileSyncService> sync_service_; }; -class ProfileSyncServiceWithStandaloneTransportStartupTest - : public ProfileSyncServiceStartupTest { - protected: - ProfileSyncServiceWithStandaloneTransportStartupTest() { - feature_list_.InitAndEnableFeature(switches::kSyncStandaloneTransport); - } - - ~ProfileSyncServiceWithStandaloneTransportStartupTest() override {} - - private: - base::test::ScopedFeatureList feature_list_; -}; - -class ProfileSyncServiceWithoutStandaloneTransportStartupTest - : public ProfileSyncServiceStartupTest { - protected: - ProfileSyncServiceWithoutStandaloneTransportStartupTest() { - feature_list_.InitAndDisableFeature(switches::kSyncStandaloneTransport); - } - - ~ProfileSyncServiceWithoutStandaloneTransportStartupTest() override {} - - private: - base::test::ScopedFeatureList feature_list_; -}; - // ChromeOS does not support sign-in after startup (in particular, // IdentityManager::Observer::OnPrimaryAccountSet never gets called). #if !defined(OS_CHROMEOS) -TEST_F(ProfileSyncServiceWithoutStandaloneTransportStartupTest, - StartFirstTime) { - // We've never completed startup. - ASSERT_FALSE(sync_prefs()->IsFirstSetupComplete()); - - CreateSyncService(ProfileSyncService::MANUAL_START); - SetUpFakeSyncEngine(); - DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock(); - EXPECT_CALL(*data_type_manager, Configure(_, _)).Times(0); - ON_CALL(*data_type_manager, state()) - .WillByDefault(Return(DataTypeManager::STOPPED)); - - // Should not actually start, rather just clean things up and wait - // to be enabled. - sync_service()->Initialize(); - EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN, - sync_service()->GetDisableReasons()); - EXPECT_EQ(syncer::SyncService::TransportState::DISABLED, - sync_service()->GetTransportState()); - - // Preferences should be back to defaults. - EXPECT_EQ(base::Time(), sync_prefs()->GetLastSyncedTime()); - EXPECT_FALSE(sync_prefs()->IsFirstSetupComplete()); - - // This tells the ProfileSyncService that setup is now in progress, which - // causes it to try starting up the engine. We're not signed in yet though, so - // that won't work. - auto sync_blocker = sync_service()->GetSetupInProgressHandle(); - EXPECT_FALSE(sync_service()->IsEngineInitialized()); - EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN, - sync_service()->GetDisableReasons()); - EXPECT_EQ(syncer::SyncService::TransportState::DISABLED, - sync_service()->GetTransportState()); - - // Simulate successful signin. This will cause ProfileSyncService to start, - // since all conditions are now fulfilled. - SimulateTestUserSignin(); - - // Now we're signed in, so the engine can start. There's already a setup in - // progress, so we don't go into the WAITING_FOR_START_REQUEST state. Engine - // initialization is immediate in this test, so we also bypass the - // INITIALIZING state. - EXPECT_TRUE(sync_service()->IsEngineInitialized()); - EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE, - sync_service()->GetDisableReasons()); - EXPECT_EQ(syncer::SyncService::TransportState::PENDING_DESIRED_CONFIGURATION, - sync_service()->GetTransportState()); - - // Simulate the UI telling sync it has finished setting up. Note that this is - // a two-step process: Releasing the SetupInProgressHandle, and marking first - // setup complete. - sync_blocker.reset(); - // Now setup isn't in progress anymore, but Sync is still waiting to be told - // that the initial setup was completed. - ASSERT_FALSE(sync_service()->IsSetupInProgress()); - EXPECT_EQ(syncer::SyncService::TransportState::PENDING_DESIRED_CONFIGURATION, - sync_service()->GetTransportState()); - - // Marking first setup complete will let ProfileSyncService configure the - // DataTypeManager. - EXPECT_CALL(*data_type_manager, Configure(_, _)); - ON_CALL(*data_type_manager, state()) - .WillByDefault(Return(DataTypeManager::CONFIGURED)); - sync_service()->GetUserSettings()->SetFirstSetupComplete(); - - // This should have fully enabled sync. - EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE, - sync_service()->GetTransportState()); - EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled()); - EXPECT_TRUE(sync_service()->IsSyncFeatureActive()); - - EXPECT_CALL(*data_type_manager, Stop(syncer::BROWSER_SHUTDOWN)); -} - -TEST_F(ProfileSyncServiceWithStandaloneTransportStartupTest, StartFirstTime) { +TEST_F(ProfileSyncServiceStartupTest, StartFirstTime) { // We've never completed startup. ASSERT_FALSE(sync_prefs()->IsFirstSetupComplete()); @@ -463,26 +363,7 @@ EXPECT_CALL(*data_type_manager, Stop(syncer::BROWSER_SHUTDOWN)); } -TEST_F(ProfileSyncServiceWithoutStandaloneTransportStartupTest, StopSync) { - sync_prefs()->SetFirstSetupComplete(); - CreateSyncService(ProfileSyncService::MANUAL_START); - SimulateTestUserSignin(); - SetUpFakeSyncEngine(); - DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock(); - ON_CALL(*data_type_manager, state()) - .WillByDefault(Return(DataTypeManager::CONFIGURED)); - ON_CALL(*data_type_manager, IsNigoriEnabled()).WillByDefault(Return(true)); - - sync_service()->Initialize(); - - EXPECT_CALL(*data_type_manager, Stop(syncer::STOP_SYNC)); - sync_service()->GetUserSettings()->SetSyncRequested(false); - - EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled()); - EXPECT_FALSE(sync_service()->IsSyncFeatureActive()); -} - -TEST_F(ProfileSyncServiceWithStandaloneTransportStartupTest, StopSync) { +TEST_F(ProfileSyncServiceStartupTest, StopSync) { sync_prefs()->SetFirstSetupComplete(); CreateSyncService(ProfileSyncService::MANUAL_START); SimulateTestUserSignin(); @@ -507,26 +388,7 @@ EXPECT_FALSE(sync_service()->IsSyncFeatureActive()); } -TEST_F(ProfileSyncServiceWithoutStandaloneTransportStartupTest, DisableSync) { - sync_prefs()->SetFirstSetupComplete(); - CreateSyncService(ProfileSyncService::MANUAL_START); - SimulateTestUserSignin(); - SetUpFakeSyncEngine(); - DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock(); - ON_CALL(*data_type_manager, state()) - .WillByDefault(Return(DataTypeManager::CONFIGURED)); - ON_CALL(*data_type_manager, IsNigoriEnabled()).WillByDefault(Return(true)); - - sync_service()->Initialize(); - - EXPECT_CALL(*data_type_manager, Stop(syncer::DISABLE_SYNC)); - sync_service()->StopAndClear(); - - EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled()); - EXPECT_FALSE(sync_service()->IsSyncFeatureActive()); -} - -TEST_F(ProfileSyncServiceWithStandaloneTransportStartupTest, DisableSync) { +TEST_F(ProfileSyncServiceStartupTest, DisableSync) { sync_prefs()->SetFirstSetupComplete(); CreateSyncService(ProfileSyncService::MANUAL_START); SimulateTestUserSignin(); @@ -615,58 +477,7 @@ sync_service()->GetDisableReasons()); } -TEST_F(ProfileSyncServiceWithoutStandaloneTransportStartupTest, SwitchManaged) { - sync_prefs()->SetFirstSetupComplete(); - CreateSyncService(ProfileSyncService::MANUAL_START); - SimulateTestUserSignin(); - SetUpFakeSyncEngine(); - DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock(); - EXPECT_CALL(*data_type_manager, Configure(_, _)); - ON_CALL(*data_type_manager, state()) - .WillByDefault(Return(DataTypeManager::CONFIGURED)); - ON_CALL(*data_type_manager, IsNigoriEnabled()).WillByDefault(Return(true)); - sync_service()->Initialize(); - EXPECT_TRUE(sync_service()->IsEngineInitialized()); - EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE, - sync_service()->GetDisableReasons()); - EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE, - sync_service()->GetTransportState()); - EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled()); - EXPECT_TRUE(sync_service()->IsSyncFeatureActive()); - - // The service should stop when switching to managed mode. - Mock::VerifyAndClearExpectations(data_type_manager); - EXPECT_CALL(*data_type_manager, state()) - .WillOnce(Return(DataTypeManager::CONFIGURED)); - EXPECT_CALL(*data_type_manager, Stop(syncer::DISABLE_SYNC)); - sync_prefs()->SetManagedForTest(true); - ASSERT_EQ(syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY, - sync_service()->GetDisableReasons()); - EXPECT_FALSE(sync_service()->IsEngineInitialized()); - EXPECT_EQ(syncer::SyncService::TransportState::DISABLED, - sync_service()->GetTransportState()); - EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled()); - EXPECT_FALSE(sync_service()->IsSyncFeatureActive()); - // Note that PSS no longer references |data_type_manager| after stopping. - - // When switching back to unmanaged, the state should change but sync should - // not start automatically because IsFirstSetupComplete() will be false and - // no setup is in progress. - // A new DataTypeManager should not be created. - Mock::VerifyAndClearExpectations(data_type_manager); - EXPECT_CALL(*component_factory(), CreateDataTypeManager(_, _, _, _, _, _)) - .Times(0); - sync_prefs()->SetManagedForTest(false); - ASSERT_EQ(syncer::SyncService::DISABLE_REASON_NONE, - sync_service()->GetDisableReasons()); - EXPECT_FALSE(sync_service()->IsEngineInitialized()); - EXPECT_EQ(syncer::SyncService::TransportState::WAITING_FOR_START_REQUEST, - sync_service()->GetTransportState()); - EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled()); - EXPECT_FALSE(sync_service()->IsSyncFeatureActive()); -} - -TEST_F(ProfileSyncServiceWithStandaloneTransportStartupTest, SwitchManaged) { +TEST_F(ProfileSyncServiceStartupTest, SwitchManaged) { sync_prefs()->SetFirstSetupComplete(); CreateSyncService(ProfileSyncService::MANUAL_START); SimulateTestUserSignin(); @@ -767,94 +578,7 @@ // ChromeOS does not support sign-in after startup (in particular, // IdentityManager::Observer::OnPrimaryAccountSet never gets called). #if !defined(OS_CHROMEOS) -TEST_F(ProfileSyncServiceWithoutStandaloneTransportStartupTest, - FullStartupSequenceFirstTime) { - // We've never completed startup. - ASSERT_FALSE(sync_prefs()->IsFirstSetupComplete()); - - MockSyncEngine* sync_engine = SetUpMockSyncEngine(); - EXPECT_CALL(*sync_engine, Initialize(_)).Times(0); - - DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock(); - EXPECT_CALL(*data_type_manager, Configure(_, _)).Times(0); - ON_CALL(*data_type_manager, state()) - .WillByDefault(Return(DataTypeManager::STOPPED)); - - // Note: Deferred startup is only enabled if SESSIONS is among the preferred - // data types. - CreateSyncService(ProfileSyncService::MANUAL_START, - syncer::ModelTypeSet(syncer::SESSIONS)); - sync_service()->Initialize(); - - // There is no signed-in user, but nothing else prevents Sync from starting. - EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN, - sync_service()->GetDisableReasons()); - EXPECT_EQ(syncer::SyncService::TransportState::DISABLED, - sync_service()->GetTransportState()); - - // Sign in. Now Sync is ready to start, just waiting for a prod. - SimulateTestUserSignin(); - EXPECT_EQ(syncer::SyncService::TransportState::WAITING_FOR_START_REQUEST, - sync_service()->GetTransportState()); - - // Once we give the service a prod by initiating Sync setup, it'll start and - // initialize the engine. Since this is the initial Sync start, this will not - // be deferred. - EXPECT_CALL(*sync_engine, Initialize(_)); - auto setup_in_progress_handle = sync_service()->GetSetupInProgressHandle(); - EXPECT_EQ(syncer::SyncService::TransportState::INITIALIZING, - sync_service()->GetTransportState()); - - // Once the engine calls back and says it's initialized, we're just waiting - // for the user to finish the initial configuration (choosing data types etc.) - // before actually syncing data. - sync_service()->OnEngineInitialized( - syncer::ModelTypeSet(), syncer::WeakHandle<syncer::JsBackend>(), - syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(), "test-guid", - "test-session-name", "test-birthday", "test-bag-of-chips", - /*success=*/true); - ASSERT_TRUE(sync_service()->IsEngineInitialized()); - EXPECT_EQ(syncer::SyncService::TransportState::PENDING_DESIRED_CONFIGURATION, - sync_service()->GetTransportState()); - EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled()); - - // Once the user finishes the initial setup, the service can actually start - // configuring the data types. Just marking the initial setup as complete - // isn't enough though, because setup is still considered in progress (we - // haven't released the setup-in-progress handle). - sync_service()->GetUserSettings()->SetFirstSetupComplete(); - EXPECT_EQ(syncer::SyncService::TransportState::PENDING_DESIRED_CONFIGURATION, - sync_service()->GetTransportState()); - EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled()); - - // Releasing the setup in progress handle lets the service actually configure - // the DataTypeManager. - EXPECT_CALL(*data_type_manager, Configure(_, _)) - .WillOnce(InvokeWithoutArgs(sync_service(), - &ProfileSyncService::OnConfigureStart)); - ON_CALL(*data_type_manager, state()) - .WillByDefault(Return(DataTypeManager::CONFIGURING)); - setup_in_progress_handle.reset(); - // While DataTypeManager configuration is ongoing, the overall state is still - // CONFIGURING. - EXPECT_EQ(syncer::SyncService::TransportState::CONFIGURING, - sync_service()->GetTransportState()); - EXPECT_TRUE(sync_service()->IsSyncFeatureActive()); - - // Finally, once the DataTypeManager says it's done with configuration, Sync - // is actually fully up and running. - DataTypeManager::ConfigureResult configure_result( - DataTypeManager::OK, syncer::ModelTypeSet(syncer::SESSIONS)); - ON_CALL(*data_type_manager, state()) - .WillByDefault(Return(DataTypeManager::CONFIGURED)); - sync_service()->OnConfigureDone(configure_result); - EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE, - sync_service()->GetTransportState()); - EXPECT_TRUE(sync_service()->IsSyncFeatureActive()); -} - -TEST_F(ProfileSyncServiceWithStandaloneTransportStartupTest, - FullStartupSequenceFirstTime) { +TEST_F(ProfileSyncServiceStartupTest, FullStartupSequenceFirstTime) { // We've never completed startup. ASSERT_FALSE(sync_prefs()->IsFirstSetupComplete());
diff --git a/components/browser_sync/profile_sync_service_unittest.cc b/components/browser_sync/profile_sync_service_unittest.cc index d036de25..33fab58 100644 --- a/components/browser_sync/profile_sync_service_unittest.cc +++ b/components/browser_sync/profile_sync_service_unittest.cc
@@ -298,32 +298,6 @@ std::unique_ptr<ProfileSyncService> service_; }; -class ProfileSyncServiceWithStandaloneTransportTest - : public ProfileSyncServiceTest { - protected: - ProfileSyncServiceWithStandaloneTransportTest() { - feature_list_.InitAndEnableFeature(switches::kSyncStandaloneTransport); - } - - ~ProfileSyncServiceWithStandaloneTransportTest() override {} - - private: - base::test::ScopedFeatureList feature_list_; -}; - -class ProfileSyncServiceWithoutStandaloneTransportTest - : public ProfileSyncServiceTest { - protected: - ProfileSyncServiceWithoutStandaloneTransportTest() { - feature_list_.InitAndDisableFeature(switches::kSyncStandaloneTransport); - } - - ~ProfileSyncServiceWithoutStandaloneTransportTest() override {} - - private: - base::test::ScopedFeatureList feature_list_; -}; - // Verify that the server URLs are sane. TEST_F(ProfileSyncServiceTest, InitialState) { CreateService(ProfileSyncService::AUTO_START); @@ -363,41 +337,8 @@ } // Verify that an initialization where first setup is not complete does not -// start up the backend. -TEST_F(ProfileSyncServiceWithoutStandaloneTransportTest, NeedsConfirmation) { - SignIn(); - CreateService(ProfileSyncService::MANUAL_START); - - syncer::SyncPrefs sync_prefs(prefs()); - base::Time now = base::Time::Now(); - sync_prefs.SetLastSyncedTime(now); - sync_prefs.SetDataTypesConfiguration(/*keep_everything_synced=*/true, - syncer::UserTypes(), - syncer::UserSelectableTypes()); - service()->Initialize(); - - EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE, - service()->GetDisableReasons()); - // Note: At this point the engine *can* start, but nothing has kicked it off - // (usually that happens via getting and then releasing a - // SyncSetupInProgressHandle), so the state is still WAITING_FOR_START_REQUEST - // and not PENDING_DESIRED_CONFIGURATION. - EXPECT_EQ(syncer::SyncService::TransportState::WAITING_FOR_START_REQUEST, - service()->GetTransportState()); - - // Once we kick off initialization by getting and releasing a setup handle, - // the state goes to PENDING_DESIRED_CONFIGURATION. - service()->GetSetupInProgressHandle(); - EXPECT_EQ(syncer::SyncService::TransportState::PENDING_DESIRED_CONFIGURATION, - service()->GetTransportState()); - - // The last sync time shouldn't be cleared. - // TODO(zea): figure out a way to check that the directory itself wasn't - // cleared. - EXPECT_EQ(now, sync_prefs.GetLastSyncedTime()); -} - -TEST_F(ProfileSyncServiceWithStandaloneTransportTest, NeedsConfirmation) { +// start up Sync-the-feature. +TEST_F(ProfileSyncServiceTest, NeedsConfirmation) { SignIn(); CreateService(ProfileSyncService::MANUAL_START); @@ -521,39 +462,7 @@ } // Test SetSyncRequested(false) before we've initialized the backend. -TEST_F(ProfileSyncServiceWithoutStandaloneTransportTest, EarlyRequestStop) { - CreateService(ProfileSyncService::AUTO_START); - // Set up a fake sync engine that will not immediately finish initialization. - EXPECT_CALL(*component_factory(), CreateSyncEngine(_, _, _)) - .WillOnce(ReturnNewFakeSyncEngineNoReturn()); - SignIn(); - InitializeForNthSync(); - - ASSERT_EQ(syncer::SyncService::TransportState::INITIALIZING, - service()->GetTransportState()); - - // Request stop. Sync should get disabled. - service()->GetUserSettings()->SetSyncRequested(false); - EXPECT_EQ(syncer::SyncService::DISABLE_REASON_USER_CHOICE, - service()->GetDisableReasons()); - EXPECT_EQ(syncer::SyncService::TransportState::DISABLED, - service()->GetTransportState()); - EXPECT_FALSE(service()->IsSyncFeatureEnabled()); - - // Request start again, this time with an engine that does get initialized. - // Sync should become active. - EXPECT_CALL(*component_factory(), CreateSyncEngine(_, _, _)) - .WillOnce(ReturnNewFakeSyncEngine()); - service()->GetUserSettings()->SetSyncRequested(true); - EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE, - service()->GetDisableReasons()); - EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE, - service()->GetTransportState()); - EXPECT_TRUE(service()->IsSyncFeatureActive()); - EXPECT_TRUE(service()->IsSyncFeatureEnabled()); -} - -TEST_F(ProfileSyncServiceWithStandaloneTransportTest, EarlyRequestStop) { +TEST_F(ProfileSyncServiceTest, EarlyRequestStop) { CreateService(ProfileSyncService::AUTO_START); // Set up a fake sync engine that will not immediately finish initialization. EXPECT_CALL(*component_factory(), CreateSyncEngine(_, _, _)) @@ -587,43 +496,7 @@ } // Test SetSyncRequested(false) after we've initialized the backend. -TEST_F(ProfileSyncServiceWithoutStandaloneTransportTest, - DisableAndEnableSyncTemporarily) { - CreateService(ProfileSyncService::AUTO_START); - SignIn(); - InitializeForNthSync(); - - ASSERT_FALSE(prefs()->GetBoolean(syncer::prefs::kSyncSuppressStart)); - ASSERT_EQ(syncer::SyncService::DISABLE_REASON_NONE, - service()->GetDisableReasons()); - ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE, - service()->GetTransportState()); - ASSERT_TRUE(service()->IsSyncFeatureActive()); - ASSERT_TRUE(service()->IsSyncFeatureEnabled()); - - testing::Mock::VerifyAndClearExpectations(component_factory()); - - service()->GetUserSettings()->SetSyncRequested(false); - EXPECT_TRUE(prefs()->GetBoolean(syncer::prefs::kSyncSuppressStart)); - EXPECT_EQ(syncer::SyncService::DISABLE_REASON_USER_CHOICE, - service()->GetDisableReasons()); - EXPECT_EQ(syncer::SyncService::TransportState::DISABLED, - service()->GetTransportState()); - EXPECT_FALSE(service()->IsSyncFeatureActive()); - EXPECT_FALSE(service()->IsSyncFeatureEnabled()); - - service()->GetUserSettings()->SetSyncRequested(true); - EXPECT_FALSE(prefs()->GetBoolean(syncer::prefs::kSyncSuppressStart)); - EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE, - service()->GetDisableReasons()); - EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE, - service()->GetTransportState()); - EXPECT_TRUE(service()->IsSyncFeatureActive()); - EXPECT_TRUE(service()->IsSyncFeatureEnabled()); -} - -TEST_F(ProfileSyncServiceWithStandaloneTransportTest, - DisableAndEnableSyncTemporarily) { +TEST_F(ProfileSyncServiceTest, DisableAndEnableSyncTemporarily) { CreateService(ProfileSyncService::AUTO_START); SignIn(); InitializeForNthSync(); @@ -771,7 +644,10 @@ // Checks that CREDENTIALS_REJECTED_BY_CLIENT resets the access token and stops // Sync. Regression test for https://crbug.com/824791. -TEST_F(ProfileSyncServiceTest, CredentialsRejectedByClient) { +TEST_F(ProfileSyncServiceTest, CredentialsRejectedByClient_StopSync) { + base::test::ScopedFeatureList feature; + feature.InitAndEnableFeature(switches::kStopSyncInPausedState); + syncer::SyncCredentials init_credentials; CreateService(ProfileSyncService::AUTO_START); @@ -830,6 +706,72 @@ service()->RemoveObserver(&observer); } +TEST_F(ProfileSyncServiceTest, CredentialsRejectedByClient_DoNotStopSync) { + base::test::ScopedFeatureList feature; + feature.InitAndDisableFeature(switches::kStopSyncInPausedState); + + syncer::SyncCredentials init_credentials; + + bool invalidate_credentials_called = false; + base::RepeatingClosure invalidate_credentials_callback = + base::BindRepeating([](bool* called) { *called = true; }, + base::Unretained(&invalidate_credentials_called)); + + CreateService(ProfileSyncService::AUTO_START); + SignIn(); + EXPECT_CALL(*component_factory(), CreateSyncEngine(_, _, _)) + .WillOnce( + Return(ByMove(std::make_unique<FakeSyncEngineCollectCredentials>( + &init_credentials, invalidate_credentials_callback)))); + InitializeForNthSync(); + ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE, + service()->GetTransportState()); + + TestSyncServiceObserver observer; + service()->AddObserver(&observer); + + const std::string primary_account_id = + identity_manager()->GetPrimaryAccountId(); + + // Make sure the expected credentials (correct account_id, empty access token) + // were passed to the SyncEngine. + ASSERT_EQ(primary_account_id, init_credentials.account_id); + ASSERT_TRUE(init_credentials.sync_token.empty()); + + // At this point, the real SyncEngine would try to connect to the server, fail + // (because it has no access token), and eventually call + // OnConnectionStatusChange(CONNECTION_AUTH_ERROR). Since our fake SyncEngine + // doesn't do any of this, call that explicitly here. + service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR); + + base::RunLoop().RunUntilIdle(); + ASSERT_FALSE(service()->GetAccessTokenForTest().empty()); + ASSERT_EQ(GoogleServiceAuthError::AuthErrorNone(), service()->GetAuthError()); + ASSERT_EQ(GoogleServiceAuthError::AuthErrorNone(), observer.auth_error()); + + // Simulate the credentials getting locally rejected by the client by setting + // the refresh token to a special invalid value. + identity_test_env()->SetInvalidRefreshTokenForPrimaryAccount(); + const GoogleServiceAuthError rejected_by_client = + GoogleServiceAuthError::FromInvalidGaiaCredentialsReason( + GoogleServiceAuthError::InvalidGaiaCredentialsReason:: + CREDENTIALS_REJECTED_BY_CLIENT); + ASSERT_EQ(rejected_by_client, + identity_test_env() + ->identity_manager() + ->GetErrorStateOfRefreshTokenForAccount(primary_account_id)); + EXPECT_TRUE(service()->GetAccessTokenForTest().empty()); + EXPECT_TRUE(invalidate_credentials_called); + + // The observer should have been notified of the auth error state. + EXPECT_EQ(rejected_by_client, observer.auth_error()); + // The Sync engine should still be running. + EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE, + service()->GetTransportState()); + + service()->RemoveObserver(&observer); +} + // CrOS does not support signout. #if !defined(OS_CHROMEOS) TEST_F(ProfileSyncServiceTest, SignOutRevokeAccessToken) { @@ -876,28 +818,7 @@ #endif // Verify that LastSyncedTime and local DeviceInfo is cleared on sign out. -TEST_F(ProfileSyncServiceWithoutStandaloneTransportTest, ClearDataOnSignOut) { - SignIn(); - CreateService(ProfileSyncService::AUTO_START); - InitializeForNthSync(); - ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE, - service()->GetTransportState()); - ASSERT_LT(base::Time::Now() - service()->GetLastSyncedTime(), - base::TimeDelta::FromMinutes(1)); - ASSERT_TRUE(local_device_info_provider()->GetLocalDeviceInfo()); - - // Sign out. - service()->StopAndClear(); - - EXPECT_EQ(syncer::SyncService::TransportState::DISABLED, - service()->GetTransportState()); - EXPECT_FALSE(service()->IsSyncFeatureEnabled()); - - EXPECT_TRUE(service()->GetLastSyncedTime().is_null()); - EXPECT_FALSE(local_device_info_provider()->GetLocalDeviceInfo()); -} - -TEST_F(ProfileSyncServiceWithStandaloneTransportTest, ClearDataOnSignOut) { +TEST_F(ProfileSyncServiceTest, ClearDataOnSignOut) { SignIn(); CreateService(ProfileSyncService::AUTO_START); InitializeForNthSync(); @@ -921,7 +842,7 @@ EXPECT_TRUE(local_device_info_provider()->GetLocalDeviceInfo()); } -TEST_F(ProfileSyncServiceWithStandaloneTransportTest, CancelSyncAfterSignOut) { +TEST_F(ProfileSyncServiceTest, CancelSyncAfterSignOut) { SignIn(); CreateService(ProfileSyncService::AUTO_START); InitializeForNthSync(); @@ -1185,44 +1106,7 @@ // Test that when ProfileSyncService receives actionable error // DISABLE_SYNC_ON_CLIENT it disables sync and signs out. -TEST_F(ProfileSyncServiceWithoutStandaloneTransportTest, DisableSyncOnClient) { - SignIn(); - CreateService(ProfileSyncService::AUTO_START); - InitializeForNthSync(); - - ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE, - service()->GetTransportState()); - ASSERT_LT(base::Time::Now() - service()->GetLastSyncedTime(), - base::TimeDelta::FromMinutes(1)); - ASSERT_TRUE(local_device_info_provider()->GetLocalDeviceInfo()); - - syncer::SyncProtocolError client_cmd; - client_cmd.action = syncer::DISABLE_SYNC_ON_CLIENT; - service()->OnActionableError(client_cmd); - -#if defined(OS_CHROMEOS) - // ChromeOS does not support signout. - EXPECT_TRUE(identity_manager()->HasPrimaryAccount()); - EXPECT_EQ(syncer::SyncService::DISABLE_REASON_USER_CHOICE, - service()->GetDisableReasons()); - EXPECT_EQ(syncer::SyncService::TransportState::DISABLED, - service()->GetTransportState()); -#else - EXPECT_FALSE(identity_manager()->HasPrimaryAccount()); - EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN | - syncer::SyncService::DISABLE_REASON_USER_CHOICE, - service()->GetDisableReasons()); - EXPECT_EQ(syncer::SyncService::TransportState::DISABLED, - service()->GetTransportState()); - EXPECT_TRUE(service()->GetLastSyncedTime().is_null()); - EXPECT_FALSE(local_device_info_provider()->GetLocalDeviceInfo()); -#endif - - EXPECT_FALSE(service()->IsSyncFeatureEnabled()); - EXPECT_FALSE(service()->IsSyncFeatureActive()); -} - -TEST_F(ProfileSyncServiceWithStandaloneTransportTest, DisableSyncOnClient) { +TEST_F(ProfileSyncServiceTest, DisableSyncOnClient) { SignIn(); CreateService(ProfileSyncService::AUTO_START); InitializeForNthSync();
diff --git a/components/browser_sync/sync_auth_manager.cc b/components/browser_sync/sync_auth_manager.cc index ee799f3..7bfa58f 100644 --- a/components/browser_sync/sync_auth_manager.cc +++ b/components/browser_sync/sync_auth_manager.cc
@@ -357,8 +357,7 @@ DCHECK(registered_for_auth_notifications_); return syncer::DetermineAccountToUse( identity_manager_, - base::FeatureList::IsEnabled(switches::kSyncStandaloneTransport) && - base::FeatureList::IsEnabled(switches::kSyncSupportSecondaryAccount)); + base::FeatureList::IsEnabled(switches::kSyncSupportSecondaryAccount)); } bool SyncAuthManager::UpdateSyncAccountIfNecessary() {
diff --git a/components/browser_sync/sync_auth_manager_unittest.cc b/components/browser_sync/sync_auth_manager_unittest.cc index 24f2376..e0509f7 100644 --- a/components/browser_sync/sync_auth_manager_unittest.cc +++ b/components/browser_sync/sync_auth_manager_unittest.cc
@@ -600,10 +600,7 @@ TEST_F(SyncAuthManagerTest, UsesCookieJarIfFeatureEnabled) { base::test::ScopedFeatureList features; - features.InitWithFeatures( - /*enabled_features=*/{switches::kSyncStandaloneTransport, - switches::kSyncSupportSecondaryAccount}, - /*disabled_features=*/{}); + features.InitAndEnableFeature(switches::kSyncSupportSecondaryAccount); auto auth_manager = CreateAuthManager(); auth_manager->RegisterForAuthNotifications(); @@ -624,10 +621,7 @@ TEST_F(SyncAuthManagerTest, DropsAccountWhenCookieGoesAway) { base::test::ScopedFeatureList features; - features.InitWithFeatures( - /*enabled_features=*/{switches::kSyncStandaloneTransport, - switches::kSyncSupportSecondaryAccount}, - /*disabled_features=*/{}); + features.InitAndEnableFeature(switches::kSyncSupportSecondaryAccount); auto auth_manager = CreateAuthManager(); auth_manager->RegisterForAuthNotifications(); @@ -653,10 +647,7 @@ TEST_F(SyncAuthManagerTest, DropsAccountWhenRefreshTokenGoesAway) { base::test::ScopedFeatureList features; - features.InitWithFeatures( - /*enabled_features=*/{switches::kSyncStandaloneTransport, - switches::kSyncSupportSecondaryAccount}, - /*disabled_features=*/{}); + features.InitAndEnableFeature(switches::kSyncSupportSecondaryAccount); auto auth_manager = CreateAuthManager(); auth_manager->RegisterForAuthNotifications(); @@ -682,10 +673,7 @@ TEST_F(SyncAuthManagerTest, PrefersPrimaryAccountOverCookie) { base::test::ScopedFeatureList features; - features.InitWithFeatures( - /*enabled_features=*/{switches::kSyncStandaloneTransport, - switches::kSyncSupportSecondaryAccount}, - /*disabled_features=*/{}); + features.InitAndEnableFeature(switches::kSyncSupportSecondaryAccount); auto auth_manager = CreateAuthManager(); auth_manager->RegisterForAuthNotifications(); @@ -711,10 +699,7 @@ TEST_F(SyncAuthManagerTest, OnlyUsesFirstCookieAccount) { base::test::ScopedFeatureList features; - features.InitWithFeatures( - /*enabled_features=*/{switches::kSyncStandaloneTransport, - switches::kSyncSupportSecondaryAccount}, - /*disabled_features=*/{}); + features.InitAndEnableFeature(switches::kSyncSupportSecondaryAccount); auto auth_manager = CreateAuthManager(); auth_manager->RegisterForAuthNotifications();
diff --git a/components/certificate_transparency/log_dns_client.cc b/components/certificate_transparency/log_dns_client.cc index d02e206..3d47b4a 100644 --- a/components/certificate_transparency/log_dns_client.cc +++ b/components/certificate_transparency/log_dns_client.cc
@@ -168,12 +168,15 @@ ~AuditProofQueryImpl() override; // Begins the process of getting an audit proof for the CT log entry with a - // leaf hash of |leaf_hash|. The proof will be for a tree of size |tree_size|. - // If it cannot be obtained synchronously, net::ERR_IO_PENDING will be - // returned and |callback| will be invoked when the operation has completed - // asynchronously. If the operation is cancelled (by deleting the - // AuditProofQueryImpl), |cancellation_callback| will be invoked. + // leaf hash of |leaf_hash|. If |lookup_securely| is true, only secure DNS + // lookups will be performed, otherwise only insecure DNS lookups will be + // performed. The proof will be for a tree of size |tree_size|. If the proof + // cannot be obtained synchronously, net::ERR_IO_PENDING will be returned and + // |callback| will be invoked when the operation has completed asynchronously. + // If the operation is cancelled (by deleting the AuditProofQueryImpl), + // |cancellation_callback| will be invoked. net::Error Start(std::string leaf_hash, + bool lookup_securely, uint64_t tree_size, net::CompletionOnceCallback callback, base::OnceClosure cancellation_callback); @@ -242,6 +245,8 @@ std::string domain_for_log_; // The Merkle leaf hash of the CT log entry an audit proof is required for. std::string leaf_hash_; + // Whether the DNS request should be sent securely or insecurely. + bool lookup_securely_; // The audit proof to populate. net::ct::MerkleAuditProof proof_; // The callback to invoke when the query is complete. @@ -289,6 +294,7 @@ // |leaf_hash| is not a const-ref to allow callers to std::move that string into // the method, avoiding the need to make a copy. net::Error AuditProofQueryImpl::Start(std::string leaf_hash, + bool lookup_securely, uint64_t tree_size, net::CompletionOnceCallback callback, base::OnceClosure cancellation_callback) { @@ -297,6 +303,7 @@ start_time_ = base::TimeTicks::Now(); proof_.tree_size = tree_size; leaf_hash_ = std::move(leaf_hash); + lookup_securely_ = lookup_securely; callback_ = std::move(callback); cancellation_callback_ = std::move(cancellation_callback); // The first step in the query is to request the leaf index corresponding to @@ -480,7 +487,8 @@ qname, net::dns_protocol::kTypeTXT, base::BindOnce(&AuditProofQueryImpl::OnDnsTransactionComplete, weak_ptr_factory_.GetWeakPtr()), - net_log_, net::SecureDnsMode::AUTOMATIC); + net_log_, + lookup_securely_ ? net::SecureDnsMode::SECURE : net::SecureDnsMode::OFF); DCHECK(url_request_context_); current_dns_transaction_->SetRequestContext(url_request_context_); @@ -524,6 +532,7 @@ net::Error LogDnsClient::QueryAuditProof( base::StringPiece domain_for_log, std::string leaf_hash, + bool lookup_securely, uint64_t tree_size, std::unique_ptr<AuditProofQuery>* out_query, const net::CompletionCallback& callback) { @@ -543,7 +552,7 @@ ++in_flight_queries_; - return query->Start(std::move(leaf_hash), tree_size, + return query->Start(std::move(leaf_hash), lookup_securely, tree_size, base::BindOnce(&LogDnsClient::QueryAuditProofComplete, base::Unretained(this), callback), base::BindOnce(&LogDnsClient::QueryAuditProofCancelled,
diff --git a/components/certificate_transparency/log_dns_client.h b/components/certificate_transparency/log_dns_client.h index 31f2bab..0376f61 100644 --- a/components/certificate_transparency/log_dns_client.h +++ b/components/certificate_transparency/log_dns_client.h
@@ -78,6 +78,10 @@ // The |leaf_hash| is the SHA-256 Merkle leaf hash (see RFC6962, section 2.1). // The size of the CT log tree, for which the proof is requested, must be // provided in |tree_size|. + // The field |lookup_securely| specifies whether DNS lookups should be + // performed securely or insecurely. This value should be set according to + // whether the hostname lookup was resolved securely or not in order to + // help achieve resolver consistency between the hostname and proof lookups. // A handle to the query will be placed in |out_query|. The audit proof can be // obtained from that once the query completes. Deleting this handle before // the query completes will cancel it. It must not outlive the LogDnsClient. @@ -96,6 +100,7 @@ // not a SHA-256 hash. net::Error QueryAuditProof(base::StringPiece domain_for_log, std::string leaf_hash, + bool lookup_securely, uint64_t tree_size, std::unique_ptr<AuditProofQuery>* out_query, const net::CompletionCallback& callback);
diff --git a/components/certificate_transparency/log_dns_client_unittest.cc b/components/certificate_transparency/log_dns_client_unittest.cc index 90776427..93da272 100644 --- a/components/certificate_transparency/log_dns_client_unittest.cc +++ b/components/certificate_transparency/log_dns_client_unittest.cc
@@ -25,6 +25,7 @@ #include "net/cert/signed_certificate_timestamp.h" #include "net/dns/dns_client.h" #include "net/dns/dns_config.h" +#include "net/dns/dns_test_util.h" #include "net/dns/public/dns_protocol.h" #include "net/log/net_log.h" #include "net/test/gtest_util.h" @@ -132,6 +133,14 @@ net::NetLogWithSource(), max_concurrent_queries); } + std::unique_ptr<LogDnsClient> CreateRuleBasedLogDnsClient( + net::MockDnsClientRuleList rules) { + return std::make_unique<LogDnsClient>( + std::make_unique<net::MockDnsClient>(net::DnsConfig(), + std::move(rules)), + new net::TestURLRequestContext(), net::NetLogWithSource(), 0); + } + // Convenience function for calling QueryAuditProof synchronously. template <typename... Types> net::Error QueryAuditProof(Types&&... args) { @@ -163,8 +172,10 @@ kLeafIndexQnames[0], net::dns_protocol::kRcodeNXDOMAIN)); std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &query), - IsError(net::ERR_NAME_NOT_RESOLVED)); + ASSERT_THAT( + QueryAuditProof("ct.test", kLeafHashes[0], false /* lookup_securely */, + kTreeSizes[0], &query), + IsError(net::ERR_NAME_NOT_RESOLVED)); histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::ERR_NAME_NOT_RESOLVED, 1); histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, @@ -179,8 +190,10 @@ kLeafIndexQnames[0], net::dns_protocol::kRcodeSERVFAIL)); std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &query), - IsError(net::ERR_DNS_SERVER_FAILED)); + ASSERT_THAT( + QueryAuditProof("ct.test", kLeafHashes[0], false /* lookup_securely */, + kTreeSizes[0], &query), + IsError(net::ERR_DNS_SERVER_FAILED)); histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::ERR_DNS_SERVER_FAILED, 1); histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, @@ -195,8 +208,10 @@ kLeafIndexQnames[0], net::dns_protocol::kRcodeREFUSED)); std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &query), - IsError(net::ERR_DNS_SERVER_FAILED)); + ASSERT_THAT( + QueryAuditProof("ct.test", kLeafHashes[0], false /* lookup_securely */, + kTreeSizes[0], &query), + IsError(net::ERR_DNS_SERVER_FAILED)); histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::ERR_DNS_SERVER_FAILED, 1); histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, @@ -226,7 +241,8 @@ std::unique_ptr<LogDnsClient::AuditProofQuery> query; ASSERT_THAT( - QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &query), + QueryAuditProof("ct.test", kLeafHashes[0], false /* lookup_securely */, + kTreeSizes[0], &query), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); histograms.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::ERR_DNS_MALFORMED_RESPONSE, 1); @@ -239,19 +255,22 @@ TEST_P(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLogDomainIsEmpty) { std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("", kLeafHashes[0], kTreeSizes[0], &query), + ASSERT_THAT(QueryAuditProof("", kLeafHashes[0], false /* lookup_securely */, + kTreeSizes[0], &query), IsError(net::ERR_INVALID_ARGUMENT)); } TEST_P(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLeafHashIsInvalid) { std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", "foo", kTreeSizes[0], &query), + ASSERT_THAT(QueryAuditProof("ct.test", "foo", false /* lookup_securely */, + kTreeSizes[0], &query), IsError(net::ERR_INVALID_ARGUMENT)); } TEST_P(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLeafHashIsEmpty) { std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", "", kTreeSizes[0], &query), + ASSERT_THAT(QueryAuditProof("ct.test", "", false /* lookup_securely */, + kTreeSizes[0], &query), IsError(net::ERR_INVALID_ARGUMENT)); } @@ -261,8 +280,10 @@ kLeafIndexQnames[0], net::ERR_CONNECTION_REFUSED)); std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &query), - IsError(net::ERR_CONNECTION_REFUSED)); + ASSERT_THAT( + QueryAuditProof("ct.test", kLeafHashes[0], false /* lookup_securely */, + kTreeSizes[0], &query), + IsError(net::ERR_CONNECTION_REFUSED)); histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::ERR_CONNECTION_REFUSED, 1); histograms_.ExpectTotalCount(kLeafIndexRcodeHistogram, 0); @@ -275,8 +296,10 @@ ASSERT_TRUE(mock_dns_.ExpectRequestAndTimeout(kLeafIndexQnames[0])); std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &query), - IsError(net::ERR_DNS_TIMED_OUT)); + ASSERT_THAT( + QueryAuditProof("ct.test", kLeafHashes[0], false /* lookup_securely */, + kTreeSizes[0], &query), + IsError(net::ERR_DNS_TIMED_OUT)); histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::ERR_DNS_TIMED_OUT, 1); histograms_.ExpectTotalCount(kLeafIndexRcodeHistogram, 0); @@ -304,7 +327,8 @@ } std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &query), + ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 999999, &query), IsOk()); const net::ct::MerkleAuditProof& proof = query->GetProof(); EXPECT_THAT(proof.leaf_index, Eq(123456u)); @@ -347,7 +371,8 @@ audit_proof.end())); std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &query), + ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 999999, &query), IsOk()); const net::ct::MerkleAuditProof& proof = query->GetProof(); EXPECT_THAT(proof.leaf_index, Eq(123456u)); @@ -370,7 +395,8 @@ "0.123456.999999.tree.ct.test.", net::dns_protocol::kRcodeNXDOMAIN)); std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &query), + ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 999999, &query), IsError(net::ERR_NAME_NOT_RESOLVED)); histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); @@ -390,7 +416,8 @@ "0.123456.999999.tree.ct.test.", net::dns_protocol::kRcodeSERVFAIL)); std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &query), + ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 999999, &query), IsError(net::ERR_DNS_SERVER_FAILED)); histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); @@ -410,7 +437,8 @@ "0.123456.999999.tree.ct.test.", net::dns_protocol::kRcodeREFUSED)); std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &query), + ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 999999, &query), IsError(net::ERR_DNS_SERVER_FAILED)); histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); @@ -433,7 +461,8 @@ "0.123456.999999.tree.ct.test.", std::vector<base::StringPiece>())); std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &query), + ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 999999, &query), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); @@ -466,7 +495,8 @@ {first_chunk_of_proof, second_chunk_of_proof})); std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &query), + ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 999999, &query), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); @@ -489,7 +519,8 @@ "0.123456.999999.tree.ct.test.", audit_proof.begin(), audit_proof.end())); std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &query), + ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 999999, &query), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); @@ -511,7 +542,8 @@ "0.123456.999999.tree.ct.test.", audit_proof.begin(), audit_proof.end())); std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &query), + ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 999999, &query), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); @@ -532,7 +564,8 @@ "0.123456.999999.tree.ct.test.", audit_proof.begin(), audit_proof.end())); std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &query), + ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 999999, &query), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); @@ -550,7 +583,8 @@ mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 123456, &query), + ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 123456, &query), IsError(net::ERR_INVALID_ARGUMENT)); } @@ -560,7 +594,8 @@ mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 999999)); std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 123456, &query), + ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 123456, &query), IsError(net::ERR_INVALID_ARGUMENT)); } @@ -572,7 +607,8 @@ "0.123456.999999.tree.ct.test.", net::ERR_CONNECTION_REFUSED)); std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &query), + ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 999999, &query), IsError(net::ERR_CONNECTION_REFUSED)); histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); @@ -591,7 +627,8 @@ mock_dns_.ExpectRequestAndTimeout("0.123456.999999.tree.ct.test.")); std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &query), + ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 999999, &query), IsError(net::ERR_DNS_TIMED_OUT)); histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); @@ -665,7 +702,8 @@ // Start query. std::unique_ptr<LogDnsClient::AuditProofQuery> query; net::TestCompletionCallback callback; - ASSERT_THAT(log_client.QueryAuditProof("ct.test", kLeafHashes[0], 999999, + ASSERT_THAT(log_client.QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 999999, &query, callback.callback()), IsError(net::ERR_IO_PENDING)); @@ -753,10 +791,10 @@ // Start the queries. for (size_t i = 0; i < kNumOfParallelQueries; ++i) { - ASSERT_THAT( - log_client->QueryAuditProof("ct.test", kLeafHashes[i], kTreeSizes[i], - &queries[i], callbacks[i].callback()), - IsError(net::ERR_IO_PENDING)) + ASSERT_THAT(log_client->QueryAuditProof( + "ct.test", kLeafHashes[i], false /* lookup_securely */, + kTreeSizes[i], &queries[i], callbacks[i].callback()), + IsError(net::ERR_IO_PENDING)) << "query #" << i; } @@ -790,19 +828,17 @@ ASSERT_TRUE( mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - // It should require 3 requests to collect the entire audit proof, as there is - // only space for 7 nodes per TXT record. One node is 32 bytes long and the - // TXT RDATA can have a maximum length of 255 bytes (255 / 32). - // Rate limiting should not interfere with these requests. - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "0.123456.999999.tree.ct.test.", audit_proof.begin(), - audit_proof.begin() + 7)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "7.123456.999999.tree.ct.test.", audit_proof.begin() + 7, - audit_proof.begin() + 14)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "14.123456.999999.tree.ct.test.", audit_proof.begin() + 14, - audit_proof.end())); + // It takes a number of DNS requests to retrieve the entire |audit_proof| + // (see |kMaxProofNodesPerDnsResponse|). + for (size_t nodes_begin = 0; nodes_begin < audit_proof.size(); + nodes_begin += kMaxProofNodesPerDnsResponse) { + const size_t nodes_end = std::min( + nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size()); + + ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( + base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin), + audit_proof.begin() + nodes_begin, audit_proof.begin() + nodes_end)); + } const size_t kMaxConcurrentQueries = 1; std::unique_ptr<LogDnsClient> log_client = @@ -811,13 +847,15 @@ // Try to start the queries. std::unique_ptr<LogDnsClient::AuditProofQuery> query1; net::TestCompletionCallback callback1; - ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], 999999, + ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 999999, &query1, callback1.callback()), IsError(net::ERR_IO_PENDING)); std::unique_ptr<LogDnsClient::AuditProofQuery> query2; net::TestCompletionCallback callback2; - ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[1], 999999, + ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[1], + false /* lookup_securely */, 999999, &query2, callback2.callback()), IsError(net::ERR_TEMPORARILY_THROTTLED)); @@ -831,19 +869,20 @@ // Try a third query, which should succeed now that the first is finished. ASSERT_TRUE( mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[2], 666)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "0.666.999999.tree.ct.test.", audit_proof.begin(), - audit_proof.begin() + 7)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "7.666.999999.tree.ct.test.", audit_proof.begin() + 7, - audit_proof.begin() + 14)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "14.666.999999.tree.ct.test.", audit_proof.begin() + 14, - audit_proof.end())); + for (size_t nodes_begin = 0; nodes_begin < audit_proof.size(); + nodes_begin += kMaxProofNodesPerDnsResponse) { + const size_t nodes_end = std::min( + nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size()); + + ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( + base::StringPrintf("%zu.666.999999.tree.ct.test.", nodes_begin), + audit_proof.begin() + nodes_begin, audit_proof.begin() + nodes_end)); + } std::unique_ptr<LogDnsClient::AuditProofQuery> query3; net::TestCompletionCallback callback3; - ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[2], 999999, + ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[2], + false /* lookup_securely */, 999999, &query3, callback3.callback()), IsError(net::ERR_IO_PENDING)); @@ -867,15 +906,15 @@ ASSERT_TRUE( mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "0.123456.999999.tree.ct.test.", audit_proof.begin(), - audit_proof.begin() + 7)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "7.123456.999999.tree.ct.test.", audit_proof.begin() + 7, - audit_proof.begin() + 14)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "14.123456.999999.tree.ct.test.", audit_proof.begin() + 14, - audit_proof.end())); + for (size_t nodes_begin = 0; nodes_begin < audit_proof.size(); + nodes_begin += kMaxProofNodesPerDnsResponse) { + const size_t nodes_end = std::min( + nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size()); + + ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( + base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin), + audit_proof.begin() + nodes_begin, audit_proof.begin() + nodes_end)); + } const size_t kMaxConcurrentQueries = 1; std::unique_ptr<LogDnsClient> log_client = @@ -884,7 +923,8 @@ // Start a query. std::unique_ptr<LogDnsClient::AuditProofQuery> query1; net::TestCompletionCallback query_callback1; - ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], 999999, + ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 999999, &query1, query_callback1.callback()), IsError(net::ERR_IO_PENDING)); @@ -897,19 +937,20 @@ // Start another query to check |not_throttled_callback| doesn't fire again. ASSERT_TRUE( mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[1], 666)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "0.666.999999.tree.ct.test.", audit_proof.begin(), - audit_proof.begin() + 7)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "7.666.999999.tree.ct.test.", audit_proof.begin() + 7, - audit_proof.begin() + 14)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "14.666.999999.tree.ct.test.", audit_proof.begin() + 14, - audit_proof.end())); + for (size_t nodes_begin = 0; nodes_begin < audit_proof.size(); + nodes_begin += kMaxProofNodesPerDnsResponse) { + const size_t nodes_end = std::min( + nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size()); + + ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( + base::StringPrintf("%zu.666.999999.tree.ct.test.", nodes_begin), + audit_proof.begin() + nodes_begin, audit_proof.begin() + nodes_end)); + } std::unique_ptr<LogDnsClient::AuditProofQuery> query2; net::TestCompletionCallback query_callback2; - ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[1], 999999, + ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[1], + false /* lookup_securely */, 999999, &query2, query_callback2.callback()), IsError(net::ERR_IO_PENDING)); @@ -933,7 +974,8 @@ // Start query. std::unique_ptr<LogDnsClient::AuditProofQuery> query; net::TestCompletionCallback callback; - ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], 999999, + ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 999999, &query, callback.callback()), IsError(net::ERR_IO_PENDING)); @@ -950,6 +992,103 @@ histograms_.ExpectTotalCount(kAuditProofRcodeHistogram, 0); } +TEST_P(LogDnsClientTest, SecureDnsMode_Secure) { + const std::vector<std::string> audit_proof = GetSampleAuditProof(20); + + net::MockDnsClientRuleList rules; + // Make leaf index queries for kLeafIndexQnames[0] successful only when + // lookup_securely is true. + rules.emplace_back( + kLeafIndexQnames[0], net::dns_protocol::kTypeTXT, + net::SecureDnsMode::SECURE, + net::MockDnsClientRule::CreateSecureResult(net::BuildTestDnsResponse( + kLeafIndexQnames[0], + std::vector<std::vector<std::string>>({{"123456"}}))), + false /* delay */); + + // Add successful audit proof queries for lookup_securely true. + for (size_t nodes_begin = 0; nodes_begin < audit_proof.size(); + nodes_begin += kMaxProofNodesPerDnsResponse) { + const size_t nodes_end = std::min( + nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size()); + rules.emplace_back( + base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin), + net::dns_protocol::kTypeTXT, net::SecureDnsMode::SECURE, + net::MockDnsClientRule::CreateSecureResult(net::BuildTestDnsResponse( + base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin), + {{std::accumulate(audit_proof.begin() + nodes_begin, + audit_proof.begin() + nodes_end, + std::string())}})), + false /* delay */ + ); + } + + std::unique_ptr<LogDnsClient> log_client = + CreateRuleBasedLogDnsClient(std::move(rules)); + + std::unique_ptr<LogDnsClient::AuditProofQuery> query; + net::TestCompletionCallback callback; + ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 999999, + &query, callback.callback()), + IsError(net::ERR_IO_PENDING)); + EXPECT_THAT(callback.WaitForResult(), IsError(net::ERR_NAME_NOT_RESOLVED)); + + ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], + true /* lookup_securely */, 999999, + &query, callback.callback()), + IsError(net::ERR_IO_PENDING)); + EXPECT_THAT(callback.WaitForResult(), IsOk()); +} + +TEST_P(LogDnsClientTest, SecureDnsMode_Insecure) { + const std::vector<std::string> audit_proof = GetSampleAuditProof(20); + + net::MockDnsClientRuleList rules; + // Make leaf index queries for kLeafIndexQnames[0] successful only when + // lookup_securely is false. + rules.emplace_back(kLeafIndexQnames[0], net::dns_protocol::kTypeTXT, + net::SecureDnsMode::OFF, + net::MockDnsClientRule::Result(net::BuildTestDnsResponse( + kLeafIndexQnames[0], + std::vector<std::vector<std::string>>({{"123456"}}))), + false /* delay */); + + // Add successful audit proof queries for lookup_securely false. + for (size_t nodes_begin = 0; nodes_begin < audit_proof.size(); + nodes_begin += kMaxProofNodesPerDnsResponse) { + const size_t nodes_end = std::min( + nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size()); + rules.emplace_back( + base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin), + net::dns_protocol::kTypeTXT, net::SecureDnsMode::OFF, + net::MockDnsClientRule::Result(net::BuildTestDnsResponse( + base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin), + {{std::accumulate(audit_proof.begin() + nodes_begin, + audit_proof.begin() + nodes_end, + std::string())}})), + false /* delay */ + ); + } + + std::unique_ptr<LogDnsClient> log_client = + CreateRuleBasedLogDnsClient(std::move(rules)); + + std::unique_ptr<LogDnsClient::AuditProofQuery> query; + net::TestCompletionCallback callback; + ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], + false /* lookup_securely */, 999999, + &query, callback.callback()), + IsError(net::ERR_IO_PENDING)); + EXPECT_THAT(callback.WaitForResult(), IsOk()); + + ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], + true /* lookup_securely */, 999999, + &query, callback.callback()), + IsError(net::ERR_IO_PENDING)); + EXPECT_THAT(callback.WaitForResult(), IsError(net::ERR_NAME_NOT_RESOLVED)); +} + INSTANTIATE_TEST_SUITE_P(ReadMode, LogDnsClientTest, ::testing::Values(net::IoMode::ASYNC,
diff --git a/components/certificate_transparency/single_tree_tracker.cc b/components/certificate_transparency/single_tree_tracker.cc index b20bc9e..854c0890 100644 --- a/components/certificate_transparency/single_tree_tracker.cc +++ b/components/certificate_transparency/single_tree_tracker.cc
@@ -159,8 +159,10 @@ struct SingleTreeTracker::EntryToAudit { base::Time sct_timestamp; SHA256HashValue leaf_hash; + bool lookup_securely; - explicit EntryToAudit(base::Time timestamp) : sct_timestamp(timestamp) {} + explicit EntryToAudit(base::Time timestamp, bool lookup_securely) + : sct_timestamp(timestamp), lookup_securely(lookup_securely) {} }; // State of a log entry: its audit state and information necessary to @@ -211,7 +213,9 @@ // Orders entries by the SCT timestamp. In case of tie, which is very unlikely // as it requires two SCTs issued from a log at exactly the same time, order -// by leaf hash. +// by leaf hash. There should never be multiple entries that are identical +// apart from the |lookup_securely| field, so this field can be excluded from +// the comparator. bool SingleTreeTracker::OrderByTimestamp::operator()( const EntryToAudit& lhs, const EntryToAudit& rhs) const { @@ -255,19 +259,21 @@ // It's ok to do this now, even though the inclusion check may not happen for // some time, because SingleTreeTracker will discard the SCT if the network // changes. - if (!WasLookedUpOverDNS(hostname)) { + bool secure; + if (!WasLookedUpOverDNS(hostname, &secure)) { LogCanBeCheckedForInclusionToUMA(NOT_AUDITED_NO_DNS_LOOKUP); return; } - EntryToAudit entry(sct->timestamp); + EntryToAudit entry(sct->timestamp, secure /* lookup_securely */); if (!GetLogEntryLeafHash(cert, sct, &entry.leaf_hash)) { LogCanBeCheckedForInclusionToUMA(NOT_AUDITED_INVALID_LEAF_HASH); return; } - // Avoid queueing multiple instances of the same entry. - switch (GetAuditedEntryInclusionStatus(entry)) { + // Avoid queueing multiple instances of the same entry, ignoring the value of + // the |lookup_securely| field. + switch (GetAuditedEntryInclusionStatus(entry, nullptr)) { case SCT_NOT_OBSERVED: // No need to record UMA, will be done below. break; @@ -379,13 +385,14 @@ } SingleTreeTracker::SCTInclusionStatus -SingleTreeTracker::GetLogEntryInclusionStatus( +SingleTreeTracker::GetLogEntryInclusionStatusForTesting( net::X509Certificate* cert, - const SignedCertificateTimestamp* sct) { - EntryToAudit entry(sct->timestamp); + const SignedCertificateTimestamp* sct, + bool* pending_lookup_securely) { + EntryToAudit entry(sct->timestamp, false /* lookup_securely */); if (!GetLogEntryLeafHash(cert, sct, &entry.leaf_hash)) return SCT_NOT_OBSERVED; - return GetAuditedEntryInclusionStatus(entry); + return GetAuditedEntryInclusionStatus(entry, pending_lookup_securely); } void SingleTreeTracker::ProcessPendingEntries() { @@ -401,8 +408,8 @@ reinterpret_cast<const char*>(it->first.leaf_hash.data), crypto::kSHA256Length); net::Error result = dns_client_->QueryAuditProof( - ct_log_->dns_domain(), leaf_hash, verified_sth_.tree_size, - &(it->second.audit_proof_query), + ct_log_->dns_domain(), leaf_hash, it->first.lookup_securely, + verified_sth_.tree_size, &(it->second.audit_proof_query), base::Bind(&SingleTreeTracker::OnAuditProofObtained, base::Unretained(this), it->first)); // Handling proofs returned synchronously is not implemeted. @@ -441,7 +448,9 @@ } SingleTreeTracker::SCTInclusionStatus -SingleTreeTracker::GetAuditedEntryInclusionStatus(const EntryToAudit& entry) { +SingleTreeTracker::GetAuditedEntryInclusionStatus( + const EntryToAudit& entry, + bool* pending_lookup_securely) { const auto checked_entries_iterator = checked_entries_.Get(entry.leaf_hash); if (checked_entries_iterator != checked_entries_.end()) { return SCT_INCLUDED_IN_LOG; @@ -451,7 +460,9 @@ if (pending_iterator == pending_entries_.end()) { return SCT_NOT_OBSERVED; } - + // Found match in |pending_entries_|, so set |pending_lookup_securely|. + if (pending_lookup_securely) + *pending_lookup_securely = pending_iterator->first.lookup_securely; switch (pending_iterator->second.state) { case PENDING_NEWER_STH: return SCT_PENDING_NEWER_STH; @@ -525,10 +536,11 @@ net_log_callback); } -bool SingleTreeTracker::WasLookedUpOverDNS(base::StringPiece hostname) const { +bool SingleTreeTracker::WasLookedUpOverDNS(base::StringPiece hostname, + bool* secure) const { net::HostCache::Entry::Source source; net::HostCache::EntryStaleness staleness; - return host_resolver_->HasCached(hostname, &source, &staleness) && + return host_resolver_->HasCached(hostname, &source, &staleness, secure) && source == net::HostCache::Entry::SOURCE_DNS && staleness.network_changes == 0; }
diff --git a/components/certificate_transparency/single_tree_tracker.h b/components/certificate_transparency/single_tree_tracker.h index fa6b9d1e..1beffdb2 100644 --- a/components/certificate_transparency/single_tree_tracker.h +++ b/components/certificate_transparency/single_tree_tracker.h
@@ -16,6 +16,7 @@ #include "net/base/hash_value.h" #include "net/base/network_change_notifier.h" #include "net/cert/signed_tree_head.h" +#include "net/dns/host_cache.h" #include "net/log/net_log_with_source.h" namespace net { @@ -153,13 +154,15 @@ // Must only be called for STHs issued by the log this instance tracks. void NewSTHObserved(const net::ct::SignedTreeHead& sth); - // Returns the status of a given log entry that is assembled from - // |cert| and |sct|. If |cert| and |sct| were not previously observed, - // |sct| is not an SCT for |cert| or |sct| is not for this log, - // SCT_NOT_OBSERVED will be returned. - SCTInclusionStatus GetLogEntryInclusionStatus( + // Returns the status of a given log entry that is assembled from |cert| and + // |sct|. If |cert| and |sct| were not previously observed, |sct| is not an + // SCT for |cert| or |sct| is not for this log, and SCT_NOT_OBSERVED will be + // returned. If the assembled entry is pending, |pending_lookup_securely| will + // be set to the value of the pending match's |lookup_securely| field. + SCTInclusionStatus GetLogEntryInclusionStatusForTesting( net::X509Certificate* cert, - const net::ct::SignedCertificateTimestamp* sct); + const net::ct::SignedCertificateTimestamp* sct, + bool* pending_lookup_securely = nullptr); private: struct EntryToAudit; @@ -180,8 +183,12 @@ // Returns the inclusion status of the given |entry|, similar to // GetLogEntryInclusionStatus(). The |entry| is an internal representation of - // a certificate + SCT combination. - SCTInclusionStatus GetAuditedEntryInclusionStatus(const EntryToAudit& entry); + // a certificate + SCT combination, and the |lookup_securely| value in |entry| + // is ignored. If |entry| has a pending status, |pending_lookup_securely| will + // be set to the value fo the pending match's |lookup_securely| field. + SCTInclusionStatus GetAuditedEntryInclusionStatus( + const EntryToAudit& entry, + bool* pending_lookup_securely); // Processes the result of obtaining an audit proof for |entry|. // * If an audit proof was successfully obtained and validated, @@ -208,7 +215,7 @@ // Returns true if |hostname| has previously been looked up using DNS, and the // network has not changed since. - bool WasLookedUpOverDNS(base::StringPiece hostname) const; + bool WasLookedUpOverDNS(base::StringPiece hostname, bool* secure) const; // Holds the latest STH fetched and verified for this log. net::ct::SignedTreeHead verified_sth_;
diff --git a/components/certificate_transparency/single_tree_tracker_unittest.cc b/components/certificate_transparency/single_tree_tracker_unittest.cc index 00a5f13..39ab151 100644 --- a/components/certificate_transparency/single_tree_tracker_unittest.cc +++ b/components/certificate_transparency/single_tree_tracker_unittest.cc
@@ -176,10 +176,12 @@ void AddCacheEntry(net::HostCache* cache, const std::string& hostname, + bool secure, net::HostCache::Entry::Source source, base::TimeDelta ttl) { - cache->Set(net::HostCache::Key(hostname, net::ADDRESS_FAMILY_UNSPECIFIED, 0), - net::HostCache::Entry(net::OK, net::AddressList(), source), + auto key = net::HostCache::Key(hostname, net::ADDRESS_FAMILY_UNSPECIFIED, 0); + key.secure = secure; + cache->Set(key, net::HostCache::Entry(net::OK, net::AddressList(), source), base::TimeTicks::Now(), ttl); } @@ -298,7 +300,7 @@ // the user had visited that host. TEST_F(SingleTreeTrackerTest, DiscardsSCTWhenHostnameNotLookedUpUsingDNS) { CreateTreeTrackerWithDefaultDnsExpectation(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, + AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, net::HostCache::Entry::SOURCE_UNKNOWN, kZeroTTL); base::HistogramTester histograms; @@ -308,16 +310,16 @@ tree_tracker_->NewSTHObserved(sth); // Make sure the SCT status is the same as if there's no STH for this log. - EXPECT_EQ( - SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); // The status for this SCT should still be 'not observed'. - EXPECT_EQ( - SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); // Exactly one value should be logged, indicating that the SCT could not be // checked for inclusion because of no prior DNS lookup for this hostname. @@ -342,16 +344,16 @@ tree_tracker_->NewSTHObserved(sth); // Make sure the SCT status is the same as if there's no STH for this log. - EXPECT_EQ( - SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); tree_tracker_->OnSCTVerified("::1", chain_.get(), cert_sct_.get()); // The status for this SCT should still be 'not observed'. - EXPECT_EQ( - SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); // Exactly one value should be logged, indicating that the SCT could not be // checked for inclusion because of no prior DNS lookup for this hostname @@ -373,7 +375,7 @@ TEST_F(SingleTreeTrackerTest, DiscardsSCTWhenHostnameLookedUpUsingDNSOnDiffNetwork) { CreateTreeTrackerWithDefaultDnsExpectation(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, + AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, net::HostCache::Entry::SOURCE_DNS, kZeroTTL); // Simulate network change. @@ -386,16 +388,16 @@ tree_tracker_->NewSTHObserved(sth); // Make sure the SCT status is the same as if there's no STH for this log. - EXPECT_EQ( - SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); // The status for this SCT should still be 'not observed'. - EXPECT_EQ( - SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); // Exactly one value should be logged, indicating that the SCT could not be // checked for inclusion because of no prior DNS lookup for this hostname on @@ -408,26 +410,83 @@ EXPECT_EQ(0u, net_log_.GetSize()); } +TEST_F(SingleTreeTrackerTest, EntriesIndistinguishedBySecurity) { + CreateTreeTrackerWithDefaultDnsExpectation(); + AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, + net::HostCache::Entry::SOURCE_DNS, kZeroTTL); + AddCacheEntry(host_resolver_.GetHostCache(), kHostname, true /* secure */, + net::HostCache::Entry::SOURCE_DNS, kZeroTTL); + + base::HistogramTester histograms; + // Provide an STH to the tree_tracker_. + SignedTreeHead sth; + GetSampleSignedTreeHead(&sth); + tree_tracker_->NewSTHObserved(sth); + + // Make sure the SCT status is the same as if there's no STH for this log. + EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); + + tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); + + // The status for this SCT should be 'pending inclusion check' with + // |pending_lookup_securely| set to true since the cache check will return the + // secure key. + bool pending_lookup_securely; + EXPECT_EQ(SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get(), &pending_lookup_securely)); + EXPECT_TRUE(pending_lookup_securely); + + // Exactly one value should be logged, indicating the SCT can be checked for + // inclusion, as |tree_tracker_| did have a valid STH when it was notified + // of a new SCT. + histograms.ExpectUniqueSample(kCanCheckForInclusionHistogramName, 2, 1); + + // Simulate network change. + host_resolver_.GetHostCache()->OnNetworkChange(); + AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, + net::HostCache::Entry::SOURCE_DNS, kZeroTTL); + + tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); + + // The status for this SCT should still be 'pending inclusion check' with + // |pending_lookup_securely| set to true. + EXPECT_EQ(SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get(), &pending_lookup_securely)); + EXPECT_TRUE(pending_lookup_securely); + + // Another value should be logged, indicating that there is already a + // pending audit check for this SCT. + histograms.ExpectBucketCount(kCanCheckForInclusionHistogramName, 6, 1); + // Nothing should be logged in the result histogram or net log since an + // inclusion check wasn't performed. + histograms.ExpectTotalCount(kInclusionCheckResultHistogramName, 0); + EXPECT_EQ(0u, net_log_.GetSize()); +} + // Test that an SCT is classified as pending for a newer STH if the // SingleTreeTracker has not seen any STHs so far. TEST_F(SingleTreeTrackerTest, CorrectlyClassifiesUnobservedSCTNoSTH) { CreateTreeTrackerWithDefaultDnsExpectation(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, + AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, net::HostCache::Entry::SOURCE_DNS, kZeroTTL); base::HistogramTester histograms; // First make sure the SCT has not been observed at all. - EXPECT_EQ( - SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); // Since no STH was provided to the tree_tracker_ the status should be that // the SCT is pending a newer STH. - EXPECT_EQ( - SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); // Expect logging of a value indicating a valid STH is required. histograms.ExpectUniqueSample(kCanCheckForInclusionHistogramName, 0, 1); @@ -438,7 +497,7 @@ // SingleTreeTracker has a fresh-enough STH to check inclusion against. TEST_F(SingleTreeTrackerTest, CorrectlyClassifiesUnobservedSCTWithRecentSTH) { CreateTreeTrackerWithDefaultDnsExpectation(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, + AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, net::HostCache::Entry::SOURCE_DNS, kZeroTTL); base::HistogramTester histograms; @@ -449,17 +508,17 @@ // Make sure the SCT status is the same as if there's no STH for // this log. - EXPECT_EQ( - SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); // The status for this SCT should be 'pending inclusion check' since the STH // provided at the beginning of the test is newer than the SCT. - EXPECT_EQ( - SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); // Exactly one value should be logged, indicating the SCT can be checked for // inclusion, as |tree_tracker_| did have a valid STH when it was notified @@ -476,16 +535,16 @@ // from pending newer STH to pending inclusion check. TEST_F(SingleTreeTrackerTest, CorrectlyUpdatesSCTStatusOnNewSTH) { CreateTreeTrackerWithDefaultDnsExpectation(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, + AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, net::HostCache::Entry::SOURCE_DNS, kZeroTTL); base::HistogramTester histograms; // Report an observed SCT and make sure it's in the pending newer STH // state. tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - EXPECT_EQ( - SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); histograms.ExpectTotalCount(kCanCheckForInclusionHistogramName, 1); // Provide with a fresh STH @@ -494,9 +553,9 @@ tree_tracker_->NewSTHObserved(sth); // Test that its status has changed. - EXPECT_EQ( - SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); // Check that no additional UMA was logged for this case as the histogram is // only supposed to measure the state of newly-observed SCTs, not pending // ones. @@ -509,14 +568,14 @@ // inclusion against. TEST_F(SingleTreeTrackerTest, DoesNotUpdatesSCTStatusOnOldSTH) { CreateTreeTrackerWithDefaultDnsExpectation(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, + AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, net::HostCache::Entry::SOURCE_DNS, kZeroTTL); // Notify of an SCT and make sure it's in the 'pending newer STH' state. tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - EXPECT_EQ( - SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); // Provide an old STH for the same log. SignedTreeHead sth; @@ -524,9 +583,9 @@ tree_tracker_->NewSTHObserved(sth); // Make sure the SCT's state hasn't changed. - EXPECT_EQ( - SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); EXPECT_EQ(0u, net_log_.GetSize()); } @@ -535,7 +594,7 @@ // STH. TEST_F(SingleTreeTrackerTest, LogsUMAForNewSCTAndOldSTH) { CreateTreeTrackerWithDefaultDnsExpectation(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, + AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, net::HostCache::Entry::SOURCE_DNS, kZeroTTL); base::HistogramTester histograms; @@ -564,13 +623,13 @@ net::Error::ERR_FAILED)); CreateTreeTracker(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, + AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, net::HostCache::Entry::SOURCE_DNS, kZeroTTL); tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - EXPECT_EQ( - SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); // Provide with a fresh STH SignedTreeHead sth; @@ -578,9 +637,9 @@ tree_tracker_->NewSTHObserved(sth); base::RunLoop().RunUntilIdle(); - EXPECT_EQ( - SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); // There should have been one NetLog event, logged with failure. EXPECT_TRUE(MatchAuditingResultInNetLog( net_log_, LeafHash(chain_.get(), cert_sct_.get()), false)); @@ -602,13 +661,13 @@ net::Error::ERR_FAILED)); CreateTreeTracker(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, + AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, net::HostCache::Entry::SOURCE_DNS, kZeroTTL); tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - EXPECT_EQ( - SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); // Provide with a fresh STH SignedTreeHead sth; @@ -616,9 +675,9 @@ tree_tracker_->NewSTHObserved(sth); base::RunLoop().RunUntilIdle(); - EXPECT_EQ( - SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); // There should have been one NetLog event, logged with failure. EXPECT_TRUE(MatchAuditingResultInNetLog( net_log_, LeafHash(chain_.get(), cert_sct_.get()), false)); @@ -644,13 +703,13 @@ audit_proof.begin() + 1)); CreateTreeTracker(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, + AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, net::HostCache::Entry::SOURCE_DNS, kZeroTTL); tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - EXPECT_EQ( - SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); // Provide with a fresh STH, which is for a tree of size 2. SignedTreeHead sth; @@ -660,9 +719,9 @@ tree_tracker_->NewSTHObserved(sth); base::RunLoop().RunUntilIdle(); - EXPECT_EQ( - SingleTreeTracker::SCT_INCLUDED_IN_LOG, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_INCLUDED_IN_LOG, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); // There should have been one NetLog event, with success logged. EXPECT_TRUE(MatchAuditingResultInNetLog( net_log_, LeafHash(chain_.get(), cert_sct_.get()), true)); @@ -673,13 +732,13 @@ TEST_F(SingleTreeTrackerTest, TestInclusionCheckCancelledIfUnderMemoryPressure) { CreateTreeTracker(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, + AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, net::HostCache::Entry::SOURCE_DNS, kZeroTTL); tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - EXPECT_EQ( - SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); // Provide with a fresh STH, which is for a tree of size 2. SignedTreeHead sth; @@ -702,9 +761,9 @@ base::RunLoop().RunUntilIdle(); // Expect the SCT to have been discarded. - EXPECT_EQ( - SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); } // Test that pending entries transition states correctly according to the @@ -764,7 +823,7 @@ ASSERT_TRUE( ExpectLeafIndexRequestAndThrottle(chain_, newer_than_old_sth_sct)); CreateTreeTracker(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, + AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, net::HostCache::Entry::SOURCE_DNS, kZeroTTL); // Add SCTs in mixed order. @@ -782,9 +841,9 @@ for (const auto& sct : {oldest_sct, not_auditable_by_old_sth_sct, newer_than_old_sth_sct, not_auditable_by_new_sth_sct, newer_than_new_sth_sct}) { - ASSERT_EQ( - SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), sct.get())) + ASSERT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, + tree_tracker_->GetLogEntryInclusionStatusForTesting(chain_.get(), + sct.get())) << "SCT age: " << sct->timestamp; } @@ -792,15 +851,15 @@ tree_tracker_->NewSTHObserved(old_sth); // Ensure all but the oldest are in the PENDING_NEWER_STH state. ASSERT_EQ(SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), - oldest_sct.get())); + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), oldest_sct.get())); for (const auto& sct : {not_auditable_by_old_sth_sct, newer_than_old_sth_sct, not_auditable_by_new_sth_sct, newer_than_new_sth_sct}) { - ASSERT_EQ( - SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), sct.get())) + ASSERT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, + tree_tracker_->GetLogEntryInclusionStatusForTesting(chain_.get(), + sct.get())) << "SCT age: " << sct->timestamp; } @@ -810,17 +869,17 @@ for (const auto& sct : {not_auditable_by_old_sth_sct, newer_than_old_sth_sct}) { - ASSERT_EQ( - SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), sct.get())) + ASSERT_EQ(SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, + tree_tracker_->GetLogEntryInclusionStatusForTesting(chain_.get(), + sct.get())) << "SCT age: " << sct->timestamp; } for (const auto& sct : {not_auditable_by_new_sth_sct, newer_than_new_sth_sct}) { - ASSERT_EQ( - SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), sct.get())) + ASSERT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, + tree_tracker_->GetLogEntryInclusionStatusForTesting(chain_.get(), + sct.get())) << "SCT age: " << sct->timestamp; } } @@ -855,7 +914,7 @@ audit_proof.begin() + 1)); CreateTreeTracker(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, + AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, net::HostCache::Entry::SOURCE_DNS, kZeroTTL); SignedTreeHead sth; @@ -868,27 +927,27 @@ // Both entries should be in the pending state, the first because the // LogDnsClient did not invoke the callback yet, the second one because // the LogDnsClient is "busy" with the first entry and so would throttle. - ASSERT_EQ( - SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); ASSERT_EQ(SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), - second_sct.get())); + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); + ASSERT_EQ(SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), second_sct.get())); // Process pending DNS queries so later assertions are on handling // of the entries based on replies received. base::RunLoop().RunUntilIdle(); // Check that the first sct is included in the log. - ASSERT_EQ( - SingleTreeTracker::SCT_INCLUDED_IN_LOG, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + ASSERT_EQ(SingleTreeTracker::SCT_INCLUDED_IN_LOG, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); // Check that the second SCT got an invalid proof and is not included, rather // than being in the pending state. ASSERT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), - second_sct.get())); + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), second_sct.get())); } // Test that proof fetching failure due to DNS config errors is handled @@ -908,7 +967,7 @@ net_change_notifier_ = base::WrapUnique(net::NetworkChangeNotifier::CreateMock()); CreateTreeTracker(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, + AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, net::HostCache::Entry::SOURCE_DNS, kZeroTTL); tree_tracker_->NewSTHObserved(sth); @@ -917,9 +976,9 @@ // Make sure the SCT status indicates the entry has been removed from // the SingleTreeTracker's internal queue as the DNS lookup failed // synchronously. - EXPECT_EQ( - SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get())); + EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, + tree_tracker_->GetLogEntryInclusionStatusForTesting( + chain_.get(), cert_sct_.get())); // Exactly one value should be logged, indicating the SCT can be checked for // inclusion, as |tree_tracker_| did have a valid STH when it was notified @@ -959,7 +1018,7 @@ audit_proof.begin() + 1)); CreateTreeTracker(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, + AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, net::HostCache::Entry::SOURCE_DNS, kZeroTTL); // Provide an STH to the tree_tracker_. @@ -971,9 +1030,9 @@ tree_tracker_->OnSCTVerified(kHostname, chain_.get(), second_sct.get()); for (auto sct : {cert_sct_, second_sct}) { - EXPECT_EQ( - SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), sct.get())); + EXPECT_EQ(SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, + tree_tracker_->GetLogEntryInclusionStatusForTesting(chain_.get(), + sct.get())); } net_change_notifier_->NotifyObserversOfNetworkChangeForTests( @@ -981,9 +1040,9 @@ base::RunLoop().RunUntilIdle(); for (auto sct : {cert_sct_, second_sct}) { - EXPECT_EQ( - SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), sct.get())); + EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, + tree_tracker_->GetLogEntryInclusionStatusForTesting(chain_.get(), + sct.get())); } }
diff --git a/components/cronet/stale_host_resolver.cc b/components/cronet/stale_host_resolver.cc index 9b632fec..303e7728 100644 --- a/components/cronet/stale_host_resolver.cc +++ b/components/cronet/stale_host_resolver.cc
@@ -444,11 +444,12 @@ optional_parameters.value_or(ResolveHostParameters()), tick_clock_); } -bool StaleHostResolver::HasCached( - base::StringPiece hostname, - net::HostCache::Entry::Source* source_out, - net::HostCache::EntryStaleness* stale_out) const { - return inner_resolver_->HasCached(hostname, source_out, stale_out); +bool StaleHostResolver::HasCached(base::StringPiece hostname, + net::HostCache::Entry::Source* source_out, + net::HostCache::EntryStaleness* stale_out, + bool* secure_out) const { + return inner_resolver_->HasCached(hostname, source_out, stale_out, + secure_out); } void StaleHostResolver::SetDnsClientEnabled(bool enabled) {
diff --git a/components/cronet/stale_host_resolver.h b/components/cronet/stale_host_resolver.h index 7e9c8f5..3f82a9d 100644 --- a/components/cronet/stale_host_resolver.h +++ b/components/cronet/stale_host_resolver.h
@@ -85,7 +85,8 @@ net::HostCache* GetHostCache() override; bool HasCached(base::StringPiece hostname, net::HostCache::Entry::Source* source_out, - net::HostCache::EntryStaleness* stale_out) const override; + net::HostCache::EntryStaleness* stale_out, + bool* secure_out) const override; std::unique_ptr<base::Value> GetDnsConfigAsValue() const override; private:
diff --git a/components/cronet/stale_host_resolver_unittest.cc b/components/cronet/stale_host_resolver_unittest.cc index 99b2b508..faa2e152 100644 --- a/components/cronet/stale_host_resolver_unittest.cc +++ b/components/cronet/stale_host_resolver_unittest.cc
@@ -93,11 +93,11 @@ net::MockDnsClientRuleList rules; rules.emplace_back( - kHostname, net::dns_protocol::kTypeA, + kHostname, net::dns_protocol::kTypeA, net::SecureDnsMode::AUTOMATIC, net::MockDnsClientRule::Result(net::MockDnsClientRule::FAIL), true /* delay */); rules.emplace_back( - kHostname, net::dns_protocol::kTypeAAAA, + kHostname, net::dns_protocol::kTypeAAAA, net::SecureDnsMode::AUTOMATIC, net::MockDnsClientRule::Result(net::MockDnsClientRule::FAIL), true /* delay */);
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 15b1c88..d120f02 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -14651,7 +14651,10 @@ { 'name': 'PluginVmLicenseKey', 'type': 'string', - 'schema': { 'type': 'string' }, + 'schema': { + 'sensitiveValue': True, + 'type': 'string' + }, 'supported_on': ['chrome_os:73-'], 'device_only': True, 'features': {
diff --git a/components/signin/core/browser/account_fetcher_service.cc b/components/signin/core/browser/account_fetcher_service.cc index 45c022a..687e5c7b 100644 --- a/components/signin/core/browser/account_fetcher_service.cc +++ b/components/signin/core/browser/account_fetcher_service.cc
@@ -99,7 +99,7 @@ return user_info_requests_.empty(); } -void AccountFetcherService::FetchUserInfoBeforeSignin( +void AccountFetcherService::ForceRefreshOfAccountInfo( const std::string& account_id) { DCHECK(network_fetches_enabled_); RefreshAccountInfo(account_id, false);
diff --git a/components/signin/core/browser/account_fetcher_service.h b/components/signin/core/browser/account_fetcher_service.h index f6a61ca..7d36bd86 100644 --- a/components/signin/core/browser/account_fetcher_service.h +++ b/components/signin/core/browser/account_fetcher_service.h
@@ -66,7 +66,7 @@ // there are still unfininshed fetchers. virtual bool IsAllUserInfoFetched() const; - void FetchUserInfoBeforeSignin(const std::string& account_id); + void ForceRefreshOfAccountInfo(const std::string& account_id); AccountTrackerService* account_tracker_service() const { return account_tracker_service_;
diff --git a/components/signin/core/browser/fake_account_fetcher_service.cc b/components/signin/core/browser/fake_account_fetcher_service.cc index 72e4df83..c70081c 100644 --- a/components/signin/core/browser/fake_account_fetcher_service.cc +++ b/components/signin/core/browser/fake_account_fetcher_service.cc
@@ -5,6 +5,7 @@ #include "components/signin/core/browser/fake_account_fetcher_service.h" #include "base/values.h" +#include "build/build_config.h" #include "components/signin/core/browser/account_tracker_service.h" #include "components/signin/core/browser/profile_oauth2_token_service.h" #include "ui/gfx/image/image_unittest_util.h" @@ -16,6 +17,13 @@ // In tests, don't do actual network fetch. } +#if defined(OS_ANDROID) +void FakeAccountFetcherService::StartFetchingChildInfo( + const std::string& account_id) { + // In tests, don't do actual network fetch. +} +#endif + TestImageDecoder::TestImageDecoder() = default; TestImageDecoder::~TestImageDecoder() = default;
diff --git a/components/signin/core/browser/fake_account_fetcher_service.h b/components/signin/core/browser/fake_account_fetcher_service.h index a57cfd2..5f56123 100644 --- a/components/signin/core/browser/fake_account_fetcher_service.h +++ b/components/signin/core/browser/fake_account_fetcher_service.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/macros.h" +#include "build/build_config.h" #include "components/image_fetcher/core/image_decoder.h" #include "components/signin/core/browser/account_fetcher_service.h" @@ -22,6 +23,9 @@ private: void StartFetchingUserInfo(const std::string& account_id) override; +#if defined(OS_ANDROID) + void StartFetchingChildInfo(const std::string& account_id) override; +#endif DISALLOW_COPY_AND_ASSIGN(FakeAccountFetcherService); };
diff --git a/components/sync/base/sync_prefs.cc b/components/sync/base/sync_prefs.cc index 5b05045..a1aa08c 100644 --- a/components/sync/base/sync_prefs.cc +++ b/components/sync/base/sync_prefs.cc
@@ -63,9 +63,6 @@ pref_groups[PROXY_TABS].Put(FAVICON_IMAGES); pref_groups[PROXY_TABS].Put(FAVICON_TRACKING); - // TODO(zea): Put favicons in the bookmarks group as well once it handles - // those favicons. - return pref_groups; } @@ -142,51 +139,48 @@ // static void SyncPrefs::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref(prefs::kSyncCacheGuid, std::string()); - registry->RegisterStringPref(prefs::kSyncBirthday, std::string()); - registry->RegisterStringPref(prefs::kSyncBagOfChips, std::string()); + // Actual user-controlled preferences. registry->RegisterBooleanPref(prefs::kSyncFirstSetupComplete, false); registry->RegisterBooleanPref(prefs::kSyncSuppressStart, false); - registry->RegisterInt64Pref(prefs::kSyncLastSyncedTime, 0); - registry->RegisterInt64Pref(prefs::kSyncLastPollTime, 0); - registry->RegisterInt64Pref(prefs::kSyncFirstSyncTime, 0); - registry->RegisterInt64Pref(prefs::kSyncShortPollIntervalSeconds, 0); - registry->RegisterInt64Pref(prefs::kSyncLongPollIntervalSeconds, 0); - - // All datatypes are on by default, but this gets set explicitly - // when you configure sync (when turning it on), in - // ProfileSyncService::OnUserChoseDatatypes. registry->RegisterBooleanPref(prefs::kSyncKeepEverythingSynced, true); - - RegisterObsoleteUserTypePrefs(registry); - - // All types are set to off by default, which forces a configuration to - // explicitly enable them. for (ModelType type : UserSelectableTypes()) { RegisterDataTypePreferredPref(registry, type); } + // Internal or bookkeeping prefs. + registry->RegisterStringPref(prefs::kSyncCacheGuid, std::string()); + registry->RegisterStringPref(prefs::kSyncBirthday, std::string()); + registry->RegisterStringPref(prefs::kSyncBagOfChips, std::string()); + registry->RegisterInt64Pref(prefs::kSyncLastSyncedTime, 0); + registry->RegisterInt64Pref(prefs::kSyncLastPollTime, 0); + // TODO(crbug.com/938865): Remove this pref. + registry->RegisterInt64Pref(prefs::kSyncFirstSyncTime, 0); + registry->RegisterInt64Pref(prefs::kSyncShortPollIntervalSeconds, 0); + registry->RegisterInt64Pref(prefs::kSyncLongPollIntervalSeconds, 0); registry->RegisterBooleanPref(prefs::kSyncManaged, false); registry->RegisterStringPref(prefs::kSyncEncryptionBootstrapToken, std::string()); registry->RegisterStringPref(prefs::kSyncKeystoreEncryptionBootstrapToken, std::string()); #if defined(OS_CHROMEOS) + // TODO(crbug.com/938869): Remove this pref. registry->RegisterStringPref(prefs::kSyncSpareBootstrapToken, ""); #endif - - registry->RegisterBooleanPref(kSyncHasAuthError, false); registry->RegisterBooleanPref(prefs::kSyncPassphrasePrompted, false); registry->RegisterIntegerPref(prefs::kSyncMemoryPressureWarningCount, -1); registry->RegisterBooleanPref(prefs::kSyncShutdownCleanly, false); registry->RegisterDictionaryPref(prefs::kSyncInvalidationVersions); registry->RegisterStringPref(prefs::kSyncLastRunVersion, std::string()); + registry->RegisterBooleanPref(prefs::kEnableLocalSyncBackend, false); + registry->RegisterFilePathPref(prefs::kLocalSyncBackendDir, base::FilePath()); + + // Obsolete prefs that will be removed after a grace period. + RegisterObsoleteUserTypePrefs(registry); registry->RegisterBooleanPref(kSyncPassphraseEncryptionTransitionInProgress, false); registry->RegisterStringPref(kSyncNigoriStateForPassphraseTransition, std::string()); - registry->RegisterBooleanPref(prefs::kEnableLocalSyncBackend, false); - registry->RegisterFilePathPref(prefs::kLocalSyncBackendDir, base::FilePath()); + registry->RegisterBooleanPref(kSyncHasAuthError, false); } void SyncPrefs::AddSyncPrefObserver(SyncPrefObserver* sync_pref_observer) { @@ -201,6 +195,7 @@ void SyncPrefs::ClearPreferences() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + pref_service_->ClearPref(prefs::kSyncCacheGuid); pref_service_->ClearPref(prefs::kSyncBirthday); pref_service_->ClearPref(prefs::kSyncBagOfChips); @@ -208,7 +203,6 @@ pref_service_->ClearPref(prefs::kSyncLastPollTime); pref_service_->ClearPref(prefs::kSyncShortPollIntervalSeconds); pref_service_->ClearPref(prefs::kSyncLongPollIntervalSeconds); - pref_service_->ClearPref(prefs::kSyncFirstSetupComplete); pref_service_->ClearPref(prefs::kSyncEncryptionBootstrapToken); pref_service_->ClearPref(prefs::kSyncKeystoreEncryptionBootstrapToken); pref_service_->ClearPref(prefs::kSyncPassphrasePrompted); @@ -216,9 +210,14 @@ pref_service_->ClearPref(prefs::kSyncShutdownCleanly); pref_service_->ClearPref(prefs::kSyncInvalidationVersions); pref_service_->ClearPref(prefs::kSyncLastRunVersion); + // No need to clear kManaged, kEnableLocalSyncBackend or kLocalSyncBackendDir, + // since they're never actually set as user preferences. // Note: We do *not* clear prefs which are directly user-controlled such as - // the set of preferred data types here. + // the set of preferred data types here, so that if the user ever chooses to + // enable Sync again, they start off with their previous settings by default. + // We do however require going through first-time setup again. + pref_service_->ClearPref(prefs::kSyncFirstSetupComplete); } bool SyncPrefs::IsFirstSetupComplete() const {
diff --git a/components/sync/driver/startup_controller.cc b/components/sync/driver/startup_controller.cc index 2b18a84..0b7da17 100644 --- a/components/sync/driver/startup_controller.cc +++ b/components/sync/driver/startup_controller.cc
@@ -59,7 +59,7 @@ StartupController::StartupController( base::RepeatingCallback<ModelTypeSet()> get_preferred_data_types, - base::RepeatingCallback<bool(bool)> should_start, + base::RepeatingCallback<bool()> should_start, base::RepeatingClosure start_engine) : get_preferred_data_types_callback_(std::move(get_preferred_data_types)), should_start_callback_(std::move(should_start)), @@ -102,7 +102,7 @@ } void StartupController::TryStart(bool force_immediate) { - if (!should_start_callback_.Run(force_immediate)) { + if (!should_start_callback_.Run()) { return; }
diff --git a/components/sync/driver/startup_controller.h b/components/sync/driver/startup_controller.h index 9c02ff7..fe55df7 100644 --- a/components/sync/driver/startup_controller.h +++ b/components/sync/driver/startup_controller.h
@@ -29,7 +29,7 @@ StartupController( base::RepeatingCallback<ModelTypeSet()> get_preferred_data_types, - base::RepeatingCallback<bool(bool force_immediate)> should_start, + base::RepeatingCallback<bool()> should_start, base::RepeatingClosure start_engine); ~StartupController(); @@ -68,7 +68,7 @@ // A function that can be invoked repeatedly to determine whether sync should // be started. |start_engine_| should not be invoked unless this returns true. - const base::RepeatingCallback<bool(bool)> should_start_callback_; + const base::RepeatingCallback<bool()> should_start_callback_; // The callback we invoke when it's time to call expensive // startup routines for the sync engine.
diff --git a/components/sync/driver/startup_controller_unittest.cc b/components/sync/driver/startup_controller_unittest.cc index 752f78d6..996ab84 100644 --- a/components/sync/driver/startup_controller_unittest.cc +++ b/components/sync/driver/startup_controller_unittest.cc
@@ -62,7 +62,7 @@ private: ModelTypeSet GetPreferredDataTypes() { return preferred_types_; } - bool ShouldStart(bool force_immediate) { return should_start_; } + bool ShouldStart() { return should_start_; } void FakeStartBackend() { started_ = true; } ModelTypeSet preferred_types_;
diff --git a/components/sync/driver/sync_driver_switches.cc b/components/sync/driver/sync_driver_switches.cc index 882962a..a3b4a73 100644 --- a/components/sync/driver/sync_driver_switches.cc +++ b/components/sync/driver/sync_driver_switches.cc
@@ -73,11 +73,6 @@ const base::Feature kSyncSendTabToSelf{"SyncSendTabToSelf", base::FEATURE_DISABLED_BY_DEFAULT}; -// If enabled, allows the Sync machinery ("transport layer") to start -// independently of Sync-the-feature. -const base::Feature kSyncStandaloneTransport{"SyncStandaloneTransport", - base::FEATURE_ENABLED_BY_DEFAULT}; - // If enabled, allows the Sync machinery to start with a signed-in account that // has *not* been chosen as Chrome's primary account (see IdentityManager). Only // has an effect if SyncStandaloneTransport is also enabled.
diff --git a/components/sync/driver/sync_driver_switches.h b/components/sync/driver/sync_driver_switches.h index 5d09d6b..fc6f979 100644 --- a/components/sync/driver/sync_driver_switches.h +++ b/components/sync/driver/sync_driver_switches.h
@@ -35,7 +35,6 @@ extern const base::Feature kSyncPseudoUSSSupervisedUsers; extern const base::Feature kSyncPseudoUSSThemes; extern const base::Feature kSyncSendTabToSelf; -extern const base::Feature kSyncStandaloneTransport; extern const base::Feature kSyncSupportSecondaryAccount; extern const base::Feature kSyncUserEvents; extern const base::Feature kSyncUserFieldTrialEvents;
diff --git a/components/variations/platform_field_trials.h b/components/variations/platform_field_trials.h index 3a7f642..bb010fe 100644 --- a/components/variations/platform_field_trials.h +++ b/components/variations/platform_field_trials.h
@@ -29,6 +29,10 @@ bool has_seed, base::FeatureList* feature_list) = 0; + // Register any synthetic field trials. Will be called later than the above + // methods, in particular after g_browser_process is available.. + virtual void RegisterSyntheticTrials() {} + private: DISALLOW_COPY_AND_ASSIGN(PlatformFieldTrials); };
diff --git a/components/viz/common/quads/draw_quad_perftest.cc b/components/viz/common/quads/draw_quad_perftest.cc index 8e235328..6759fde2 100644 --- a/components/viz/common/quads/draw_quad_perftest.cc +++ b/components/viz/common/quads/draw_quad_perftest.cc
@@ -6,7 +6,7 @@ #include "base/bind.h" #include "base/time/time.h" -#include "cc/base/lap_timer.h" +#include "base/timer/lap_timer.h" #include "components/viz/common/quads/draw_quad.h" #include "components/viz/common/quads/render_pass.h" #include "components/viz/common/quads/texture_draw_quad.h" @@ -104,7 +104,7 @@ private: std::unique_ptr<RenderPass> render_pass_; SharedQuadState* shared_state_; - cc::LapTimer timer_; + base::LapTimer timer_; }; TEST_F(DrawQuadPerfTest, IterateResources) {
diff --git a/components/viz/host/host_frame_sink_manager.cc b/components/viz/host/host_frame_sink_manager.cc index 63d8a0d..57584df 100644 --- a/components/viz/host/host_frame_sink_manager.cc +++ b/components/viz/host/host_frame_sink_manager.cc
@@ -305,6 +305,10 @@ void HostFrameSinkManager::EvictSurfaces( const std::vector<SurfaceId>& surface_ids) { + // TODO(sgilhuly): Remove this check once crbug.com/911308 is fixed. + for (auto& surface_id : surface_ids) { + CHECK(surface_id.is_valid()); + } frame_sink_manager_->EvictSurfaces(surface_ids); }
diff --git a/components/viz/service/display/bsp_tree_perftest.cc b/components/viz/service/display/bsp_tree_perftest.cc index 29efb30..2895bd10 100644 --- a/components/viz/service/display/bsp_tree_perftest.cc +++ b/components/viz/service/display/bsp_tree_perftest.cc
@@ -14,7 +14,7 @@ #include "base/strings/string_piece.h" #include "base/threading/thread.h" #include "base/time/time.h" -#include "cc/base/lap_timer.h" +#include "base/timer/lap_timer.h" #include "cc/layers/layer.h" #include "cc/test/fake_content_layer_client.h" #include "cc/test/fake_layer_tree_host_client.h" @@ -135,12 +135,12 @@ void AfterTest() override { CHECK(!test_name_.empty()) << "Must SetTestName() before TearDown()."; perf_test::PrintResult("calc_draw_props_time", "", test_name_, - 1000 * timer_.MsPerLap(), "us", true); + timer_.TimePerLap().InMicrosecondsF(), "us", true); } private: cc::FakeContentLayerClient content_layer_client_; - cc::LapTimer timer_; + base::LapTimer timer_; std::string test_name_; std::string json_; cc::LayerImplList base_list_;
diff --git a/components/viz/service/display/display_perftest.cc b/components/viz/service/display/display_perftest.cc index dc09344a..d6f91b7 100644 --- a/components/viz/service/display/display_perftest.cc +++ b/components/viz/service/display/display_perftest.cc
@@ -7,7 +7,7 @@ #include "base/bind.h" #include "base/test/null_task_runner.h" #include "base/time/time.h" -#include "cc/base/lap_timer.h" +#include "base/timer/lap_timer.h" #include "components/viz/common/display/renderer_settings.h" #include "components/viz/common/quads/compositor_frame.h" #include "components/viz/common/quads/draw_quad.h" @@ -290,7 +290,7 @@ private: CompositorFrame frame_; - cc::LapTimer timer_; + base::LapTimer timer_; StubBeginFrameSource begin_frame_source_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; ServerSharedBitmapManager bitmap_manager_;
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc index f749b54..c08fab0 100644 --- a/components/viz/service/display/surface_aggregator.cc +++ b/components/viz/service/display/surface_aggregator.cc
@@ -71,6 +71,10 @@ } // namespace +std::string SurfaceAggregator::ClipData::ToString() const { + return is_clipped ? "clip " + rect.ToString() : "no clip"; +} + SurfaceAggregator::SurfaceAggregator(SurfaceManager* manager, DisplayResourceProvider* provider, bool aggregate_only_damaged)
diff --git a/components/viz/service/display/surface_aggregator.h b/components/viz/service/display/surface_aggregator.h index 352a124c..d692e75 100644 --- a/components/viz/service/display/surface_aggregator.h +++ b/components/viz/service/display/surface_aggregator.h
@@ -6,6 +6,7 @@ #define COMPONENTS_VIZ_SERVICE_DISPLAY_SURFACE_AGGREGATOR_H_ #include <memory> +#include <string> #include <unordered_map> #include "base/containers/flat_map.h" @@ -64,6 +65,8 @@ ClipData(bool is_clipped, const gfx::Rect& rect) : is_clipped(is_clipped), rect(rect) {} + std::string ToString() const; + bool is_clipped; gfx::Rect rect; };
diff --git a/components/viz/service/display/surface_aggregator_perftest.cc b/components/viz/service/display/surface_aggregator_perftest.cc index 2975828a..95539d5 100644 --- a/components/viz/service/display/surface_aggregator_perftest.cc +++ b/components/viz/service/display/surface_aggregator_perftest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/base/lap_timer.h" +#include "base/timer/lap_timer.h" #include "cc/test/fake_output_surface_client.h" #include "components/viz/common/frame_sinks/begin_frame_args.h" #include "components/viz/common/quads/compositor_frame.h" @@ -157,7 +157,7 @@ scoped_refptr<TestContextProvider> context_provider_; std::unique_ptr<DisplayResourceProvider> resource_provider_; std::unique_ptr<SurfaceAggregator> aggregator_; - cc::LapTimer timer_; + base::LapTimer timer_; }; TEST_F(SurfaceAggregatorPerfTest, ManySurfacesOpaque) {
diff --git a/components/viz/service/frame_sinks/surface_synchronization_unittest.cc b/components/viz/service/frame_sinks/surface_synchronization_unittest.cc index 6e14e2d..dc15ded 100644 --- a/components/viz/service/frame_sinks/surface_synchronization_unittest.cc +++ b/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
@@ -120,6 +120,9 @@ } FrameSinkManagerImpl& frame_sink_manager() { return frame_sink_manager_; } + SurfaceManager* surface_manager() { + return frame_sink_manager_.surface_manager(); + } // Returns all the references where |surface_id| is the parent. const base::flat_set<SurfaceId>& GetChildReferences( @@ -135,12 +138,6 @@ surface_id); } - // Returns true if there is a Persistent reference for |surface_id|. - bool HasPersistentReference(const SurfaceId& surface_id) { - return frame_sink_manager().surface_manager()->HasPersistentReference( - surface_id); - } - Surface* GetLatestInFlightSurface(const SurfaceRange& surface_range) { return frame_sink_manager().surface_manager()->GetLatestInFlightSurface( surface_range); @@ -2058,9 +2055,11 @@ GetLatestInFlightSurface(SurfaceRange(child_id1, child_id3))); } -// This test verifies that GetLatestInFlightSurface will return nullptr -// if it has a bogus fallback SurfaceID. -TEST_F(SurfaceSynchronizationTest, LatestInFlightSurfaceWithBogusFallback) { +// This test verifies that GetLatestInFlightSurface will return nullptr when the +// start of the range is newer than its end, even if a surface matching the end +// exists. +TEST_F(SurfaceSynchronizationTest, + LatestInFlightSurfaceWithInvalidSurfaceRange) { const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1); const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink1, 2); @@ -2084,12 +2083,11 @@ const SurfaceId bogus_child_id = MakeSurfaceId(kChildFrameSink1, 10); - // If primary exists and active return it regardless of the fallback. - EXPECT_EQ(GetSurfaceForId(child_id1), + // The end exists but don't return it because the start is newer than the end. + EXPECT_EQ(nullptr, GetLatestInFlightSurface(SurfaceRange(bogus_child_id, child_id1))); - // If primary is not active and fallback is doesn't exist, we always return - // nullptr. + // In this case, the end doesn't exist either. Still return nullptr. EXPECT_EQ(nullptr, GetLatestInFlightSurface(SurfaceRange(bogus_child_id, child_id2))); } @@ -2310,7 +2308,9 @@ // |child_id1| now should have a temporary reference. EXPECT_TRUE(HasTemporaryReference(child_id1)); - EXPECT_FALSE(HasPersistentReference(child_id1)); + EXPECT_TRUE(surface_manager() + ->GetSurfacesThatReferenceChildForTesting(child_id1) + .empty()); // Activate |child_id2|. child_support1().SubmitCompositorFrame(child_id2.local_surface_id(), @@ -2318,7 +2318,9 @@ // |child_id2| now should have a temporary reference. EXPECT_TRUE(HasTemporaryReference(child_id2)); - EXPECT_FALSE(HasPersistentReference(child_id2)); + EXPECT_TRUE(surface_manager() + ->GetSurfacesThatReferenceChildForTesting(child_id2) + .empty()); // Create a reference from |parent_id| to |child_id2|. parent_support().SubmitCompositorFrame( @@ -2328,11 +2330,15 @@ // |child_id1| have no references and can be garbage collected. EXPECT_FALSE(HasTemporaryReference(child_id1)); - EXPECT_FALSE(HasPersistentReference(child_id1)); + EXPECT_TRUE(surface_manager() + ->GetSurfacesThatReferenceChildForTesting(child_id1) + .empty()); // |child_id2| has a persistent references now. EXPECT_FALSE(HasTemporaryReference(child_id2)); - EXPECT_TRUE(HasPersistentReference(child_id2)); + EXPECT_FALSE(surface_manager() + ->GetSurfacesThatReferenceChildForTesting(child_id2) + .empty()); // Verify that GetLatestInFlightSurface returns |child_id2|. EXPECT_EQ(GetSurfaceForId(child_id2),
diff --git a/components/viz/service/surfaces/surface_allocation_group.cc b/components/viz/service/surfaces/surface_allocation_group.cc index dc3e9e62..dc42639 100644 --- a/components/viz/service/surfaces/surface_allocation_group.cc +++ b/components/viz/service/surfaces/surface_allocation_group.cc
@@ -34,4 +34,82 @@ surfaces_.erase(it); } +Surface* SurfaceAllocationGroup::FindLatestActiveSurfaceInRange( + const SurfaceRange& range) const { + // If the embed token of the end of the SurfaceRange matches that of this + // group, find the latest active surface that is older than or equal to the + // end, then check that it's not older than start. + if (range.end().local_surface_id().embed_token() == embed_token_) { + DCHECK_EQ(submitter_, range.end().frame_sink_id()); + Surface* result = FindOlderOrEqual(range.end()); + if (result && + (!range.start() || !range.start()->IsNewerThan(result->surface_id()))) { + return result; + } else { + return nullptr; + } + } + + // If we are here, the embed token of the end of the range doesn't match this + // group's embed token. In this case, the range must have a start and its + // embed token must match this group. Simply find the last active surface, and + // check whether it's newer than the range's start. + DCHECK(range.start()); + DCHECK_EQ(embed_token_, range.start()->local_surface_id().embed_token()); + DCHECK_NE(embed_token_, range.end().local_surface_id().embed_token()); + DCHECK_EQ(submitter_, range.start()->frame_sink_id()); + + Surface* result = nullptr; + // Normally there is at most one pending surface, so this for loop shouldn't + // take more than two iterations. + for (int i = surfaces_.size() - 1; i >= 0; i--) { + if (surfaces_[i]->HasActiveFrame()) { + result = surfaces_[i]; + break; + } + } + if (result && range.start()->IsNewerThan(result->surface_id())) + return nullptr; + return result; +} + +Surface* SurfaceAllocationGroup::FindOlderOrEqual( + const SurfaceId& surface_id) const { + DCHECK_EQ(submitter_, surface_id.frame_sink_id()); + DCHECK_EQ(embed_token_, surface_id.local_surface_id().embed_token()); + + // Return early if there are no surfaces in this group. + if (surfaces_.empty()) + return nullptr; + + // If even the first surface is newer than |surface_id|, we can't find a + // surface that is older than or equal to |surface_id|. + if (surfaces_[0]->surface_id().IsNewerThan(surface_id)) + return nullptr; + + // Perform a binary search the find the latest active surface that is older + // than or equal to |surface_id|. + int begin = 0; + int end = surfaces_.size(); + while (end - begin > 1) { + int avg = (begin + end) / 2; + if (surfaces_[avg]->surface_id().IsNewerThan(surface_id)) + end = avg; + else + begin = avg; + } + + // We have found the latest surface. Now keep iterating back until we find an + // active surface. Normally, there is only one pending surface at a time, so + // this shouldn't take more than two iterations. + for (; begin >= 0; --begin) { + if (surfaces_[begin]->HasActiveFrame()) + return surfaces_[begin]; + } + + // No active surface was found, so return null. + DCHECK_EQ(-1, begin); + return nullptr; +} + } // namespace viz
diff --git a/components/viz/service/surfaces/surface_allocation_group.h b/components/viz/service/surfaces/surface_allocation_group.h index 38e99e29..780ce97 100644 --- a/components/viz/service/surfaces/surface_allocation_group.h +++ b/components/viz/service/surfaces/surface_allocation_group.h
@@ -9,6 +9,7 @@ #include "base/unguessable_token.h" #include "components/viz/common/surfaces/frame_sink_id.h" +#include "components/viz/common/surfaces/surface_range.h" #include "components/viz/service/viz_service_export.h" namespace viz { @@ -41,12 +42,21 @@ // allocation group. void UnregisterSurface(Surface* surface); + // Returns the latest active surface in the given range that is a part of this + // allocation group. The embed token of at least one end of the range must + // match the embed token of this group. + Surface* FindLatestActiveSurfaceInRange(const SurfaceRange& range) const; + // Returns the last surface created in this allocation group. - Surface* last_created_surface() { + Surface* last_created_surface() const { return surfaces_.empty() ? nullptr : surfaces_.back(); } private: + // Helper method for FindLatestActiveSurfaceInRange. Returns the latest active + // surface whose SurfaceId is older than or equal to |surface_id|. + Surface* FindOlderOrEqual(const SurfaceId& surface_id) const; + // The ID of the FrameSink that is submitting to the surfaces in this // allocation group. const FrameSinkId submitter_;
diff --git a/components/viz/service/surfaces/surface_manager.cc b/components/viz/service/surfaces/surface_manager.cc index e9fa75c5..b96a45c8 100644 --- a/components/viz/service/surfaces/surface_manager.cc +++ b/components/viz/service/surfaces/surface_manager.cc
@@ -65,7 +65,6 @@ // destroyed. temporary_references_.clear(); temporary_reference_ranges_.clear(); - persistent_references_by_frame_sink_id_.clear(); // Create a copy of the children set as RemoveSurfaceReferenceImpl below will // mutate that set. base::flat_set<SurfaceId> children( @@ -249,43 +248,6 @@ return parents; } -Surface* SurfaceManager::GetLatestInFlightSurfaceForFrameSinkId( - const SurfaceRange& surface_range, - const FrameSinkId& sink_id) { - std::vector<LocalSurfaceId> valid_local_surfaces; - // Get all valid temporary references. - auto temporary_it = temporary_reference_ranges_.find(sink_id); - if (temporary_it != temporary_reference_ranges_.end()) { - for (const LocalSurfaceId& local_id : temporary_it->second) { - if (surface_range.IsInRangeInclusive(SurfaceId(sink_id, local_id))) - valid_local_surfaces.push_back(local_id); - } - } - - // Get all valid persistent references. - auto persistent_it = persistent_references_by_frame_sink_id_.find(sink_id); - if (persistent_it != persistent_references_by_frame_sink_id_.end()) { - for (const LocalSurfaceId& local_id : persistent_it->second) { - if (surface_range.IsInRangeInclusive(SurfaceId(sink_id, local_id))) - valid_local_surfaces.push_back(local_id); - } - } - - // Sort all possible surfaces from newest to oldest, then return the first - // surface that has an active frame. - std::sort(valid_local_surfaces.begin(), valid_local_surfaces.end(), - [](const LocalSurfaceId& first, const LocalSurfaceId& second) { - return first > second; - }); - - for (const LocalSurfaceId& local_surface_id : valid_local_surfaces) { - Surface* surface = GetSurfaceForId(SurfaceId(sink_id, local_surface_id)); - if (surface && surface->HasActiveFrame()) - return surface; - } - return nullptr; -} - SurfaceManager::SurfaceIdSet SurfaceManager::GetLiveSurfacesForReferences() { SurfaceIdSet reachable_surfaces; @@ -343,10 +305,6 @@ references_[parent_id].insert(child_id); - // Add a real reference to child_id. - persistent_references_by_frame_sink_id_[child_id.frame_sink_id()].insert( - child_id.local_surface_id()); - for (auto& observer : observer_list_) observer.OnAddedSurfaceReference(parent_id, child_id); @@ -373,36 +331,12 @@ iter_parent->second.erase(child_iter); if (iter_parent->second.empty()) references_.erase(iter_parent); - - // Remove the presistent reference. - const FrameSinkId& sink_id = child_id.frame_sink_id(); - const LocalSurfaceId& local_id = child_id.local_surface_id(); - - auto sink_it = persistent_references_by_frame_sink_id_.find(sink_id); - if (sink_it == persistent_references_by_frame_sink_id_.end()) - return; - - auto local_surface_it = sink_it->second.find(local_id); - if (local_surface_it == sink_it->second.end()) - return; - - sink_it->second.erase(local_surface_it); - if (sink_it->second.empty()) - persistent_references_by_frame_sink_id_.erase(sink_it); } bool SurfaceManager::HasTemporaryReference(const SurfaceId& surface_id) const { return temporary_references_.count(surface_id) != 0; } -bool SurfaceManager::HasPersistentReference(const SurfaceId& surface_id) const { - auto it = - persistent_references_by_frame_sink_id_.find(surface_id.frame_sink_id()); - if (it == persistent_references_by_frame_sink_id_.end()) - return false; - return it->second.count(surface_id.local_surface_id()) != 0; -} - void SurfaceManager::AddTemporaryReference(const SurfaceId& surface_id) { DCHECK(!HasTemporaryReference(surface_id)); @@ -462,29 +396,24 @@ Surface* SurfaceManager::GetLatestInFlightSurface( const SurfaceRange& surface_range) { - // If primary exists, we return it. - Surface* primary_surface = GetSurfaceForId(surface_range.end()); - if (primary_surface && primary_surface->HasActiveFrame()) - return primary_surface; - - // If both end of the range exists, we try the primary's FrameSinkId first. - Surface* latest_surface = GetLatestInFlightSurfaceForFrameSinkId( - surface_range, surface_range.end().frame_sink_id()); - - // If the fallback has a different FrameSinkId, then try that also. - if (!latest_surface && surface_range.HasDifferentFrameSinkIds()) { - latest_surface = GetLatestInFlightSurfaceForFrameSinkId( - surface_range, surface_range.start()->frame_sink_id()); + SurfaceAllocationGroup* end_allocation_group = + GetAllocationGroupForSurfaceId(surface_range.end()); + if (end_allocation_group) { + Surface* result = + end_allocation_group->FindLatestActiveSurfaceInRange(surface_range); + if (result) + return result; } - - // Fallback might have neither temporary or presistent references, so we - // consider it separately. - if (!latest_surface && surface_range.start()) - latest_surface = GetSurfaceForId(*surface_range.start()); - - if (latest_surface && latest_surface->HasActiveFrame()) - return latest_surface; - return nullptr; + if (!surface_range.start() || + surface_range.start()->local_surface_id().embed_token() == + surface_range.end().local_surface_id().embed_token()) { + return nullptr; + } + SurfaceAllocationGroup* start_allocation_group = + GetAllocationGroupForSurfaceId(*surface_range.start()); + if (!start_allocation_group) + return nullptr; + return start_allocation_group->FindLatestActiveSurfaceInRange(surface_range); } void SurfaceManager::ExpireOldTemporaryReferences() { @@ -687,4 +616,18 @@ return allocation_group.get(); } +SurfaceAllocationGroup* SurfaceManager::GetAllocationGroupForSurfaceId( + const SurfaceId& surface_id) { + auto it = embed_token_to_allocation_group_.find( + surface_id.local_surface_id().embed_token()); + if (it == embed_token_to_allocation_group_.end()) + return nullptr; + DCHECK(it->second); + if (it->second->submitter_frame_sink_id() != surface_id.frame_sink_id()) { + DLOG(ERROR) << "Cannot reuse embed token across frame sinks"; + return nullptr; + } + return it->second.get(); +} + } // namespace viz
diff --git a/components/viz/service/surfaces/surface_manager.h b/components/viz/service/surfaces/surface_manager.h index 39811e121..8221842 100644 --- a/components/viz/service/surfaces/surface_manager.h +++ b/components/viz/service/surfaces/surface_manager.h
@@ -206,6 +206,11 @@ SurfaceAllocationGroup* GetOrCreateAllocationGroupForSurfaceId( const SurfaceId& surface_id); + // Similar to GetOrCreateAllocationGroupForSurfaceId, but will not attempt to + // create the allocation group if it does not already exist. + SurfaceAllocationGroup* GetAllocationGroupForSurfaceId( + const SurfaceId& surface_id); + private: friend class CompositorFrameSinkSupportTest; friend class FrameSinkManagerTest; @@ -233,11 +238,6 @@ bool marked_as_old = false; }; - // Returns the latest surface in a FrameSinkId that satisfies |is_valid|. - Surface* GetLatestInFlightSurfaceForFrameSinkId( - const SurfaceRange& surface_range, - const FrameSinkId& sink_id); - // Returns set of live surfaces for |lifetime_manager_| is REFERENCES. SurfaceIdSet GetLiveSurfacesForReferences(); @@ -254,9 +254,6 @@ // Returns whether |surface_id| has a temporary reference or not. bool HasTemporaryReference(const SurfaceId& surface_id) const; - // Returns whether |surface_id| has a Persistent reference or not. - bool HasPersistentReference(const SurfaceId& surface_id) const; - // Adds a temporary reference to |surface_id|. The reference will not have an // owner initially. void AddTemporaryReference(const SurfaceId& surface_id); @@ -331,11 +328,6 @@ std::unordered_map<FrameSinkId, std::vector<LocalSurfaceId>, FrameSinkIdHash> temporary_reference_ranges_; - // A list of surfaces with a given FrameSinkId that have a persistent - // reference. - base::flat_map<FrameSinkId, base::flat_set<LocalSurfaceId>> - persistent_references_by_frame_sink_id_; - // A map storing SurfaceIds interested in knowing about activation events // happending in FrameSinkId. base::flat_map<FrameSinkId, base::flat_set<SurfaceId>> activation_observers_;
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc index f0207f0..4fa2f08 100644 --- a/content/browser/devtools/protocol/network_handler.cc +++ b/content/browser/devtools/protocol/network_handler.cc
@@ -1927,16 +1927,16 @@ const protocol::Binary& raw = raw_response.fromJust(); std::string raw_headers; - int header_size = net::HttpUtil::LocateEndOfHeaders( + size_t header_size = net::HttpUtil::LocateEndOfHeaders( reinterpret_cast<const char*>(raw.data()), raw.size()); - if (header_size == -1) { + if (header_size == std::string::npos) { LOG(WARNING) << "Can't find headers in raw response"; header_size = 0; } else { raw_headers = net::HttpUtil::AssembleRawHeaders( reinterpret_cast<const char*>(raw.data()), header_size); } - CHECK_LE(static_cast<size_t>(header_size), raw.size()); + CHECK_LE(header_size, raw.size()); response_headers = base::MakeRefCounted<net::HttpResponseHeaders>(std::move(raw_headers)); response_body = raw.bytes();
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc index 073cc1cc..d30899a 100644 --- a/content/browser/frame_host/navigation_handle_impl.cc +++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -33,7 +33,6 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/site_instance.h" #include "content/public/common/child_process_host.h" -#include "content/public/common/content_client.h" #include "content/public/common/url_constants.h" #include "content/public/common/url_utils.h" #include "net/base/net_errors.h" @@ -155,7 +154,6 @@ reload_type_(ReloadType::NONE), restore_type_(RestoreType::NONE), navigation_type_(NAVIGATION_TYPE_UNKNOWN), - expected_render_process_host_id_(ChildProcessHost::kInvalidUniqueID), is_same_process_(true), throttle_runner_(this, this), weak_factory_(this) { @@ -167,12 +165,6 @@ DCHECK(!navigation_request_->common_params().navigation_start.is_null()); DCHECK(!IsRendererDebugURL(url)); - starting_site_instance_ = - frame_tree_node()->current_frame_host()->GetSiteInstance(); - - site_url_ = SiteInstanceImpl::GetSiteForURL( - starting_site_instance_->GetBrowserContext(), - starting_site_instance_->GetIsolationContext(), url); if (redirect_chain_.empty()) redirect_chain_.push_back(url); @@ -230,17 +222,6 @@ } NavigationHandleImpl::~NavigationHandleImpl() { - // Inform the RenderProcessHost to no longer expect a navigation. - if (expected_render_process_host_id_ != ChildProcessHost::kInvalidUniqueID) { - RenderProcessHost* process = - RenderProcessHost::FromID(expected_render_process_host_id_); - if (process) { - RenderProcessHostImpl::RemoveExpectedNavigationToSite( - frame_tree_node()->navigator()->GetController()->GetBrowserContext(), - process, site_url_); - } - } - #if defined(OS_ANDROID) navigation_handle_proxy_->DidFinish(); #endif @@ -269,7 +250,7 @@ } SiteInstanceImpl* NavigationHandleImpl::GetStartingSiteInstance() { - return starting_site_instance_.get(); + return navigation_request_->starting_site_instance(); } bool NavigationHandleImpl::IsInMainFrame() { @@ -636,7 +617,7 @@ "WillRedirectRequest", "url", GetURL().possibly_invalid_spec()); UpdateStateFollowingRedirect(new_referrer_url, std::move(callback)); - UpdateSiteURL(post_redirect_process); + navigation_request_->UpdateSiteURL(post_redirect_process); if (IsSelfReferentialURL()) { state_ = CANCELING; @@ -731,7 +712,7 @@ } } - SetExpectedProcess(GetRenderFrameHost()->GetProcess()); + navigation_request_->SetExpectedProcess(GetRenderFrameHost()->GetProcess()); if (!IsSameDocument()) GetDelegate()->ReadyToCommitNavigation(this); @@ -829,38 +810,6 @@ } } -void NavigationHandleImpl::SetExpectedProcess( - RenderProcessHost* expected_process) { - if (expected_process && - expected_process->GetID() == expected_render_process_host_id_) { - // This |expected_process| has already been informed of the navigation, - // no need to update it again. - return; - } - - // If a RenderProcessHost was expecting this navigation to commit, have it - // stop tracking this site. - RenderProcessHost* old_process = - RenderProcessHost::FromID(expected_render_process_host_id_); - if (old_process) { - RenderProcessHostImpl::RemoveExpectedNavigationToSite( - frame_tree_node()->navigator()->GetController()->GetBrowserContext(), - old_process, site_url_); - } - - if (expected_process == nullptr) { - expected_render_process_host_id_ = ChildProcessHost::kInvalidUniqueID; - return; - } - - // Keep track of the speculative RenderProcessHost and tell it to expect a - // navigation to |site_url_|. - expected_render_process_host_id_ = expected_process->GetID(); - RenderProcessHostImpl::AddExpectedNavigationToSite( - frame_tree_node()->navigator()->GetController()->GetBrowserContext(), - expected_process, site_url_); -} - void NavigationHandleImpl::OnNavigationEventProcessed( NavigationThrottleRunner::Event event, NavigationThrottle::ThrottleCheckResult result) { @@ -1021,30 +970,6 @@ return false; } -void NavigationHandleImpl::UpdateSiteURL( - RenderProcessHost* post_redirect_process) { - // TODO(alexmos): Using |starting_site_instance_|'s IsolationContext may not - // be correct for cross-BrowsingInstance redirects. - GURL new_site_url = SiteInstanceImpl::GetSiteForURL( - frame_tree_node()->navigator()->GetController()->GetBrowserContext(), - starting_site_instance_->GetIsolationContext(), GetURL()); - int post_redirect_process_id = post_redirect_process - ? post_redirect_process->GetID() - : ChildProcessHost::kInvalidUniqueID; - if (new_site_url == site_url_ && - post_redirect_process_id == expected_render_process_host_id_) { - return; - } - - // Stop expecting a navigation to the current site URL in the current expected - // process. - SetExpectedProcess(nullptr); - - // Update the site URL and the expected process. - site_url_ = new_site_url; - SetExpectedProcess(post_redirect_process); -} - void NavigationHandleImpl::RenderProcessBlockedStateChanged(bool blocked) { if (blocked) StopCommitTimeout();
diff --git a/content/browser/frame_host/navigation_handle_impl.h b/content/browser/frame_host/navigation_handle_impl.h index 7b636cbd..17b4489f 100644 --- a/content/browser/frame_host/navigation_handle_impl.h +++ b/content/browser/frame_host/navigation_handle_impl.h
@@ -326,11 +326,6 @@ return std::move(modified_request_headers_); } - // Sets ID of the RenderProcessHost we expect the navigation to commit in. - // This is used to inform the RenderProcessHost to expect a navigation to the - // url we're navigating to. - void SetExpectedProcess(RenderProcessHost* expected_process); - NavigationThrottle* GetDeferringThrottleForTesting() const { return throttle_runner_.GetDeferringThrottle(); } @@ -392,12 +387,6 @@ // WillStartRequest and WillRedirectRequest to prevent the navigation. bool IsSelfReferentialURL(); - // Updates the destination site URL for this navigation. This is called on - // redirects. |post_redirect_process| is the renderer process that should - // handle the navigation following the redirect if it can be handled by an - // existing RenderProcessHost. Otherwise, it should be null. - void UpdateSiteURL(RenderProcessHost* post_redirect_process); - // Called if READY_TO_COMMIT -> COMMIT state transition takes an unusually // long time. void OnCommitTimeout(); @@ -413,7 +402,6 @@ NavigationRequest* navigation_request_; // See NavigationHandle for a description of those member variables. - scoped_refptr<SiteInstanceImpl> starting_site_instance_; Referrer sanitized_referrer_; net::Error net_error_code_; const bool is_same_document_; @@ -422,9 +410,6 @@ bool should_update_history_; bool subframe_entry_committed_; - // The site URL of this navigation, as obtained from SiteInstance::GetSiteURL. - GURL site_url_; - // The headers used for the request. net::HttpRequestHeaders request_headers_; @@ -499,10 +484,6 @@ GURL base_url_; NavigationType navigation_type_; - // Used to inform a RenderProcessHost that we expect this navigation to commit - // in it. - int expected_render_process_host_id_; - // Which proxy server was used for this navigation, if any. net::ProxyServer proxy_server_;
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index 81c4941..68b3df2 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -496,6 +496,7 @@ from_begin_navigation_(from_begin_navigation), has_stale_copy_in_cache_(false), net_error_(net::OK), + expected_render_process_host_id_(ChildProcessHost::kInvalidUniqueID), devtools_navigation_token_(base::UnguessableToken::Create()), request_navigation_client_(nullptr), commit_navigation_client_(nullptr), @@ -542,6 +543,18 @@ bindings_ = entry->bindings(); } + // This is needed to get site URLs and assign the expected RenderProcessHost. + // This is not always the same as |source_site_instance|, as it only depends + // on the current frame host, and does not depend on |entry|. + starting_site_instance_ = + frame_tree_node->current_frame_host()->GetSiteInstance(); + + // TODO(alexmos): Using |starting_site_instance_|'s IsolationContext may not + // be correct for cross-BrowsingInstance redirects. + site_url_ = SiteInstanceImpl::GetSiteForURL( + starting_site_instance_->GetBrowserContext(), + starting_site_instance_->GetIsolationContext(), common_params_.url); + // Update the load flags with cache information. UpdateLoadFlagsWithCacheFlags(&begin_params_->load_flags, common_params_.navigation_type, @@ -617,6 +630,7 @@ NavigationRequest::~NavigationRequest() { TRACE_EVENT_ASYNC_END0("navigation", "NavigationRequest", this); + ResetExpectedProcess(); if (state_ == STARTED) { devtools_instrumentation::OnNavigationRequestFailed( *this, network::URLLoaderCompletionStatus(net::ERR_ABORTED)); @@ -1270,6 +1284,7 @@ void NavigationRequest::OnRequestFailed( const network::URLLoaderCompletionStatus& status) { + DCHECK_NE(status.error_code, net::OK); bool collapse_frame = status.extended_error_code == static_cast<int>(blink::ResourceRequestBlockedReason::kCollapsedByClient); @@ -1332,7 +1347,7 @@ // TODO(nasko): Investigate whether GetFrameHostForNavigation can properly // account for clearing the expected process if it clears the speculative // RenderFrameHost. See https://crbug.com/793127. - navigation_handle_->SetExpectedProcess(nullptr); + ResetExpectedProcess(); render_frame_host = frame_tree_node_->render_manager()->GetFrameHostForNavigation(*this); } else { @@ -1448,7 +1463,7 @@ : frame_tree_node_->current_frame_host(); DCHECK(navigating_frame_host); - navigation_handle_->SetExpectedProcess(navigating_frame_host->GetProcess()); + SetExpectedProcess(navigating_frame_host->GetProcess()); BrowserContext* browser_context = frame_tree_node_->navigator()->GetController()->GetBrowserContext(); @@ -1859,6 +1874,69 @@ render_frame_host_->GetSiteInstance()->GetBrowserContext()); } +void NavigationRequest::ResetExpectedProcess() { + if (expected_render_process_host_id_ == ChildProcessHost::kInvalidUniqueID) { + // No expected process is set, nothing to update. + return; + } + RenderProcessHost* process = + RenderProcessHost::FromID(expected_render_process_host_id_); + if (process) { + RenderProcessHostImpl::RemoveExpectedNavigationToSite( + frame_tree_node()->navigator()->GetController()->GetBrowserContext(), + process, site_url_); + } + expected_render_process_host_id_ = ChildProcessHost::kInvalidUniqueID; +} + +void NavigationRequest::SetExpectedProcess( + RenderProcessHost* expected_process) { + if (expected_process && + expected_process->GetID() == expected_render_process_host_id_) { + // This |expected_process| has already been informed of the navigation, + // no need to update it again. + return; + } + + ResetExpectedProcess(); + + if (expected_process == nullptr) { + expected_render_process_host_id_ = ChildProcessHost::kInvalidUniqueID; + return; + } + + // Keep track of the speculative RenderProcessHost and tell it to expect a + // navigation to |site_url_|. + expected_render_process_host_id_ = expected_process->GetID(); + RenderProcessHostImpl::AddExpectedNavigationToSite( + frame_tree_node()->navigator()->GetController()->GetBrowserContext(), + expected_process, site_url_); +} + +void NavigationRequest::UpdateSiteURL( + RenderProcessHost* post_redirect_process) { + // TODO(alexmos): Using |starting_site_instance_|'s IsolationContext may not + // be correct for cross-BrowsingInstance redirects. + GURL new_site_url = SiteInstanceImpl::GetSiteForURL( + frame_tree_node()->navigator()->GetController()->GetBrowserContext(), + starting_site_instance_->GetIsolationContext(), common_params_.url); + int post_redirect_process_id = post_redirect_process + ? post_redirect_process->GetID() + : ChildProcessHost::kInvalidUniqueID; + if (new_site_url == site_url_ && + post_redirect_process_id == expected_render_process_host_id_) { + return; + } + + // Stop expecting a navigation to the current site URL in the current expected + // process. + ResetExpectedProcess(); + + // Update the site URL and the expected process. + site_url_ = new_site_url; + SetExpectedProcess(post_redirect_process); +} + bool NavigationRequest::IsAllowedByCSPDirective( CSPContext* context, CSPDirective::Name directive,
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h index a8ec710d..7c16f465 100644 --- a/content/browser/frame_host/navigation_request.h +++ b/content/browser/frame_host/navigation_request.h
@@ -164,6 +164,10 @@ int bindings() const { return bindings_; } + SiteInstanceImpl* starting_site_instance() const { + return starting_site_instance_.get(); + } + bool browser_initiated() const { return browser_initiated_ ; } bool from_begin_navigation() const { return from_begin_navigation_; } @@ -213,6 +217,17 @@ on_start_checks_complete_closure_ = closure; } + // Sets ID of the RenderProcessHost we expect the navigation to commit in. + // This is used to inform the RenderProcessHost to expect a navigation to the + // url we're navigating to. + void SetExpectedProcess(RenderProcessHost* expected_process); + + // Updates the destination site URL for this navigation. This is called on + // redirects. |post_redirect_process| is the renderer process that should + // handle the navigation following the redirect if it can be handled by an + // existing RenderProcessHost. Otherwise, it should be null. + void UpdateSiteURL(RenderProcessHost* post_redirect_process); + int nav_entry_id() const { return nav_entry_id_; } // For automation driver-initiated navigations over the devtools protocol, @@ -396,6 +411,9 @@ // Only used with PerNavigationMojoInterface enabled. void IgnoreInterfaceDisconnection(); + // Inform the RenderProcessHost to no longer expect a navigation. + void ResetExpectedProcess(); + FrameTreeNode* frame_tree_node_; RenderFrameHostImpl* render_frame_host_ = nullptr; @@ -442,6 +460,8 @@ int bindings_; int nav_entry_id_ = 0; + scoped_refptr<SiteInstanceImpl> starting_site_instance_; + // Whether the navigation should be sent to a renderer a process. This is // true, except for 204/205 responses and downloads. bool response_should_be_rendered_; @@ -476,6 +496,13 @@ bool has_stale_copy_in_cache_; int net_error_; + // Identifies in which RenderProcessHost this navigation is expected to + // commit. + int expected_render_process_host_id_; + + // The site URL of this navigation, as obtained from SiteInstance::GetSiteURL. + GURL site_url_; + std::unique_ptr<InitiatorCSPContext> initiator_csp_context_; base::Closure on_start_checks_complete_closure_;
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc index db40189..4f1a7d82 100644 --- a/content/browser/loader/navigation_url_loader_impl.cc +++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/debug/dump_without_crashing.h" #include "base/feature_list.h" #include "base/metrics/histogram_macros.h" #include "base/optional.h" @@ -1315,21 +1316,28 @@ UMA_HISTOGRAM_BOOLEAN( "Navigation.URLLoaderNetworkService.OnCompleteHasSSLInfo", status.ssl_info.has_value()); + + // Successful load must have used OnResponseStarted first. In this case, the + // URLLoaderClient has already been transferred to the renderer process and + // OnComplete is not expected to be called here. + if (status.error_code == net::OK) { + base::debug::DumpWithoutCrashing(); + return; + } + if (status.ssl_info.has_value()) { UMA_HISTOGRAM_MEMORY_KB( "Navigation.URLLoaderNetworkService.OnCompleteCertificateChainsSize", GetCertificateChainsSizeInKB(status.ssl_info.value())); } - if (status.error_code != net::OK && !received_response_) { - // If the default loader (network) was used to handle the URL load - // request we need to see if the interceptors want to potentially create a - // new loader for the response. e.g. AppCache. - if (MaybeCreateLoaderForResponse(network::ResourceResponseHead())) - return; - } - status_ = status; + // If the default loader (network) was used to handle the URL load + // request we need to see if the interceptors want to potentially create a + // new loader for the response. e.g. AppCache. + if (MaybeCreateLoaderForResponse(network::ResourceResponseHead())) + return; + status_ = status; base::PostTaskWithTraits( FROM_HERE, {BrowserThread::UI}, base::BindOnce(&NavigationURLLoaderImpl::OnComplete, owner_, status)); @@ -1793,12 +1801,8 @@ void NavigationURLLoaderImpl::OnComplete( const network::URLLoaderCompletionStatus& status) { - if (status.error_code == net::OK) - return; - TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this, "&NavigationURLLoaderImpl", this, "success", false); - delegate_->OnRequestFailed(status); }
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc index 4e8b510c..79e3fb5d 100644 --- a/content/browser/renderer_host/render_widget_host_input_event_router.cc +++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -331,6 +331,10 @@ return touch_event_ack_queue_->length_for_testing(); } +size_t RenderWidgetHostInputEventRouter::RegisteredViewCountForTesting() const { + return owner_map_.size(); +} + void RenderWidgetHostInputEventRouter::OnRenderWidgetHostViewBaseDestroyed( RenderWidgetHostViewBase* view) { // RenderWidgetHostViewBase::RemoveObserver() should only ever be called
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.h b/content/browser/renderer_host/render_widget_host_input_event_router.h index ca8cd0c..137dd83 100644 --- a/content/browser/renderer_host/render_widget_host_input_event_router.h +++ b/content/browser/renderer_host/render_widget_host_input_event_router.h
@@ -169,6 +169,7 @@ bool HasEventsPendingDispatch() const; size_t TouchEventAckQueueLengthForTesting() const; + size_t RegisteredViewCountForTesting() const; private: FRIEND_TEST_ALL_PREFIXES(BrowserSideFlingBrowserTest,
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index 770cdea..26d4e7aa 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -14653,4 +14653,5 @@ InnerWebContentsAttachChildFrameOriginType::kCrossOrigin}), testing::Bool(), testing::Bool())); + } // namespace content
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 28984b3..58c6678 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1894,6 +1894,20 @@ return web_contents; } +void WebContentsImpl::RecursivelyRegisterFrameSinkIds() { + auto* view = static_cast<RenderWidgetHostViewBase*>( + GetRenderManager()->GetRenderWidgetHostView()); + DCHECK(view); + if (!view->IsRenderWidgetHostViewChildFrame()) + return; + static_cast<RenderWidgetHostViewChildFrame*>(view)->RegisterFrameSinkId(); + + for (auto* inner_web_contents : node_.GetInnerWebContents()) { + static_cast<WebContentsImpl*>(inner_web_contents) + ->RecursivelyRegisterFrameSinkIds(); + } +} + void WebContentsImpl::ReattachToOuterWebContentsFrame() { DCHECK(node_.outer_web_contents()); auto* render_manager = GetRenderManager(); @@ -1902,9 +1916,7 @@ render_manager->SetRWHViewForInnerContents( render_manager->GetRenderWidgetHostView()); - static_cast<RenderWidgetHostViewChildFrame*>( - render_manager->GetRenderWidgetHostView()) - ->RegisterFrameSinkId(); + RecursivelyRegisterFrameSinkIds(); // Set up the the guest's AX tree to point back at the embedder's AX tree. GetMainFrame()->set_browser_plugin_embedder_ax_tree_id(
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 568aa2e..25fcc96d 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -1301,6 +1301,10 @@ // These functions are helpers in managing a hierarchy of WebContents // involved in rendering inner WebContents. + // Registers FrameSinkIds for all WebContents in the subtree of + // WebContentsTree, rooted at |contents|. + void RecursivelyRegisterFrameSinkIds(); + // When multiple WebContents are present within a tab or window, a single one // is focused and will route keyboard events in most cases to a RenderWidget // contained within it. |GetFocusedWebContents()|'s main frame widget will
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc index be9986ee..d0e1df7 100644 --- a/content/browser/web_contents/web_contents_impl_browsertest.cc +++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -26,6 +26,7 @@ #include "content/browser/frame_host/navigation_entry_impl.h" #include "content/browser/loader/resource_dispatcher_host_impl.h" #include "content/browser/renderer_host/render_widget_host_impl.h" +#include "content/browser/renderer_host/render_widget_host_input_event_router.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/browser/web_contents/web_contents_view.h" #include "content/common/frame_messages.h" @@ -3265,4 +3266,50 @@ EXPECT_TRUE(EvalJs(web_contents.get(), "document.hidden").ExtractBool()); } +// This test verifies that if we attach an inner WebContents that has +// descendants in the WebContentsTree, that the descendants also have their +// views registered with the top-level WebContents' InputEventRouter. This +// ensures the descendants will receive events that should be routed to them. +IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, + AttachNestedInnerWebContents) { + ASSERT_TRUE(embedded_test_server()->Start()); + GURL main_url(embedded_test_server()->GetURL( + "a.com", "/cross_site_iframe_factory.html?a(a)")); + EXPECT_TRUE(NavigateToURL(shell(), main_url)); + + auto* root_web_contents = + static_cast<WebContentsImpl*>(shell()->web_contents()); + FrameTreeNode* root = root_web_contents->GetFrameTree()->root(); + ASSERT_EQ(1u, root->child_count()); + FrameTreeNode* child_to_replace = root->child_at(0); + auto* child_to_replace_rfh = child_to_replace->current_frame_host(); + + WebContents::CreateParams inner_params( + root_web_contents->GetBrowserContext()); + + std::unique_ptr<WebContents> child_contents_ptr = + WebContents::Create(inner_params); + auto* child_rfh = + static_cast<RenderFrameHostImpl*>(child_contents_ptr->GetMainFrame()); + + std::unique_ptr<WebContents> grandchild_contents_ptr = + WebContents::Create(inner_params); + + // Attach grandchild to child. + child_contents_ptr->AttachInnerWebContents(std::move(grandchild_contents_ptr), + child_rfh); + + // At this point the child hasn't been attached to the root. + EXPECT_EQ(1U, root_web_contents->GetInputEventRouter() + ->RegisteredViewCountForTesting()); + + // Attach child+grandchild subtree to root. + root_web_contents->AttachInnerWebContents(std::move(child_contents_ptr), + child_to_replace_rfh); + + // Verify views registered for both child and grandchild. + EXPECT_EQ(3U, root_web_contents->GetInputEventRouter() + ->RegisteredViewCountForTesting()); +} + } // namespace content
diff --git a/content/browser/worker_host/shared_worker_host.cc b/content/browser/worker_host/shared_worker_host.cc index f6d57ef..b280737 100644 --- a/content/browser/worker_host/shared_worker_host.cc +++ b/content/browser/worker_host/shared_worker_host.cc
@@ -29,7 +29,6 @@ #include "services/network/public/cpp/features.h" #include "third_party/blink/public/common/loader/url_loader_factory_bundle.h" #include "third_party/blink/public/common/messaging/message_port_channel.h" -#include "third_party/blink/public/common/service_worker/service_worker_utils.h" #include "third_party/blink/public/mojom/appcache/appcache.mojom.h" #include "third_party/blink/public/mojom/renderer_preference_watcher.mojom.h" #include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h" @@ -178,19 +177,17 @@ #if DCHECK_IS_ON() // Verify the combination of the given args based on the flags. See the // function comment for details. + DCHECK(service_worker_provider_info); + DCHECK(subresource_loader_factories); if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { // NetworkService (PlzWorker): - DCHECK(service_worker_provider_info); DCHECK(!main_script_loader_factory); DCHECK(main_script_load_params); - DCHECK(subresource_loader_factories); DCHECK(!subresource_loader_factories->default_factory_info()); } else { // non-NetworkService: - DCHECK(service_worker_provider_info); DCHECK(main_script_loader_factory); DCHECK(!main_script_load_params); - DCHECK(subresource_loader_factories); DCHECK(subresource_loader_factories->default_factory_info()); DCHECK(!controller); DCHECK(!controller_service_worker_object_host); @@ -237,7 +234,7 @@ mojo::MakeRequest(&interface_provider))); // Set the default factory to the bundle for subresource loading to pass to - // the renderer when NetworkService is on. When S13nServiceWorker is on, the + // the renderer when NetworkService is on. When NetworkService is off, the // default factory is already provided by // WorkerScriptFetchInitiator::CreateFactoryBundle(). if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
diff --git a/content/browser/worker_host/shared_worker_host.h b/content/browser/worker_host/shared_worker_host.h index 473de50..ef31b0c 100644 --- a/content/browser/worker_host/shared_worker_host.h +++ b/content/browser/worker_host/shared_worker_host.h
@@ -70,16 +70,13 @@ // Starts the SharedWorker in the renderer process. // - // S13nServiceWorker: // |service_worker_provider_info| is sent to the renderer process and contains // information about its ServiceWorkerProviderHost, the browser-side host for // supporting the shared worker as a service worker client. // - // S13nServiceWorker (non-NetworkService): // |main_script_loader_factory| is sent to the renderer process and is to be - // used to request the shared worker's main script. Currently it's only - // non-null when S13nServiceWorker is enabled but NetworkService is disabled, - // to allow service worker machinery to observe the request. + // used to request the shared worker's main script. This is null when + // NetworkService is enabled in favor of |main_script_load_params|. // // NetworkService (PlzWorker): // |main_script_load_params| is sent to the renderer process and to be used to @@ -97,8 +94,8 @@ // a ServiceWorker object about the controller is prepared, it is registered // to |controller_service_worker_object_host|. These can be non-null only when // NetworkService is enabled. - // When S13nServiceWorker is enabled but NetworkService is disabled, the - // service worker controller is sent via ServiceWorkerContainer#SetController. + // When NetworkService is disabled, the service worker controller is sent via + // ServiceWorkerContainer#SetController. void Start( blink::mojom::SharedWorkerFactoryPtr factory, blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
diff --git a/content/browser/worker_host/shared_worker_host_unittest.cc b/content/browser/worker_host/shared_worker_host_unittest.cc index f369fa6f..92e2738 100644 --- a/content/browser/worker_host/shared_worker_host_unittest.cc +++ b/content/browser/worker_host/shared_worker_host_unittest.cc
@@ -29,7 +29,6 @@ #include "services/network/public/cpp/features.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/messaging/message_port_channel.h" -#include "third_party/blink/public/common/service_worker/service_worker_utils.h" #include "url/origin.h" using blink::MessagePortChannel; @@ -81,8 +80,8 @@ subresource_loader_factories; base::Optional<SubresourceLoaderParams> subresource_loader_params; - // Set up various mocks based on NetworkService/S13nServiceWorker - // configuration. See the comment on SharedWorkerHost::Start() for details. + // Set up various mocks based on NetworkService configuration. See the + // comment on SharedWorkerHost::Start() for details. if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { provider_info = blink::mojom::ServiceWorkerProviderInfoForWorker::New(); ServiceWorkerProviderHost::PreCreateForSharedWorker( @@ -101,7 +100,7 @@ subresource_loader_params->appcache_loader_factory_info = loader_factory_ptr.PassInterface(); - } else if (blink::ServiceWorkerUtils::IsServicificationEnabled()) { + } else { provider_info = blink::mojom::ServiceWorkerProviderInfoForWorker::New(); ServiceWorkerProviderHost::PreCreateForSharedWorker( helper_->context()->AsWeakPtr(), mock_render_process_host_.GetID(),
diff --git a/content/browser/worker_host/shared_worker_service_impl.cc b/content/browser/worker_host/shared_worker_service_impl.cc index 7ccb93b3..fab8ac8 100644 --- a/content/browser/worker_host/shared_worker_service_impl.cc +++ b/content/browser/worker_host/shared_worker_service_impl.cc
@@ -37,7 +37,6 @@ #include "services/network/loader_util.h" #include "services/network/public/cpp/features.h" #include "third_party/blink/public/common/messaging/message_port_channel.h" -#include "third_party/blink/public/common/service_worker/service_worker_utils.h" #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h" #include "third_party/blink/public/mojom/worker/shared_worker_client.mojom.h" #include "third_party/blink/public/mojom/worker/shared_worker_info.mojom.h" @@ -195,39 +194,25 @@ auto weak_host = host->AsWeakPtr(); worker_hosts_.insert(std::move(host)); - if (blink::ServiceWorkerUtils::IsServicificationEnabled()) { - // NetworkService (PlzWorker): - // An appcache interceptor is available only when the network service is - // enabled. - AppCacheNavigationHandleCore* appcache_handle_core = nullptr; - if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { - auto appcache_handle = std::make_unique<AppCacheNavigationHandle>( - appcache_service_.get(), process_id); - appcache_handle_core = appcache_handle->core(); - weak_host->SetAppCacheHandle(std::move(appcache_handle)); - } - - WorkerScriptFetchInitiator::Start( - process_id, weak_host->instance()->url(), - weak_host->instance()->constructor_origin(), - RESOURCE_TYPE_SHARED_WORKER, service_worker_context_, - appcache_handle_core, std::move(blob_url_loader_factory), - storage_partition_, - base::BindOnce(&SharedWorkerServiceImpl::DidCreateScriptLoader, - weak_factory_.GetWeakPtr(), std::move(instance), - weak_host, std::move(client), process_id, frame_id, - message_port)); - return; + // NetworkService (PlzWorker): + // An appcache interceptor is available only when the network service is + // enabled. + AppCacheNavigationHandleCore* appcache_handle_core = nullptr; + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { + auto appcache_handle = std::make_unique<AppCacheNavigationHandle>( + appcache_service_.get(), process_id); + appcache_handle_core = appcache_handle->core(); + weak_host->SetAppCacheHandle(std::move(appcache_handle)); } - // Legacy case (to be deprecated): - StartWorker(std::move(instance), weak_host, std::move(client), process_id, - frame_id, message_port, - nullptr /* service_worker_provider_info */, - {} /* main_script_loader_factory */, - nullptr /* subresource_loader_factories */, - nullptr /* main_script_load_params */, nullptr /* controller */, - nullptr /* controller_service_worker_object_host */); + WorkerScriptFetchInitiator::Start( + process_id, weak_host->instance()->url(), + weak_host->instance()->constructor_origin(), RESOURCE_TYPE_SHARED_WORKER, + service_worker_context_, appcache_handle_core, + std::move(blob_url_loader_factory), storage_partition_, + base::BindOnce(&SharedWorkerServiceImpl::DidCreateScriptLoader, + weak_factory_.GetWeakPtr(), std::move(instance), weak_host, + std::move(client), process_id, frame_id, message_port)); } void SharedWorkerServiceImpl::DidCreateScriptLoader( @@ -249,7 +234,6 @@ controller_service_worker_object_host, bool success) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled()); // NetworkService (PlzWorker): // If the script fetcher fails to load shared worker's main script, notify the
diff --git a/content/browser/worker_host/worker_script_fetch_initiator.cc b/content/browser/worker_host/worker_script_fetch_initiator.cc index 7213bb5e..81453c2 100644 --- a/content/browser/worker_host/worker_script_fetch_initiator.cc +++ b/content/browser/worker_host/worker_script_fetch_initiator.cc
@@ -40,7 +40,6 @@ #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "third_party/blink/public/common/loader//url_loader_factory_bundle.h" -#include "third_party/blink/public/common/service_worker/service_worker_utils.h" #include "third_party/blink/public/mojom/renderer_preferences.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h" #include "url/origin.h" @@ -58,7 +57,6 @@ StoragePartitionImpl* storage_partition, CompletionCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled()); DCHECK(storage_partition); DCHECK(resource_type == RESOURCE_TYPE_WORKER || resource_type == RESOURCE_TYPE_SHARED_WORKER) @@ -129,7 +127,6 @@ StoragePartitionImpl* storage_partition, bool file_support) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled()); ContentBrowserClient::NonNetworkURLLoaderFactoryMap non_network_factories; GetContentClient() @@ -254,7 +251,6 @@ blob_url_loader_factory_info, CompletionCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled()); DCHECK(resource_context); // Set up for service worker.
diff --git a/content/browser/worker_host/worker_script_loader_factory.cc b/content/browser/worker_host/worker_script_loader_factory.cc index 65a7f7d..433a6a67 100644 --- a/content/browser/worker_host/worker_script_loader_factory.cc +++ b/content/browser/worker_host/worker_script_loader_factory.cc
@@ -14,7 +14,6 @@ #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/resource_response.h" #include "services/network/public/cpp/shared_url_loader_factory.h" -#include "third_party/blink/public/common/service_worker/service_worker_utils.h" #include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h" namespace content { @@ -32,7 +31,6 @@ loader_factory_(std::move(loader_factory)) { #if DCHECK_IS_ON() DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled()); // In the current implementation, dedicated workers use // ServiceWorkerProviderHost w/ kForSharedWorker. // TODO(nhiroki): Rename it to kForWorker for both dedicated workers and
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index 0d817a9..58645639 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -310,7 +310,7 @@ IPC_STRUCT_TRAITS_MEMBER(connection_info) IPC_STRUCT_TRAITS_MEMBER(timing) IPC_STRUCT_TRAITS_MEMBER(last_redirect_end_time) - IPC_STRUCT_TRAITS_MEMBER(finish_time) + IPC_STRUCT_TRAITS_MEMBER(response_end) IPC_STRUCT_TRAITS_MEMBER(transfer_size) IPC_STRUCT_TRAITS_MEMBER(encoded_body_size) IPC_STRUCT_TRAITS_MEMBER(decoded_body_size)
diff --git a/content/common/resource_timing_info.h b/content/common/resource_timing_info.h index d8301d3..0f3d587 100644 --- a/content/common/resource_timing_info.h +++ b/content/common/resource_timing_info.h
@@ -72,7 +72,7 @@ std::string connection_info; base::Optional<ResourceLoadTiming> timing; base::TimeTicks last_redirect_end_time; - base::TimeTicks finish_time; + base::TimeTicks response_end; uint64_t transfer_size = 0; uint64_t encoded_body_size = 0; uint64_t decoded_body_size = 0;
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/BrowserTaskExecutor.java b/content/public/android/java/src/org/chromium/content_public/browser/BrowserTaskExecutor.java index e457409..957256e 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/BrowserTaskExecutor.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/BrowserTaskExecutor.java
@@ -16,6 +16,8 @@ import java.util.WeakHashMap; +import javax.annotation.concurrent.GuardedBy; + /** * This {@link TaskExecutor} is for tasks posted with {@link UiThreadTaskTraits}. It maps directly * to content::BrowserTaskExecutor except only UI thread posting is supported from java. @@ -58,6 +60,11 @@ createSingleThreadTaskRunner(taskTraits).postDelayedTask(task, delay); } + @Override + public boolean canRunTaskImmediately(TaskTraits traits) { + return createSingleThreadTaskRunner(traits).belongsToCurrentThread(); + } + public static void register() { // In some tests we will get called multiple times. if (sRegistered) return; @@ -67,6 +74,7 @@ UiThreadTaskTraitsImpl.DESCRIPTOR.getId(), new BrowserTaskExecutor()); } + @GuardedBy("mTaskRunners") private final WeakHashMap<TaskTraits, SingleThreadTaskRunner> mTaskRunners = new WeakHashMap<>();
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/scheduler/NativePostTaskTest.java b/content/public/android/javatests/src/org/chromium/content/browser/scheduler/NativePostTaskTest.java index d4081fa..38641d1a 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/scheduler/NativePostTaskTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/scheduler/NativePostTaskTest.java
@@ -61,13 +61,10 @@ } } }); + synchronized (lock) { - try { - while (!taskExecuted.get()) { - lock.wait(); - } - } catch (InterruptedException ie) { - ie.printStackTrace(); + while (!taskExecuted.get()) { + lock.wait(); } } } @@ -88,16 +85,12 @@ Assert.assertFalse(taskExecuted.get()); startNativeScheduler(); - try { - // The task should now be scheduled at some point after the delay, so the test shouldn't - // time out. - synchronized (lock) { - while (!taskExecuted.get()) { - lock.wait(); - } + // The task should now be scheduled at some point after the delay, so the test shouldn't + // time out. + synchronized (lock) { + while (!taskExecuted.get()) { + lock.wait(); } - } catch (InterruptedException ie) { - ie.printStackTrace(); } } @@ -169,9 +162,9 @@ public void testCreateTaskRunnerMigrationToNative() throws Exception { final Object lock = new Object(); final AtomicBoolean taskExecuted = new AtomicBoolean(); - TaskRunner taskQueue = PostTask.createSequencedTaskRunner(new TaskTraits()); + TaskRunner taskQueue = PostTask.createTaskRunner(new TaskTraits()); - taskQueue.postDelayedTask(new Runnable() { + postRepeatingTaskAndStartNativeSchedulerThenWaitForTaskToRun(taskQueue, new Runnable() { @Override public void run() { synchronized (lock) { @@ -179,23 +172,18 @@ lock.notify(); } } - }, 1); - taskQueue.destroy(); - - // We verify that the task didn't get scheduled before the native scheduler is initialised - Assert.assertFalse(taskExecuted.get()); - startNativeScheduler(); + }); try { - // The task should now be scheduled at some point after the delay, so the test shouldn't + // The task should run at some point after the migration, so the test shouldn't // time out. synchronized (lock) { while (!taskExecuted.get()) { lock.wait(); } } - } catch (InterruptedException ie) { - ie.printStackTrace(); + } finally { + taskQueue.destroy(); } } @@ -258,12 +246,8 @@ nativeSchedulerStarted.set(true); synchronized (lock) { - try { - while (!taskRun.get()) { - lock.wait(); - } - } catch (InterruptedException ie) { - ie.printStackTrace(); + while (!taskRun.get()) { + lock.wait(); } } }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/scheduler/UiThreadSchedulerTest.java b/content/public/android/javatests/src/org/chromium/content/browser/scheduler/UiThreadSchedulerTest.java index 67f7bb6..95f4b28 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/scheduler/UiThreadSchedulerTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/scheduler/UiThreadSchedulerTest.java
@@ -140,6 +140,35 @@ } } + @Test + @MediumTest + public void testRunOrPostTask() throws InterruptedException { + final Object lock = new Object(); + final AtomicBoolean taskExecuted = new AtomicBoolean(); + List<Integer> orderList = new ArrayList<>(); + PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> { + // We are running on the UI thread now. First, we post a task on the + // UI thread; it will not run immediately because the UI thread is + // busy running the current code: + PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> { + orderList.add(1); + synchronized (lock) { + taskExecuted.set(true); + lock.notify(); + } + }); + // Now, we runOrPost a task on the UI thread. We are on the UI thread, + // so it will run immediately. + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { orderList.add(2); }); + }); + synchronized (lock) { + while (!taskExecuted.get()) { + lock.wait(); + } + } + assertThat(orderList, contains(2, 1)); + } + private void startContentMainOnUiThread() { final Object lock = new Object(); final AtomicBoolean uiThreadInitalized = new AtomicBoolean();
diff --git a/content/public/test/test_utils.cc b/content/public/test/test_utils.cc index 151f062..a9dfae8 100644 --- a/content/public/test/test_utils.cc +++ b/content/public/test/test_utils.cc
@@ -244,40 +244,12 @@ kFakeTrialName, kFakeTrialGroupName, param_values, command_line); } -namespace { - -// Helper class for CreateAndAttachInnerContents. -// -// TODO(lfg): https://crbug.com/821187 Inner webcontentses currently require -// supplying a BrowserPluginGuestDelegate; however, the oopif architecture -// doesn't really require it. Refactor this so that we can create an inner -// contents without any of the guest machinery. -class InnerWebContentsHelper : public WebContentsObserver { - public: - explicit InnerWebContentsHelper() : WebContentsObserver() {} - ~InnerWebContentsHelper() override = default; - - // WebContentsObserver: - void WebContentsDestroyed() override { delete this; } - - void SetInnerWebContents(WebContents* inner_web_contents) { - Observe(inner_web_contents); - } - - private: - DISALLOW_COPY_AND_ASSIGN(InnerWebContentsHelper); -}; - -} // namespace - WebContents* CreateAndAttachInnerContents(RenderFrameHost* rfh) { WebContents* outer_contents = static_cast<RenderFrameHostImpl*>(rfh)->delegate()->GetAsWebContents(); if (!outer_contents) return nullptr; - auto guest_delegate = std::make_unique<InnerWebContentsHelper>(); - WebContents::CreateParams inner_params(outer_contents->GetBrowserContext()); std::unique_ptr<WebContents> inner_contents_ptr = @@ -287,9 +259,6 @@ WebContents* inner_contents = inner_contents_ptr.get(); outer_contents->AttachInnerWebContents(std::move(inner_contents_ptr), rfh); - // |guest_delegate| becomes owned by |inner_contents|. - guest_delegate.release()->SetInnerWebContents(inner_contents); - return inner_contents; }
diff --git a/content/renderer/media/webrtc/rtc_peer_connection_handler.cc b/content/renderer/media/webrtc/rtc_peer_connection_handler.cc index 947d5c6..ff4f8f65 100644 --- a/content/renderer/media/webrtc/rtc_peer_connection_handler.cc +++ b/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
@@ -857,16 +857,16 @@ handler_->OnRenegotiationNeeded(); } } - void OnStandardizedIceConnectionChange( - PeerConnectionInterface::IceConnectionState new_state) override {} + void OnIceConnectionChange( + PeerConnectionInterface::IceConnectionState new_state) override {} + void OnStandardizedIceConnectionChange( PeerConnectionInterface::IceConnectionState new_state) override { if (!main_thread_->BelongsToCurrentThread()) { main_thread_->PostTask( - FROM_HERE, - base::BindOnce( - &RTCPeerConnectionHandler::Observer::OnIceConnectionChange, this, - new_state)); + FROM_HERE, base::BindOnce(&RTCPeerConnectionHandler::Observer:: + OnStandardizedIceConnectionChange, + this, new_state)); } else if (handler_) { handler_->OnIceConnectionChange(new_state); }
diff --git a/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc b/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc index 2bce931..07d65e5 100644 --- a/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc +++ b/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc
@@ -1046,7 +1046,7 @@ EXPECT_CALL(*mock_client_.get(), DidChangeIceConnectionState( webrtc::PeerConnectionInterface::kIceConnectionNew)); - pc_handler_->observer()->OnIceConnectionChange(new_state); + pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state); new_state = webrtc::PeerConnectionInterface::kIceConnectionChecking; EXPECT_CALL(*mock_tracker_.get(), @@ -1056,7 +1056,7 @@ EXPECT_CALL(*mock_client_.get(), DidChangeIceConnectionState( webrtc::PeerConnectionInterface::kIceConnectionChecking)); - pc_handler_->observer()->OnIceConnectionChange(new_state); + pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state); new_state = webrtc::PeerConnectionInterface::kIceConnectionConnected; EXPECT_CALL(*mock_tracker_.get(), @@ -1066,7 +1066,7 @@ EXPECT_CALL(*mock_client_.get(), DidChangeIceConnectionState( webrtc::PeerConnectionInterface::kIceConnectionConnected)); - pc_handler_->observer()->OnIceConnectionChange(new_state); + pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state); new_state = webrtc::PeerConnectionInterface::kIceConnectionCompleted; EXPECT_CALL(*mock_tracker_.get(), @@ -1076,7 +1076,7 @@ EXPECT_CALL(*mock_client_.get(), DidChangeIceConnectionState( webrtc::PeerConnectionInterface::kIceConnectionCompleted)); - pc_handler_->observer()->OnIceConnectionChange(new_state); + pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state); new_state = webrtc::PeerConnectionInterface::kIceConnectionFailed; EXPECT_CALL(*mock_tracker_.get(), @@ -1086,7 +1086,7 @@ EXPECT_CALL(*mock_client_.get(), DidChangeIceConnectionState( webrtc::PeerConnectionInterface::kIceConnectionFailed)); - pc_handler_->observer()->OnIceConnectionChange(new_state); + pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state); new_state = webrtc::PeerConnectionInterface::kIceConnectionDisconnected; EXPECT_CALL(*mock_tracker_.get(), @@ -1096,7 +1096,7 @@ EXPECT_CALL(*mock_client_.get(), DidChangeIceConnectionState( webrtc::PeerConnectionInterface::kIceConnectionDisconnected)); - pc_handler_->observer()->OnIceConnectionChange(new_state); + pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state); new_state = webrtc::PeerConnectionInterface::kIceConnectionClosed; EXPECT_CALL(*mock_tracker_.get(), @@ -1106,7 +1106,7 @@ EXPECT_CALL(*mock_client_.get(), DidChangeIceConnectionState( webrtc::PeerConnectionInterface::kIceConnectionClosed)); - pc_handler_->observer()->OnIceConnectionChange(new_state); + pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state); } TEST_F(RTCPeerConnectionHandlerTest, OnIceGatheringChange) {
diff --git a/content/renderer/resource_timing_info_conversions.cc b/content/renderer/resource_timing_info_conversions.cc index 9a175a8..fa5c48d 100644 --- a/content/renderer/resource_timing_info_conversions.cc +++ b/content/renderer/resource_timing_info_conversions.cc
@@ -49,7 +49,7 @@ } resource_timing.last_redirect_end_time = info.last_redirect_end_time; - resource_timing.finish_time = info.finish_time; + resource_timing.response_end = info.response_end; resource_timing.transfer_size = info.transfer_size; resource_timing.encoded_body_size = info.encoded_body_size; @@ -109,7 +109,7 @@ } info.last_redirect_end_time = resource_timing.last_redirect_end_time; - info.finish_time = resource_timing.finish_time; + info.response_end = resource_timing.response_end; info.transfer_size = resource_timing.transfer_size; info.encoded_body_size = resource_timing.encoded_body_size;
diff --git a/content/renderer/worker/embedded_shared_worker_stub.cc b/content/renderer/worker/embedded_shared_worker_stub.cc index cf5707e..18a200b 100644 --- a/content/renderer/worker/embedded_shared_worker_stub.cc +++ b/content/renderer/worker/embedded_shared_worker_stub.cc
@@ -20,7 +20,6 @@ #include "content/renderer/loader/navigation_response_override_parameters.h" #include "content/renderer/loader/tracked_child_url_loader_factory_bundle.h" #include "content/renderer/loader/web_worker_fetch_context_impl.h" -#include "content/renderer/render_thread_impl.h" #include "content/renderer/renderer_blink_platform_impl.h" #include "content/renderer/service_worker/service_worker_provider_context.h" #include "content/renderer/worker/service_worker_network_provider_for_worker.h" @@ -31,7 +30,6 @@ #include "third_party/blink/public/common/loader/url_loader_factory_bundle.h" #include "third_party/blink/public/common/messaging/message_port_channel.h" #include "third_party/blink/public/common/privacy_preferences.h" -#include "third_party/blink/public/common/service_worker/service_worker_utils.h" #include "third_party/blink/public/mojom/appcache/appcache.mojom.h" #include "third_party/blink/public/mojom/renderer_preferences.mojom.h" #include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom.h" @@ -113,6 +111,7 @@ renderer_preferences_(renderer_preferences), preference_watcher_request_(std::move(preference_watcher_request)), appcache_host_id_(appcache_host_id) { + DCHECK(factory_bundle); // The ID of the precreated AppCacheHost can be valid only when the // NetworkService is enabled. DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService) || @@ -141,45 +140,25 @@ main_script_loader_factory_ = std::move(main_script_loader_factory); controller_info_ = std::move(controller_info); - // |factory_bundle| is provided in the - // ServiceWorkerServicification or NetworkService case. - DCHECK(factory_bundle || - !blink::ServiceWorkerUtils::IsServicificationEnabled()); + // If the network service crashes, then self-destruct so clients don't get + // stuck with a worker with a broken loader. Self-destruction is effectively + // the same as the worker's process crashing. + if (IsOutOfProcessNetworkService()) { + default_factory_connection_error_handler_holder_.Bind( + std::move(factory_bundle->default_factory_info())); + default_factory_connection_error_handler_holder_->Clone( + mojo::MakeRequest(&factory_bundle->default_factory_info())); + default_factory_connection_error_handler_holder_ + .set_connection_error_handler(base::BindOnce( + &EmbeddedSharedWorkerStub::Terminate, base::Unretained(this))); + } - // Make the factory bundle. subresource_loader_factories_ = base::MakeRefCounted<HostChildURLLoaderFactoryBundle>( impl_->GetTaskRunner(blink::TaskType::kInternalLoading)); - - // If NetworkService or S13nSW is enabled, the default factory must be - // given as a |factory_bundle|. - // In some tests |render_thread| could be null. - RenderThreadImpl* render_thread = RenderThreadImpl::current(); - if (render_thread && !blink::ServiceWorkerUtils::IsServicificationEnabled()) { - subresource_loader_factories_->Update( - render_thread->blink_platform_impl() - ->CreateDefaultURLLoaderFactoryBundle() - ->PassInterface()); - } - - if (factory_bundle) { - // If the network service crashes, then self-destruct so clients don't get - // stuck with a worker with a broken loader. Self-destruction is effectively - // the same as the worker's process crashing. - if (IsOutOfProcessNetworkService()) { - default_factory_connection_error_handler_holder_.Bind( - std::move(factory_bundle->default_factory_info())); - default_factory_connection_error_handler_holder_->Clone( - mojo::MakeRequest(&factory_bundle->default_factory_info())); - default_factory_connection_error_handler_holder_ - .set_connection_error_handler(base::BindOnce( - &EmbeddedSharedWorkerStub::Terminate, base::Unretained(this))); - } - - subresource_loader_factories_->Update( - std::make_unique<ChildURLLoaderFactoryBundleInfo>( - std::move(factory_bundle))); - } + subresource_loader_factories_->Update( + std::make_unique<ChildURLLoaderFactoryBundleInfo>( + std::move(factory_bundle))); impl_->StartWorkerContext( url_, blink::WebString::FromUTF8(name_),
diff --git a/content/renderer/worker/embedded_shared_worker_stub.h b/content/renderer/worker/embedded_shared_worker_stub.h index d5d248e..5fb382c 100644 --- a/content/renderer/worker/embedded_shared_worker_stub.h +++ b/content/renderer/worker/embedded_shared_worker_stub.h
@@ -127,8 +127,7 @@ const int appcache_host_id_; WebApplicationCacheHostImpl* app_cache_host_ = nullptr; // Not owned. - // S13nServiceWorker: The info needed to connect to the - // ServiceWorkerProviderHost on the browser. + // The info needed to connect to the ServiceWorkerProviderHost on the browser. blink::mojom::ServiceWorkerProviderInfoForWorkerPtr service_worker_provider_info_; @@ -139,8 +138,7 @@ // NetworkService: blink::mojom::ControllerServiceWorkerInfoPtr controller_info_; - // S13nServiceWorker: The factory bundle used for loading subresources for - // this shared worker. + // The factory bundle used for loading subresources for this shared worker. scoped_refptr<HostChildURLLoaderFactoryBundle> subresource_loader_factories_; // NetworkService (PlzWorker): The response override parameters used for
diff --git a/content/renderer/worker/service_worker_network_provider_for_worker.cc b/content/renderer/worker/service_worker_network_provider_for_worker.cc index 1106d554..f2cffab 100644 --- a/content/renderer/worker/service_worker_network_provider_for_worker.cc +++ b/content/renderer/worker/service_worker_network_provider_for_worker.cc
@@ -29,47 +29,17 @@ scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory, bool is_secure_context, std::unique_ptr<NavigationResponseOverrideParameters> response_override) { + DCHECK(info); auto provider = base::WrapUnique(new ServiceWorkerNetworkProviderForWorker( is_secure_context, std::move(response_override))); - if (blink::ServiceWorkerUtils::IsServicificationEnabled()) { - DCHECK(info); - provider->context_ = base::MakeRefCounted<ServiceWorkerProviderContext>( - info->provider_id, - blink::mojom::ServiceWorkerProviderType::kForSharedWorker, - std::move(info->client_request), std::move(info->host_ptr_info), - std::move(controller_info), std::move(fallback_loader_factory)); - if (script_loader_factory_info.is_valid()) { - provider->script_loader_factory_.Bind( - std::move(script_loader_factory_info)); - } - } else { - DCHECK(!info); - int provider_id = ServiceWorkerProviderContext::GetNextId(); - auto host_info = blink::mojom::ServiceWorkerProviderHostInfo::New( - provider_id, MSG_ROUTING_NONE, - blink::mojom::ServiceWorkerProviderType::kForSharedWorker, - true /* is_parent_frame_secure */, nullptr /* host_request */, - nullptr /* client_ptr_info */); - blink::mojom::ServiceWorkerContainerAssociatedRequest client_request = - mojo::MakeRequest(&host_info->client_ptr_info); - blink::mojom::ServiceWorkerContainerHostAssociatedPtrInfo host_ptr_info; - host_info->host_request = mojo::MakeRequest(&host_ptr_info); - - provider->context_ = base::MakeRefCounted<ServiceWorkerProviderContext>( - provider_id, blink::mojom::ServiceWorkerProviderType::kForSharedWorker, - std::move(client_request), std::move(host_ptr_info), - std::move(controller_info), std::move(fallback_loader_factory)); - if (ChildThreadImpl::current()) { - ChildThreadImpl::current()->channel()->GetRemoteAssociatedInterface( - &provider->dispatcher_host_); - provider->dispatcher_host_->OnProviderCreated(std::move(host_info)); - } else { - // current() may be null in tests. Silently drop messages sent over - // ServiceWorkerContainerHost since we couldn't set it up correctly due - // to this test limitation. This way we don't crash when the associated - // interface ptr is used. - mojo::AssociateWithDisconnectedPipe(host_info->host_request.PassHandle()); - } + provider->context_ = base::MakeRefCounted<ServiceWorkerProviderContext>( + info->provider_id, + blink::mojom::ServiceWorkerProviderType::kForSharedWorker, + std::move(info->client_request), std::move(info->host_ptr_info), + std::move(controller_info), std::move(fallback_loader_factory)); + if (script_loader_factory_info.is_valid()) { + provider->script_loader_factory_.Bind( + std::move(script_loader_factory_info)); } return provider; } @@ -107,11 +77,6 @@ return nullptr; } - // S13nServiceWorker: - // We only install our own URLLoader if Servicification is enabled. - if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) - return nullptr; - // If the |script_loader_factory_| exists, use it. if (script_loader_factory_) { RenderThreadImpl* render_thread = RenderThreadImpl::current();
diff --git a/content/renderer/worker/service_worker_network_provider_for_worker.h b/content/renderer/worker/service_worker_network_provider_for_worker.h index 946f76c..fc8d6f29 100644 --- a/content/renderer/worker/service_worker_network_provider_for_worker.h +++ b/content/renderer/worker/service_worker_network_provider_for_worker.h
@@ -26,8 +26,7 @@ class ServiceWorkerNetworkProviderForWorker final : public blink::WebServiceWorkerNetworkProvider { public: - // Creates a new instance. Some params might only be used in S13nServiceWorker - // or PlzSharedWorker. + // Creates a new instance. // - |info|: provider info from the browser // - |script_loader_factory_info|: the factory for loading the worker's // scripts
diff --git a/content/test/data/accessibility/event/live-region-change.html b/content/test/data/accessibility/event/live-region-change.html index 9898d95b..caf272b 100644 --- a/content/test/data/accessibility/event/live-region-change.html +++ b/content/test/data/accessibility/event/live-region-change.html
@@ -4,7 +4,7 @@ <div id="live" aria-live="polite">Before</div> <script> function go() { - document.getElementById('live').innerText = 'After'; + document.getElementById('live').firstChild.data = 'After'; } </script> </body>
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json index 5309636..e96ecfc4 100644 --- a/gpu/config/gpu_driver_bug_list.json +++ b/gpu/config/gpu_driver_bug_list.json
@@ -3183,6 +3183,30 @@ "features": [ "disable_direct_composition_layers" ] + }, + { + "id": 295, + "description": "Avoid waiting on a egl fence before swapping buffers and rely on implicit sync on Intel GPUs", + "cr_bugs": [938286], + "os": { + "type": "linux" + }, + "gl_vendor": "Intel.*", + "features": [ + "rely_on_implicit_sync_for_swap_buffers" + ] + }, + { + "id": 296, + "description": "Avoid waiting on a egl fence before swapping buffers and rely on implicit sync on Broadcom GPUs", + "cr_bugs": [938286], + "os": { + "type": "linux" + }, + "gl_vendor": "Broadcom.*", + "features": [ + "rely_on_implicit_sync_for_swap_buffers" + ] } ] }
diff --git a/ios/chrome/app/application_delegate/user_activity_handler.mm b/ios/chrome/app/application_delegate/user_activity_handler.mm index 018f840..46d4c86 100644 --- a/ios/chrome/app/application_delegate/user_activity_handler.mm +++ b/ios/chrome/app/application_delegate/user_activity_handler.mm
@@ -23,10 +23,8 @@ #include "ios/chrome/browser/chrome_url_constants.h" #include "ios/chrome/browser/metrics/first_user_action_recorder.h" #include "ios/chrome/browser/system_flags.h" -#import "ios/chrome/browser/tabs/legacy_tab_helper.h" -#import "ios/chrome/browser/tabs/tab.h" #import "ios/chrome/browser/tabs/tab_model.h" -#import "ios/chrome/browser/u2f/u2f_controller.h" +#import "ios/chrome/browser/u2f/u2f_tab_helper.h" #import "ios/chrome/browser/ui/main/browser_interface_provider.h" #import "ios/chrome/browser/web/tab_id_tab_helper.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" @@ -237,13 +235,12 @@ if ([startupInformation isPresentingFirstRunUI]) return; + GURL externalURL = startupInformation.startupParameters.externalURL; // Check if it's an U2F call. If so, route it to correct tab. // If not, open or reuse tab in main BVC. - if ([U2FController - isU2FURL:[[startupInformation startupParameters] externalURL]]) { - [UserActivityHandler - routeU2FURL:[[startupInformation startupParameters] externalURL] - interfaceProvider:interfaceProvider]; + if (U2FTabHelper::IsU2FUrl(externalURL)) { + [UserActivityHandler routeU2FURL:externalURL + interfaceProvider:interfaceProvider]; // It's OK to clear startup parameters here because routeU2FURL works // synchronously. [startupInformation setStartupParameters:nil]; @@ -270,7 +267,6 @@ GURL URL; GURL virtualURL; GURL completeURL = startupInformation.startupParameters.completeURL; - GURL externalURL = startupInformation.startupParameters.externalURL; if (completeURL.SchemeIsFile() && base::FeatureList::IsEnabled( experimental_flags::kExternalFilesLoadedInWebState)) { @@ -342,7 +338,7 @@ + (void)routeU2FURL:(const GURL&)URL interfaceProvider:(id<BrowserInterfaceProvider>)interfaceProvider { // Retrieve the designated TabID from U2F URL. - NSString* tabID = [U2FController tabIDFromResponseURL:URL]; + NSString* tabID = U2FTabHelper::GetTabIdFromU2FUrl(URL); if (!tabID) { return; } @@ -358,8 +354,7 @@ web::WebState* webState = webStateList->GetWebStateAt(index); NSString* currentTabID = TabIdTabHelper::FromWebState(webState)->tab_id(); if ([currentTabID isEqualToString:tabID]) { - Tab* tab = LegacyTabHelper::GetTabForWebState(webState); - [tab evaluateU2FResultFromURL:URL]; + U2FTabHelper::FromWebState(webState)->EvaluateU2FResult(URL); } } }
diff --git a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm index 6a2ef7a..fc028fc 100644 --- a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm +++ b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
@@ -30,7 +30,7 @@ #import "ios/chrome/browser/tabs/tab.h" #import "ios/chrome/browser/tabs/tab_model.h" #import "ios/chrome/browser/tabs/tab_model_observer.h" -#import "ios/chrome/browser/u2f/u2f_controller.h" +#import "ios/chrome/browser/u2f/u2f_tab_helper.h" #import "ios/chrome/browser/ui/main/test/stub_browser_interface_provider.h" #import "ios/chrome/browser/web/tab_id_tab_helper.h" #import "ios/chrome/browser/web_state_list/fake_web_state_list_delegate.h" @@ -50,14 +50,27 @@ #error "This file requires ARC support." #endif -#pragma mark - Tab Mock +// Substitutes U2FTabHelper for testing. +class FakeU2FTabHelper : public U2FTabHelper { + public: + static void CreateForWebState(web::WebState* web_state) { + web_state->SetUserData(U2FTabHelper::UserDataKey(), + base::WrapUnique(new FakeU2FTabHelper(web_state))); + } + + void EvaluateU2FResult(const GURL& url) override { url_ = url; } + + const GURL& url() const { return url_; } + + private: + FakeU2FTabHelper(web::WebState* web_state) : U2FTabHelper(web_state) {} + GURL url_; + DISALLOW_COPY_AND_ASSIGN(FakeU2FTabHelper); +}; // Tab mock for using in UserActivity tests. @interface UserActivityHandlerTabMock : NSObject -@property(nonatomic, readonly) GURL url; -@property(nonatomic, readonly) NSString* tabId; - - (instancetype)initWithWebState:(web::WebState*)webState NS_DESIGNATED_INITIALIZER; @@ -69,8 +82,6 @@ web::WebState* _webState; } -@synthesize url = _url; - - (instancetype)initWithWebState:(web::WebState*)webState { if ((self = [super init])) { DCHECK(webState); @@ -79,12 +90,11 @@ return self; } -- (void)evaluateU2FResultFromURL:(const GURL&)url { - _url = url; +- (FakeU2FTabHelper*)U2FTabHelper { + return static_cast<FakeU2FTabHelper*>(U2FTabHelper::FromWebState(_webState)); } - (NSString*)tabId { - DCHECK(_webState); return TabIdTabHelper::FromWebState(_webState)->tab_id(); } @@ -112,6 +122,7 @@ - (UserActivityHandlerTabMock*)addMockTab { auto testWebState = std::make_unique<web::TestWebState>(); TabIdTabHelper::CreateForWebState(testWebState.get()); + FakeU2FTabHelper::CreateForWebState(testWebState.get()); UserActivityHandlerTabMock* tab = [[UserActivityHandlerTabMock alloc] initWithWebState:testWebState.get()]; @@ -617,7 +628,7 @@ // Tests. EXPECT_OCMOCK_VERIFY(startupInformationMock); - EXPECT_EQ(gurl, tabMock.url); + EXPECT_EQ(gurl, [tabMock U2FTabHelper] -> url()); EXPECT_TRUE(tabOpener.url.is_empty()); EXPECT_TRUE(tabOpener.virtualURL.is_empty()); }
diff --git a/ios/chrome/browser/about_flags.mm b/ios/chrome/browser/about_flags.mm index f86c009..27ce382 100644 --- a/ios/chrome/browser/about_flags.mm +++ b/ios/chrome/browser/about_flags.mm
@@ -390,10 +390,6 @@ {"app-launcher-refresh", flag_descriptions::kAppLauncherRefreshName, flag_descriptions::kAppLauncherRefreshDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kAppLauncherRefresh)}, - {"sync-standalone-transport", - flag_descriptions::kSyncStandaloneTransportName, - flag_descriptions::kSyncStandaloneTransportDescription, flags_ui::kOsIos, - FEATURE_VALUE_TYPE(switches::kSyncStandaloneTransport)}, {"sync-support-secondary-account", flag_descriptions::kSyncSupportSecondaryAccountName, flag_descriptions::kSyncSupportSecondaryAccountDescription,
diff --git a/ios/chrome/browser/app_launcher/BUILD.gn b/ios/chrome/browser/app_launcher/BUILD.gn index 96c7b5fe..21d636b 100644 --- a/ios/chrome/browser/app_launcher/BUILD.gn +++ b/ios/chrome/browser/app_launcher/BUILD.gn
@@ -22,6 +22,7 @@ "//ios/chrome/browser", "//ios/chrome/browser/reading_list", "//ios/chrome/browser/tabs", + "//ios/chrome/browser/u2f", "//ios/web/public", "//url", ] @@ -56,6 +57,7 @@ "//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/reading_list", "//ios/chrome/browser/tabs", + "//ios/chrome/browser/u2f", "//ios/chrome/browser/web:tab_id_tab_helper", "//ios/chrome/browser/web:web_internal", "//ios/web/public/test/fakes",
diff --git a/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm b/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm index b9a384df..21a5fbb 100644 --- a/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm +++ b/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm
@@ -17,6 +17,7 @@ #include "ios/chrome/browser/reading_list/reading_list_model_factory.h" #import "ios/chrome/browser/tabs/legacy_tab_helper.h" #import "ios/chrome/browser/tabs/tab.h" +#import "ios/chrome/browser/u2f/u2f_tab_helper.h" #import "ios/web/public/navigation_item.h" #import "ios/web/public/navigation_manager.h" #import "ios/web/public/url_scheme_util.h" @@ -191,7 +192,6 @@ if (!IsValidAppUrl(request_url)) return false; - Tab* tab = LegacyTabHelper::GetTabForWebState(web_state_); // If this is a Universal 2nd Factor (U2F) call, the origin needs to be // checked to make sure it's secure and then update the |request_url| with @@ -201,7 +201,8 @@ ->GetLastCommittedItem() ->GetURL() .GetOrigin(); - request_url = [tab XCallbackFromRequestURL:request_url originURL:origin]; + U2FTabHelper* u2f_helper = U2FTabHelper::FromWebState(web_state_); + request_url = u2f_helper->GetXCallbackUrl(request_url, origin); // If the URL was rejected by the U2F handler, |request_url| will be empty. if (!request_url.is_valid()) return false; @@ -215,6 +216,8 @@ bool is_link_transition = ui::PageTransitionTypeIncludingQualifiersIs( request_info.transition_type, ui::PAGE_TRANSITION_LINK); + Tab* tab = LegacyTabHelper::GetTabForWebState(web_state_); + if (base::FeatureList::IsEnabled(kAppLauncherRefresh)) { if (!is_link_transition && original_pending_url.is_valid()) { // At this stage the navigation will be canceled in all cases. If this
diff --git a/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm b/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm index e71d928..27e66f6d 100644 --- a/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm +++ b/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm
@@ -20,6 +20,7 @@ #import "ios/chrome/browser/chrome_url_util.h" #include "ios/chrome/browser/reading_list/reading_list_model_factory.h" #import "ios/chrome/browser/tabs/legacy_tab_helper.h" +#import "ios/chrome/browser/u2f/u2f_tab_helper.h" #import "ios/chrome/browser/web/tab_id_tab_helper.h" #import "ios/web/public/test/fakes/test_navigation_manager.h" #import "ios/web/public/test/fakes/test_web_state.h" @@ -112,6 +113,7 @@ delegate_([[FakeAppLauncherTabHelperDelegate alloc] init]) { AppLauncherTabHelper::CreateForWebState(&web_state_, abuse_detector_, delegate_); + U2FTabHelper::CreateForWebState(&web_state_); // Allow is the default policy for this test. abuse_detector_.policy = ExternalAppLaunchPolicyAllow; auto navigation_manager = std::make_unique<FakeNavigationManager>();
diff --git a/ios/chrome/browser/autofill/autofill_controller_unittest.mm b/ios/chrome/browser/autofill/autofill_controller_unittest.mm index d80bc62..05d6555 100644 --- a/ios/chrome/browser/autofill/autofill_controller_unittest.mm +++ b/ios/chrome/browser/autofill/autofill_controller_unittest.mm
@@ -195,7 +195,7 @@ void SetUp() override; void TearDown() override; - void SetUpForSuggestions(NSString* data); + void SetUpForSuggestions(NSString* data, size_t expected_number_of_forms); // Adds key value data to the Personal Data Manager and loads test page. void SetUpKeyValueData(); @@ -207,7 +207,13 @@ // Blocks until |expected_size| forms have been fecthed. bool WaitForFormFetched(AutofillManager* manager, - size_t expected_size) WARN_UNUSED_RESULT; + size_t expected_number_of_forms) WARN_UNUSED_RESULT; + + // Loads the page and wait until the initial form processing has been done. + // This processing must find |expected_size| forms. + bool LoadHtmlAndWaitForFormFetched(NSString* html, + size_t expected_number_of_forms) + WARN_UNUSED_RESULT; // Fails if the specified metric was not registered the given number of times. void ExpectMetric(const std::string& histogram_name, int sum); @@ -303,14 +309,26 @@ }); } -bool AutofillControllerTest::WaitForFormFetched(AutofillManager* manager, - size_t expected_size) { +bool AutofillControllerTest::WaitForFormFetched( + AutofillManager* manager, + size_t expected_number_of_forms) { return base::test::ios::WaitUntilConditionOrTimeout( base::test::ios::kWaitForPageLoadTimeout, ^bool { - return manager->form_structures().size() == expected_size; + return manager->form_structures().size() == expected_number_of_forms; }); } +bool AutofillControllerTest::LoadHtmlAndWaitForFormFetched( + NSString* html, + size_t expected_number_of_forms) { + LoadHtml(html); + web::WebFrame* main_frame = web::GetMainWebFrame(web_state()); + AutofillManager* autofill_manager = + AutofillDriverIOS::FromWebStateAndWebFrame(web_state(), main_frame) + ->autofill_manager(); + return WaitForFormFetched(autofill_manager, expected_number_of_forms); +} + void AutofillControllerTest::ExpectMetric(const std::string& histogram_name, int sum) { histogram_tester_->ExpectBucketCount(histogram_name, sum, 1); @@ -324,12 +342,11 @@ // Checks that viewing an HTML page containing a form results in the form being // registered as a FormStructure by the AutofillManager. TEST_F(AutofillControllerTest, ReadForm) { - LoadHtml(kProfileFormHtml); + ASSERT_TRUE(LoadHtmlAndWaitForFormFetched(kProfileFormHtml, 1)); web::WebFrame* main_frame = web::GetMainWebFrame(web_state()); AutofillManager* autofill_manager = AutofillDriverIOS::FromWebStateAndWebFrame(web_state(), main_frame) ->autofill_manager(); - EXPECT_TRUE(WaitForFormFetched(autofill_manager, 1)); const auto& forms = autofill_manager->form_structures(); const auto& form = *(forms.begin()->second); CheckField(form, NAME_FULL, "name_1"); @@ -345,12 +362,11 @@ // the form being registered as a FormStructure by the AutofillManager, and the // name is correctly set. TEST_F(AutofillControllerTest, ReadFormName) { - LoadHtml(kMinimalFormWithNameHtml); + ASSERT_TRUE(LoadHtmlAndWaitForFormFetched(kMinimalFormWithNameHtml, 1)); web::WebFrame* main_frame = web::GetMainWebFrame(web_state()); AutofillManager* autofill_manager = AutofillDriverIOS::FromWebStateAndWebFrame(web_state(), main_frame) ->autofill_manager(); - EXPECT_TRUE(WaitForFormFetched(autofill_manager, 1)); const auto& forms = autofill_manager->form_structures(); const auto& form = *(forms.begin()->second); EXPECT_EQ(base::UTF8ToUTF16("form1"), form.ToFormData().name); @@ -365,7 +381,7 @@ ios::ChromeBrowserState::FromBrowserState(GetBrowserState())); // Check there are no registered profiles already. EXPECT_EQ(0U, personal_data_manager->GetProfiles().size()); - LoadHtml(kProfileFormHtml); + ASSERT_TRUE(LoadHtmlAndWaitForFormFetched(kProfileFormHtml, 1)); ExecuteJavaScript(@"document.forms[0].name.value = 'Homer Simpson'"); ExecuteJavaScript(@"document.forms[0].address.value = '123 Main Street'"); ExecuteJavaScript(@"document.forms[0].city.value = 'Springfield'"); @@ -392,7 +408,9 @@ profile.GetInfo(AutofillType(ADDRESS_HOME_ZIP), "en-US")); } -void AutofillControllerTest::SetUpForSuggestions(NSString* data) { +void AutofillControllerTest::SetUpForSuggestions( + NSString* data, + size_t expected_number_of_forms) { PersonalDataManager* personal_data_manager = PersonalDataManagerFactory::GetForBrowserState( ios::ChromeBrowserState::FromBrowserState(GetBrowserState())); @@ -406,7 +424,7 @@ personal_data_manager->SaveImportedProfile(profile); EXPECT_EQ(1U, personal_data_manager->GetProfiles().size()); - LoadHtml(data); + ASSERT_TRUE(LoadHtmlAndWaitForFormFetched(data, expected_number_of_forms)); WaitForBackgroundTasks(); } @@ -414,7 +432,7 @@ // suggestions being sent to the AutofillAgent, once data has been loaded into a // test data manager. TEST_F(AutofillControllerTest, ProfileSuggestions) { - SetUpForSuggestions(kProfileFormHtml); + SetUpForSuggestions(kProfileFormHtml, 1); ForceViewRendering(web_state()->GetView()); ExecuteJavaScript(@"document.forms[0].name.focus()"); WaitForSuggestionRetrieval(/*wait_for_trigger=*/YES); @@ -429,7 +447,8 @@ // there is another anonymous form on the page. TEST_F(AutofillControllerTest, ProfileSuggestionsTwoAnonymousForms) { SetUpForSuggestions( - [NSString stringWithFormat:@"%@%@", kProfileFormHtml, kProfileFormHtml]); + [NSString stringWithFormat:@"%@%@", kProfileFormHtml, kProfileFormHtml], + 2); ForceViewRendering(web_state()->GetView()); ExecuteJavaScript(@"document.forms[0].name.focus()"); WaitForSuggestionRetrieval(/*wait_for_trigger=*/YES); @@ -444,7 +463,7 @@ // in suggestions being sent to the AutofillAgent, once data has been loaded // into a test data manager. TEST_F(AutofillControllerTest, ProfileSuggestionsFromSelectField) { - SetUpForSuggestions(kProfileFormHtml); + SetUpForSuggestions(kProfileFormHtml, 1); ForceViewRendering(web_state()->GetView()); ExecuteJavaScript(@"document.forms[0].state.focus()"); WaitForSuggestionRetrieval(/*wait_for_trigger=*/YES); @@ -483,9 +502,7 @@ profile2.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("94043")); personal_data_manager->SaveImportedProfile(profile2); EXPECT_EQ(2U, personal_data_manager->GetProfiles().size()); - LoadHtml(kProfileFormHtml); - base::TaskScheduler::GetInstance()->FlushForTesting(); - WaitForBackgroundTasks(); + EXPECT_TRUE(LoadHtmlAndWaitForFormFetched(kProfileFormHtml, 1)); ForceViewRendering(web_state()->GetView()); ExecuteJavaScript(@"document.forms[0].name.focus()"); WaitForSuggestionRetrieval(/*wait_for_trigger=*/YES); @@ -498,7 +515,7 @@ // with scripts (simulating user form submission) results in data being // successfully registered. TEST_F(AutofillControllerTest, KeyValueImport) { - LoadHtml(kKeyValueFormHtml); + ASSERT_TRUE(LoadHtmlAndWaitForFormFetched(kKeyValueFormHtml, 1)); ExecuteJavaScript(@"document.forms[0].greeting.value = 'Hello'"); scoped_refptr<AutofillWebDataService> web_data_service = ios::WebDataServiceFactory::GetAutofillWebDataForBrowserState( @@ -540,7 +557,7 @@ web_data_service->AddFormFields(values); // Load test page. - LoadHtml(kKeyValueFormHtml); + ASSERT_TRUE(LoadHtmlAndWaitForFormFetched(kKeyValueFormHtml, 1)); WaitForBackgroundTasks(); } @@ -631,7 +648,7 @@ // Check there are no registered profiles already. EXPECT_EQ(0U, personal_data_manager->GetCreditCards().size()); - LoadHtml(kCreditCardFormHtml); + ASSERT_TRUE(LoadHtmlAndWaitForFormFetched(kCreditCardFormHtml, 1)); ExecuteJavaScript(@"document.forms[0].name.value = 'Superman'"); ExecuteJavaScript(@"document.forms[0].CCNo.value = '4000-4444-4444-4444'"); ExecuteJavaScript(@"document.forms[0].CCExpiresMonth.value = '11'");
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/ios_chrome_flag_descriptions.cc index 434cc98..d9d3d6ea 100644 --- a/ios/chrome/browser/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/ios_chrome_flag_descriptions.cc
@@ -121,12 +121,6 @@ const char kSyncSandboxDescription[] = "Connects to the testing server for Chrome Sync."; -const char kSyncStandaloneTransportName[] = "Allow Sync standalone transport"; -const char kSyncStandaloneTransportDescription[] = - "If enabled, allows Chrome Sync to start in standalone transport mode. In " - "this mode, the Sync machinery can start without user opt-in, but only a " - "subset of data types are supported."; - const char kSyncSupportSecondaryAccountName[] = "Support secondary accounts for Sync standalone transport"; const char kSyncSupportSecondaryAccountDescription[] =
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.h b/ios/chrome/browser/ios_chrome_flag_descriptions.h index 64319c5..00a2007c 100644 --- a/ios/chrome/browser/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/ios_chrome_flag_descriptions.h
@@ -93,11 +93,6 @@ extern const char kSyncSandboxName[]; extern const char kSyncSandboxDescription[]; -// Title and description for the flag to control if Chrome Sync can start up in -// standalone transport mode. -extern const char kSyncStandaloneTransportName[]; -extern const char kSyncStandaloneTransportDescription[]; - // Title and description for the flag to control if Chrome Sync (in standalone // transport mode) supports non-primary accounts. extern const char kSyncSupportSecondaryAccountName[];
diff --git a/ios/chrome/browser/metrics/ukm_egtest.mm b/ios/chrome/browser/metrics/ukm_egtest.mm index 9a7bbd291..a29d9a3 100644 --- a/ios/chrome/browser/metrics/ukm_egtest.mm +++ b/ios/chrome/browser/metrics/ukm_egtest.mm
@@ -402,9 +402,9 @@ // Open sync encryption menu. [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"kSettingsSyncId")] performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)]; - [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel( - l10n_util::GetNSStringWithFixup( - IDS_IOS_SYNC_ENCRYPTION_TITLE))] + [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId( + + IDS_IOS_SYNC_ENCRYPTION_TITLE)] performAction:grey_tap()]; // Select passphrase encryption. [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId(
diff --git a/ios/chrome/browser/payments/payment_request_util.h b/ios/chrome/browser/payments/payment_request_util.h index c2e8377..a91e732 100644 --- a/ios/chrome/browser/payments/payment_request_util.h +++ b/ios/chrome/browser/payments/payment_request_util.h
@@ -11,16 +11,13 @@ #include <vector> #include "base/strings/string16.h" +#include "base/values.h" #include "components/payments/core/payment_options_provider.h" namespace autofill { class AutofillProfile; } // namespace autofill -namespace base { -class DictionaryValue; -} // namespace base - namespace payments { class PaymentInstrument; class PaymentRequest; @@ -29,9 +26,9 @@ namespace payment_request_util { -// Returns a base::DictionaryValue populated with the properties of |response|. -std::unique_ptr<base::DictionaryValue> PaymentResponseToDictionaryValue( - const payments::PaymentResponse& response); +// Returns a base::Value populated with the properties of |response|. The +// returned value is always a dictionary. +base::Value PaymentResponseToValue(const payments::PaymentResponse& response); // Helper function to create a name label from an autofill profile. Returns nil // if the resulting label is empty.
diff --git a/ios/chrome/browser/payments/payment_request_util.mm b/ios/chrome/browser/payments/payment_request_util.mm index 4a00ee9..aecf6768 100644 --- a/ios/chrome/browser/payments/payment_request_util.mm +++ b/ios/chrome/browser/payments/payment_request_util.mm
@@ -46,28 +46,28 @@ } // namespace -std::unique_ptr<base::DictionaryValue> PaymentResponseToDictionaryValue( - const payments::PaymentResponse& response) { - auto result = std::make_unique<base::DictionaryValue>(); - result->SetString(kPaymentResponseId, response.payment_request_id); - result->SetString(kPaymentResponseMethodName, response.method_name); +base::Value PaymentResponseToValue(const payments::PaymentResponse& response) { + base::Value result(base::Value::Type::DICTIONARY); + result.SetKey(kPaymentResponseId, base::Value(response.payment_request_id)); + result.SetKey(kPaymentResponseMethodName, base::Value(response.method_name)); // |details| is a json-serialized string. Parse it to a base::Value so that // when |result| is converted to a JSON string, the "details" property won't // get json-escaped. - std::unique_ptr<base::Value> details_value = - base::JSONReader::ReadDeprecated(response.details); - result->Set(kPaymentResponseDetails, details_value - ? std::move(details_value) - : std::make_unique<base::Value>()); - result->Set(kPaymentResponseShippingAddress, - response.shipping_address - ? payments::PaymentAddressToDictionaryValue( - *response.shipping_address) - : std::make_unique<base::Value>()); - result->SetString(kPaymentResponseShippingOption, response.shipping_option); - result->SetString(kPaymentResponsePayerName, response.payer_name); - result->SetString(kPaymentResponsePayerEmail, response.payer_email); - result->SetString(kPaymentResponsePayerPhone, response.payer_phone); + base::Optional<base::Value> details_value = + base::JSONReader::Read(response.details); + result.SetKey(kPaymentResponseDetails, + std::move(details_value).value_or(base::Value())); + result.SetKey(kPaymentResponseShippingAddress, + response.shipping_address + ? base::Value::FromUniquePtrValue( + payments::PaymentAddressToDictionaryValue( + *response.shipping_address)) + : base::Value()); + result.SetKey(kPaymentResponseShippingOption, + base::Value(response.shipping_option)); + result.SetKey(kPaymentResponsePayerName, base::Value(response.payer_name)); + result.SetKey(kPaymentResponsePayerEmail, base::Value(response.payer_email)); + result.SetKey(kPaymentResponsePayerPhone, base::Value(response.payer_phone)); return result; }
diff --git a/ios/chrome/browser/payments/payment_request_util_unittest.mm b/ios/chrome/browser/payments/payment_request_util_unittest.mm index 72dfeea3..5d77fd3 100644 --- a/ios/chrome/browser/payments/payment_request_util_unittest.mm +++ b/ios/chrome/browser/payments/payment_request_util_unittest.mm
@@ -21,65 +21,70 @@ // Tests that serializing a default PaymentResponse yields the expected result. TEST_F(PaymentRequestUtilTest, PaymentResponseToDictionaryValue_EmptyResponseDictionary) { - base::DictionaryValue expected_value; + base::Value expected_value(base::Value::Type::DICTIONARY); - expected_value.SetString("requestId", ""); - expected_value.SetString("methodName", ""); - expected_value.Set("details", std::make_unique<base::Value>()); - expected_value.Set("shippingAddress", std::make_unique<base::Value>()); - expected_value.SetString("shippingOption", ""); - expected_value.SetString("payerName", ""); - expected_value.SetString("payerEmail", ""); - expected_value.SetString("payerPhone", ""); + expected_value.SetKey("requestId", base::Value(base::Value::Type::STRING)); + expected_value.SetKey("methodName", base::Value(base::Value::Type::STRING)); + expected_value.SetKey("details", base::Value()); + expected_value.SetKey("shippingAddress", base::Value()); + expected_value.SetKey("shippingOption", + base::Value(base::Value::Type::STRING)); + expected_value.SetKey("payerName", base::Value(base::Value::Type::STRING)); + expected_value.SetKey("payerEmail", base::Value(base::Value::Type::STRING)); + expected_value.SetKey("payerPhone", base::Value(base::Value::Type::STRING)); payments::PaymentResponse payment_response; - EXPECT_TRUE(expected_value.Equals( - PaymentResponseToDictionaryValue(payment_response).get())); + EXPECT_EQ(expected_value, PaymentResponseToValue(payment_response)); } // Tests that serializing a populated PaymentResponse yields the expected // result. TEST_F(PaymentRequestUtilTest, PaymentResponseToDictionaryValue_PopulatedResponseDictionary) { - base::DictionaryValue expected_value; + base::Value expected_value(base::Value::Type::DICTIONARY); - auto details = std::make_unique<base::DictionaryValue>(); - details->SetString("cardNumber", "1111-1111-1111-1111"); - details->SetString("cardholderName", "Jon Doe"); - details->SetString("expiryMonth", "02"); - details->SetString("expiryYear", "2090"); - details->SetString("cardSecurityCode", "111"); - auto billing_address = std::make_unique<base::DictionaryValue>(); - billing_address->SetString("country", ""); - billing_address->Set("addressLine", std::make_unique<base::ListValue>()); - billing_address->SetString("region", ""); - billing_address->SetString("dependentLocality", ""); - billing_address->SetString("city", ""); - billing_address->SetString("postalCode", "90210"); - billing_address->SetString("sortingCode", ""); - billing_address->SetString("organization", ""); - billing_address->SetString("recipient", ""); - billing_address->SetString("phone", ""); - details->Set("billingAddress", std::move(billing_address)); - expected_value.Set("details", std::move(details)); - expected_value.SetString("requestId", "12345"); - expected_value.SetString("methodName", "American Express"); - auto shipping_address = std::make_unique<base::DictionaryValue>(); - shipping_address->SetString("country", ""); - shipping_address->Set("addressLine", std::make_unique<base::ListValue>()); - shipping_address->SetString("region", ""); - shipping_address->SetString("dependentLocality", ""); - shipping_address->SetString("city", ""); - shipping_address->SetString("postalCode", "94115"); - shipping_address->SetString("sortingCode", ""); - shipping_address->SetString("organization", ""); - shipping_address->SetString("recipient", ""); - shipping_address->SetString("phone", ""); - expected_value.Set("shippingAddress", std::move(shipping_address)); - expected_value.SetString("shippingOption", "666"); - expected_value.SetString("payerName", "Jane Doe"); - expected_value.SetString("payerEmail", "jane@example.com"); - expected_value.SetString("payerPhone", "1234-567-890"); + base::Value details(base::Value::Type::DICTIONARY); + details.SetKey("cardNumber", base::Value("1111-1111-1111-1111")); + details.SetKey("cardholderName", base::Value("Jon Doe")); + details.SetKey("expiryMonth", base::Value("02")); + details.SetKey("expiryYear", base::Value("2090")); + details.SetKey("cardSecurityCode", base::Value("111")); + base::Value billing_address(base::Value::Type::DICTIONARY); + billing_address.SetKey("country", base::Value(base::Value::Type::STRING)); + billing_address.SetKey("addressLine", base::Value(base::Value::Type::LIST)); + billing_address.SetKey("region", base::Value(base::Value::Type::STRING)); + billing_address.SetKey("dependentLocality", + base::Value(base::Value::Type::STRING)); + billing_address.SetKey("city", base::Value(base::Value::Type::STRING)); + billing_address.SetKey("postalCode", base::Value("90210")); + billing_address.SetKey("sortingCode", base::Value(base::Value::Type::STRING)); + billing_address.SetKey("organization", + base::Value(base::Value::Type::STRING)); + billing_address.SetKey("recipient", base::Value(base::Value::Type::STRING)); + billing_address.SetKey("phone", base::Value(base::Value::Type::STRING)); + details.SetKey("billingAddress", std::move(billing_address)); + expected_value.SetKey("details", std::move(details)); + expected_value.SetKey("requestId", base::Value("12345")); + expected_value.SetKey("methodName", base::Value("American Express")); + base::Value shipping_address(base::Value::Type::DICTIONARY); + shipping_address.SetKey("country", base::Value(base::Value::Type::STRING)); + shipping_address.SetKey("addressLine", base::Value(base::Value::Type::LIST)); + shipping_address.SetKey("region", base::Value(base::Value::Type::STRING)); + shipping_address.SetKey("dependentLocality", + base::Value(base::Value::Type::STRING)); + shipping_address.SetKey("city", base::Value(base::Value::Type::STRING)); + shipping_address.SetKey("postalCode", base::Value("94115")); + shipping_address.SetKey("sortingCode", + base::Value(base::Value::Type::STRING)); + shipping_address.SetKey("organization", + base::Value(base::Value::Type::STRING)); + shipping_address.SetKey("recipient", base::Value(base::Value::Type::STRING)); + shipping_address.SetKey("phone", base::Value(base::Value::Type::STRING)); + expected_value.SetKey("shippingAddress", std::move(shipping_address)); + expected_value.SetKey("shippingOption", base::Value("666")); + expected_value.SetKey("payerName", base::Value("Jane Doe")); + expected_value.SetKey("payerEmail", base::Value("jane@example.com")); + expected_value.SetKey("payerPhone", base::Value("1234-567-890")); payments::PaymentResponse payment_response; payment_response.payment_request_id = "12345"; @@ -106,8 +111,7 @@ payment_response.payer_name = base::ASCIIToUTF16("Jane Doe"); payment_response.payer_email = base::ASCIIToUTF16("jane@example.com"); payment_response.payer_phone = base::ASCIIToUTF16("1234-567-890"); - EXPECT_TRUE(expected_value.Equals( - PaymentResponseToDictionaryValue(payment_response).get())); + EXPECT_EQ(expected_value, PaymentResponseToValue(payment_response)); } } // namespace payment_request_util
diff --git a/ios/chrome/browser/signin/identity_service_creator.cc b/ios/chrome/browser/signin/identity_service_creator.cc index 47e228f..a67f597 100644 --- a/ios/chrome/browser/signin/identity_service_creator.cc +++ b/ios/chrome/browser/signin/identity_service_creator.cc
@@ -9,8 +9,6 @@ #include "components/signin/core/browser/signin_manager.h" #include "ios/chrome/browser/signin/account_tracker_service_factory.h" #include "ios/chrome/browser/signin/identity_manager_factory.h" -#include "ios/chrome/browser/signin/profile_oauth2_token_service_factory.h" -#include "ios/chrome/browser/signin/signin_manager_factory.h" #include "services/identity/identity_service.h" std::unique_ptr<service_manager::Service> CreateIdentityService( @@ -20,8 +18,6 @@ IdentityManagerFactory::GetForBrowserState(browser_state); AccountTrackerService* account_tracker = ios::AccountTrackerServiceFactory::GetForBrowserState(browser_state); - ProfileOAuth2TokenService* token_service = - ProfileOAuth2TokenServiceFactory::GetForBrowserState(browser_state); return std::make_unique<identity::IdentityService>( - identity_manager, account_tracker, token_service, std::move(request)); + identity_manager, account_tracker, std::move(request)); }
diff --git a/ios/chrome/browser/tabs/tab.h b/ios/chrome/browser/tabs/tab.h index 14e4043..7162082 100644 --- a/ios/chrome/browser/tabs/tab.h +++ b/ios/chrome/browser/tabs/tab.h
@@ -103,15 +103,6 @@ // Called before capturing a snapshot for Tab. - (void)willUpdateSnapshot; -// Evaluates U2F result. -- (void)evaluateU2FResultFromURL:(const GURL&)url; - -// Generates a GURL compliant with the x-callback-url specs for FIDO Universal -// 2nd Factory (U2F) requests. Returns empty GURL if origin is not secure. -// See http://x-callback-url.com/specifications/ for specifications. -- (GURL)XCallbackFromRequestURL:(const GURL&)requestURL - originURL:(const GURL&)originURL; - // Sends a notification to indicate that |url| is going to start loading. - (void)notifyTabOfUrlMayStartLoading:(const GURL&)url;
diff --git a/ios/chrome/browser/tabs/tab.mm b/ios/chrome/browser/tabs/tab.mm index 561a56c5..727fe254 100644 --- a/ios/chrome/browser/tabs/tab.mm +++ b/ios/chrome/browser/tabs/tab.mm
@@ -60,7 +60,6 @@ #import "ios/chrome/browser/tabs/tab_helper_util.h" #import "ios/chrome/browser/tabs/tab_private.h" #include "ios/chrome/browser/translate/chrome_ios_translate_client.h" -#import "ios/chrome/browser/u2f/u2f_controller.h" #import "ios/chrome/browser/ui/commands/open_new_tab_command.h" #import "ios/chrome/browser/ui/commands/show_signin_command.h" #import "ios/chrome/browser/ui/open_in_controller.h" @@ -131,9 +130,6 @@ // Allows Tab to conform CRWWebStateDelegate protocol. std::unique_ptr<web::WebStateObserverBridge> _webStateObserver; - // Universal Second Factor (U2F) call controller. - U2FController* _secondFactorController; - } // Returns the OpenInController for this tab. @@ -245,27 +241,6 @@ } } -#pragma mark - Public API (relating to U2F) - -- (void)evaluateU2FResultFromURL:(const GURL&)URL { - DCHECK(_secondFactorController); - [_secondFactorController evaluateU2FResultFromU2FURL:URL - webState:self.webState]; -} - -- (GURL)XCallbackFromRequestURL:(const GURL&)requestURL - originURL:(const GURL&)originURL { - // Create U2FController object lazily. - if (!_secondFactorController) - _secondFactorController = [[U2FController alloc] init]; - return [_secondFactorController - XCallbackFromRequestURL:requestURL - originURL:originURL - tabURL:self.webState->GetLastCommittedURL() - tabID:TabIdTabHelper::FromWebState(self.webState) - ->tab_id()]; -} - #pragma mark - CRWWebStateObserver protocol - (void)webState:(web::WebState*)webState
diff --git a/ios/chrome/browser/tabs/tab_helper_util.mm b/ios/chrome/browser/tabs/tab_helper_util.mm index 97a2fc6..db87f14 100644 --- a/ios/chrome/browser/tabs/tab_helper_util.mm +++ b/ios/chrome/browser/tabs/tab_helper_util.mm
@@ -45,6 +45,7 @@ #import "ios/chrome/browser/tabs/legacy_tab_helper.h" #import "ios/chrome/browser/tabs/tab.h" #import "ios/chrome/browser/translate/chrome_ios_translate_client.h" +#import "ios/chrome/browser/u2f/u2f_tab_helper.h" #import "ios/chrome/browser/ui/infobars/infobar_feature.h" #import "ios/chrome/browser/ui/ui_feature_flags.h" #import "ios/chrome/browser/voice/voice_search_navigations_tab_helper.h" @@ -85,6 +86,7 @@ IOSSecurityStateTabHelper::CreateForWebState(web_state); BlockedPopupTabHelper::CreateForWebState(web_state); FindTabHelper::CreateForWebState(web_state); + U2FTabHelper::CreateForWebState(web_state); StoreKitTabHelper::CreateForWebState(web_state); JavaScriptConsoleTabHelper::CreateForWebState(tab.webState); ITunesUrlsHandlerTabHelper::CreateForWebState(web_state);
diff --git a/ios/chrome/browser/translate/BUILD.gn b/ios/chrome/browser/translate/BUILD.gn index 65dfe36..0de815d 100644 --- a/ios/chrome/browser/translate/BUILD.gn +++ b/ios/chrome/browser/translate/BUILD.gn
@@ -95,12 +95,7 @@ ] } -# Those tests do not use external URLs but fail if the network is unavailable -# as they explicitly check whether the network is up or not; it is not possible -# to safely instantiate a net::NetworkChangeNotifier::DisableForTest to disable -# those checks as this in not thread-safe. See http://crbug.com/709131 for more -# details. -source_set("external_url_eg_tests") { +source_set("eg_tests") { configs += [ "//build/config/compiler:enable_arc" ] testonly = true sources = [
diff --git a/ios/chrome/browser/translate/translate_egtest.mm b/ios/chrome/browser/translate/translate_egtest.mm index 78e5d12..f4724555 100644 --- a/ios/chrome/browser/translate/translate_egtest.mm +++ b/ios/chrome/browser/translate/translate_egtest.mm
@@ -36,6 +36,7 @@ #include "ios/web/public/test/http_server/data_response_provider.h" #import "ios/web/public/test/http_server/http_server.h" #include "ios/web/public/test/http_server/http_server_util.h" +#include "net/base/network_change_notifier.h" #include "net/base/url_util.h" #include "ui/base/l10n/l10n_util.h" @@ -237,6 +238,28 @@ base::StringPrintf("<html><body>%s</body></html>", kLanguagePathText); } +// Simulates a given network connection type for tests. +// TODO(crbug.com/938598): Refactor this and similar net::NetworkChangeNotifier +// subclasses for testing into a separate file. +class FakeNetworkChangeNotifier : public net::NetworkChangeNotifier { + public: + FakeNetworkChangeNotifier( + net::NetworkChangeNotifier::ConnectionType connection_type_to_return) + : connection_type_to_return_(connection_type_to_return) {} + + private: + ConnectionType GetCurrentConnectionType() const override { + return connection_type_to_return_; + } + + // The currently simulated network connection type. If this is set to + // CONNECTION_NONE, then NetworkChangeNotifier::IsOffline will return true. + net::NetworkChangeNotifier::ConnectionType connection_type_to_return_ = + net::NetworkChangeNotifier::CONNECTION_UNKNOWN; + + DISALLOW_COPY_AND_ASSIGN(FakeNetworkChangeNotifier); +}; + } // namespace using chrome_test_util::TapWebViewElementWithId; @@ -302,6 +325,9 @@ @interface TranslateTestCase : ChromeTestCase { std::unique_ptr<translate::LanguageDetectionDetails> _language_detection_details; + std::unique_ptr<net::NetworkChangeNotifier::DisableForTest> + network_change_notifier_disabler_; + std::unique_ptr<FakeNetworkChangeNotifier> network_change_notifier_; } @end @@ -316,6 +342,13 @@ std::make_unique<translate::LanguageDetectionDetails>(details); }); SetTestingLanguageDetectionCallback(copyDetailsCallback); + + // Disable the net::NetworkChangeNotifier singleton and replace it with a + // FakeNetworkChangeNotifier to simulate a WIFI network connection. + network_change_notifier_disabler_ = + std::make_unique<net::NetworkChangeNotifier::DisableForTest>(); + network_change_notifier_ = std::make_unique<FakeNetworkChangeNotifier>( + net::NetworkChangeNotifier::CONNECTION_WIFI); } - (void)tearDown {
diff --git a/ios/chrome/browser/u2f/BUILD.gn b/ios/chrome/browser/u2f/BUILD.gn index bfb6bab..7cebd98 100644 --- a/ios/chrome/browser/u2f/BUILD.gn +++ b/ios/chrome/browser/u2f/BUILD.gn
@@ -4,6 +4,23 @@ source_set("u2f") { sources = [ + "u2f_tab_helper.h", + "u2f_tab_helper.mm", + ] + deps = [ + ":u2f_internal", + "//base", + "//ios/chrome/browser/web:tab_id_tab_helper", + "//ios/web", + "//net", + "//url", + ] + + configs += [ "//build/config/compiler:enable_arc" ] +} + +source_set("u2f_internal") { + sources = [ "u2f_controller.h", "u2f_controller.mm", ] @@ -17,7 +34,6 @@ "//net", "//url", ] - configs += [ "//build/config/compiler:enable_arc" ] } @@ -25,13 +41,17 @@ testonly = true sources = [ "u2f_controller_unittest.mm", + "u2f_tab_helper_unittest.mm", ] deps = [ ":u2f", + ":u2f_internal", "//base", "//ios/chrome/browser", + "//ios/chrome/browser/web:tab_id_tab_helper", "//ios/web", "//ios/web/public/test/fakes", + "//net", "//testing/gmock", "//testing/gtest", "//url",
diff --git a/ios/chrome/browser/u2f/u2f_controller.h b/ios/chrome/browser/u2f/u2f_controller.h index fa1f6fb..d2357097 100644 --- a/ios/chrome/browser/u2f/u2f_controller.h +++ b/ios/chrome/browser/u2f/u2f_controller.h
@@ -14,14 +14,10 @@ } // namespace web // This class provides methods needed to handle FIDO U2F calls. +// U2FController shouldn't be used outside of this directory. Instead all users +// should use U2FTabHelper. @interface U2FController : NSObject -// Checks if the given URL is U2F callback. -+ (BOOL)isU2FURL:(const GURL&)URL; - -// Returns the tabID in the U2F callback. Returns nil if tabID not found. -+ (NSString*)tabIDFromResponseURL:(const GURL&)URL; - // Generates the x-callback GURL for making FIDO U2F requests. Returns empty // GURL if origin is not secure. - (GURL)XCallbackFromRequestURL:(const GURL&)requestURL
diff --git a/ios/chrome/browser/u2f/u2f_controller.mm b/ios/chrome/browser/u2f/u2f_controller.mm index e55fe043..ef3e9715d 100644 --- a/ios/chrome/browser/u2f/u2f_controller.mm +++ b/ios/chrome/browser/u2f/u2f_controller.mm
@@ -61,22 +61,6 @@ return self; } -+ (BOOL)isU2FURL:(const GURL&)URL { - std::string isU2F; - if (net::GetValueForKeyInQuery(URL, std::string(kIsU2FKey), &isU2F)) { - return isU2F == "1"; - } - return NO; -} - -+ (NSString*)tabIDFromResponseURL:(const GURL&)URL { - std::string tabID; - if (net::GetValueForKeyInQuery(URL, std::string(kTabIDKey), &tabID)) { - return base::SysUTF8ToNSString(tabID); - } - return nil; -} - - (GURL)XCallbackFromRequestURL:(const GURL&)requestURL originURL:(const GURL&)originURL tabURL:(const GURL&)tabURL
diff --git a/ios/chrome/browser/u2f/u2f_controller_unittest.mm b/ios/chrome/browser/u2f/u2f_controller_unittest.mm index 0442e9e..d561373 100644 --- a/ios/chrome/browser/u2f/u2f_controller_unittest.mm +++ b/ios/chrome/browser/u2f/u2f_controller_unittest.mm
@@ -64,32 +64,6 @@ U2FController* _U2FController; }; -TEST_F(U2FControllerTest, IsU2FURLTest) { - GURL U2FURL("chromium://u2f-callback?isU2F=1"); - EXPECT_TRUE([U2FController isU2FURL:U2FURL]); - - GURL wrongU2FURL("chromium://u2f-callback?isU2F=0"); - EXPECT_FALSE([U2FController isU2FURL:wrongU2FURL]); - - GURL nonU2FURL("chromium://u2f-callback"); - EXPECT_FALSE([U2FController isU2FURL:nonU2FURL]); - - GURL invalidURL; - EXPECT_FALSE([U2FController isU2FURL:invalidURL]); -} - -TEST_F(U2FControllerTest, TabIDFromResponseURLTest) { - NSString* tabID = @"B05B1860-18BA-43EA-B7DC-470D9F918FF5"; - GURL correctURL( - "chromium://" - "u2f-callback?tabID=B05B1860-18BA-43EA-B7DC-470D9F918FF5"); - EXPECT_TRUE( - [[U2FController tabIDFromResponseURL:correctURL] isEqualToString:tabID]); - - GURL wrongURL("chromium://u2fdemo.appspot.com"); - EXPECT_EQ(nil, [U2FController tabIDFromResponseURL:wrongURL]); -} - TEST_F(U2FControllerTest, XCallbackFromRequestURLWithCorrectFlowTest) { // Test when request is legal and properly formatted. GURL requestURL("u2f://accounts.google.com?data=abc&def%26ghi");
diff --git a/ios/chrome/browser/u2f/u2f_tab_helper.h b/ios/chrome/browser/u2f/u2f_tab_helper.h new file mode 100644 index 0000000..984cbd1 --- /dev/null +++ b/ios/chrome/browser/u2f/u2f_tab_helper.h
@@ -0,0 +1,53 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_U2F_U2F_TAB_HELPER_H_ +#define IOS_CHROME_BROWSER_U2F_U2F_TAB_HELPER_H_ + +#include "base/macros.h" +#import "ios/web/public/web_state/web_state_user_data.h" +#include "url/gurl.h" + +@class U2FController; + +// A tab helper that handles Universal 2nd Factory (U2F) requests. +class U2FTabHelper : public web::WebStateUserData<U2FTabHelper> { + public: + ~U2FTabHelper() override; + + // Checks if the given |url| is U2F call URL. + static bool IsU2FUrl(const GURL& url); + + // Returns the tabID in the U2F callback. Returns nil if tabID not found. + static NSString* GetTabIdFromU2FUrl(const GURL& u2f_url); + + // Evaluates U2F result. + virtual void EvaluateU2FResult(const GURL& url); + + // Generates a GURL compliant with the x-callback-url specs for FIDO Universal + // 2nd Factory (U2F) requests. Returns empty GURL if origin is not secure. + // See http://x-callback-url.com/specifications/ for specifications. + // This function is needed used in App launching to verify the |request_url| + // before launching the required authentication app. + GURL GetXCallbackUrl(const GURL& request_url, const GURL& origin_url); + + protected: + // Constructor for U2FTabHelper. + U2FTabHelper(web::WebState* web_state); + + private: + friend class web::WebStateUserData<U2FTabHelper>; + + // The WebState that this object is attached to. + web::WebState* web_state_ = nullptr; + + // Universal Second Factor (U2F) call controller. + U2FController* second_factor_controller_ = nil; + + WEB_STATE_USER_DATA_KEY_DECL(); + + DISALLOW_COPY_AND_ASSIGN(U2FTabHelper); +}; + +#endif // IOS_CHROME_BROWSER_U2F_U2F_TAB_HELPER_H_
diff --git a/ios/chrome/browser/u2f/u2f_tab_helper.mm b/ios/chrome/browser/u2f/u2f_tab_helper.mm new file mode 100644 index 0000000..2218c0e --- /dev/null +++ b/ios/chrome/browser/u2f/u2f_tab_helper.mm
@@ -0,0 +1,58 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/u2f/u2f_tab_helper.h" + +#import "base/strings/sys_string_conversions.h" +#import "ios/chrome/browser/u2f/u2f_controller.h" +#import "ios/chrome/browser/web/tab_id_tab_helper.h" +#import "ios/web/public/web_state/web_state.h" +#include "net/base/url_util.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +const char kIsU2FKey[] = "isU2F"; +const char kTabIDKey[] = "tabID"; +} // namespace + +U2FTabHelper::U2FTabHelper(web::WebState* web_state) : web_state_(web_state) {} + +U2FTabHelper::~U2FTabHelper() = default; + +bool U2FTabHelper::IsU2FUrl(const GURL& url) { + std::string is_u2f; + return net::GetValueForKeyInQuery(url, kIsU2FKey, &is_u2f) && is_u2f == "1"; +} + +NSString* U2FTabHelper::GetTabIdFromU2FUrl(const GURL& url) { + std::string tab_id; + if (net::GetValueForKeyInQuery(url, kTabIDKey, &tab_id)) { + return base::SysUTF8ToNSString(tab_id); + } + return nil; +} + +void U2FTabHelper::EvaluateU2FResult(const GURL& url) { + DCHECK(second_factor_controller_); + [second_factor_controller_ evaluateU2FResultFromU2FURL:url + webState:web_state_]; +} + +GURL U2FTabHelper::GetXCallbackUrl(const GURL& request_url, + const GURL& origin_url) { + // Create U2FController object lazily. + if (!second_factor_controller_) + second_factor_controller_ = [[U2FController alloc] init]; + NSString* tab_id = TabIdTabHelper::FromWebState(web_state_)->tab_id(); + return [second_factor_controller_ + XCallbackFromRequestURL:request_url + originURL:origin_url + tabURL:web_state_->GetLastCommittedURL() + tabID:tab_id]; +} + +WEB_STATE_USER_DATA_KEY_IMPL(U2FTabHelper)
diff --git a/ios/chrome/browser/u2f/u2f_tab_helper_unittest.mm b/ios/chrome/browser/u2f/u2f_tab_helper_unittest.mm new file mode 100644 index 0000000..b09d2a94 --- /dev/null +++ b/ios/chrome/browser/u2f/u2f_tab_helper_unittest.mm
@@ -0,0 +1,286 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/u2f/u2f_tab_helper.h" + +#import <UIKit/UIKit.h> + +#import "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" +#import "ios/chrome/browser/chrome_url_util.h" +#import "ios/chrome/browser/web/tab_id_tab_helper.h" +#import "ios/web/public/test/fakes/test_web_state.h" +#include "ios/web/public/web_state/url_verification_constants.h" +#include "net/base/escape.h" +#include "testing/gtest/include/gtest/gtest.h" +#import "testing/gtest_mac.h" +#include "testing/platform_test.h" +#include "url/gurl.h" +#include "url/url_util.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +class U2FTabHelperTest : public PlatformTest { + protected: + U2FTabHelperTest() { + U2FTabHelper::CreateForWebState(&web_state_); + TabIdTabHelper::CreateForWebState(&web_state_); + url::AddStandardScheme("chromium", url::SCHEME_WITH_HOST); + [[ChromeAppConstants sharedInstance] + setCallbackSchemeForTesting:@"chromium"]; + } + + U2FTabHelper* tab_helper() { return U2FTabHelper::FromWebState(&web_state_); } + + NSString* tab_id() { + return TabIdTabHelper::FromWebState(&web_state_)->tab_id(); + } + + // Returns the requestUUID NSString from a properly formatted U2F XCallback + // GURL. + NSString* GetRequestUuidFromXCallbackUrl(const GURL& xcallback_url) { + NSString* regex_string = @".+success.+requestUUID%3D(.+)%26.+error.+"; + NSRegularExpression* regex = + [NSRegularExpression regularExpressionWithPattern:regex_string + options:0 + error:nil]; + NSString* url_string = base::SysUTF8ToNSString(xcallback_url.spec()); + NSArray* matches = + [regex matchesInString:url_string + options:0 + range:NSMakeRange(0, url_string.length)]; + EXPECT_EQ(1u, [matches count]); + NSString* request_uuid_string = [regex + stringByReplacingMatchesInString:url_string + options:0 + range:NSMakeRange(0, url_string.length) + withTemplate:@"$1"]; + DCHECK(request_uuid_string.length); + return request_uuid_string; + } + + // Returns Regular experssion string that match a correct XCallback URL. + NSString* GetRegexString(const GURL& request_url, const GURL& origin_url) { + return [@[ + @"u2f-x-callback://x-callback-url/auth\\?x-success=.+u2f-callback", + @"%2F%3FtabID%3D", tab_id(), + @"%26requestUUID%3.+%26isU2F%3D1&x-error=.+u2f-callback%2F%3FtabID%3D", + tab_id(), @"%26requestUUID%3.+%26isU2F%3D1&data=", + base::SysUTF8ToNSString( + net::EscapeQueryParamValue(request_url.query(), true)), + @"&origin=", + base::SysUTF8ToNSString( + net::EscapeQueryParamValue(origin_url.spec(), true)) + ] componentsJoinedByString:@""]; + } + + web::TestWebState web_state_; +}; + +// Tests that IsU2FUrl returns true only if U2F url param is true. +TEST_F(U2FTabHelperTest, TestIsU2FUrl) { + GURL u2f_url("chromium://u2f-callback?isU2F=1"); + EXPECT_TRUE(U2FTabHelper::IsU2FUrl(u2f_url)); + + GURL wrong_u2f_url("chromium://u2f-callback?isU2F=0"); + EXPECT_FALSE(U2FTabHelper::IsU2FUrl(wrong_u2f_url)); + + GURL non_u2f_url("chromium://u2f-callback"); + EXPECT_FALSE(U2FTabHelper::IsU2FUrl(non_u2f_url)); + + GURL invalid_url; + EXPECT_FALSE(U2FTabHelper::IsU2FUrl(invalid_url)); +} + +// Tests that GetTabIdFromU2FUrl returns the correct tab ID. +TEST_F(U2FTabHelperTest, TestGetTabIdFromU2FURL) { + NSString* tab_id = @"B05B1860-18BA-43EA-B7DC-470D9F918FF5"; + GURL correct_url("chromium://" + "u2f-callback?tabID=B05B1860-18BA-43EA-B7DC-470D9F918FF5"); + EXPECT_NSEQ(tab_id, U2FTabHelper::GetTabIdFromU2FUrl(correct_url)); + + GURL wrong_url("chromium://u2fdemo.appspot.com"); + EXPECT_FALSE(U2FTabHelper::GetTabIdFromU2FUrl(wrong_url)); +} + +// Tests when request is legal and properly formatted. +TEST_F(U2FTabHelperTest, TestGetXCallbackUrlWithCorrectFlow) { + GURL tab_url("https://accounts.google.com"); + web_state_.SetCurrentURL(tab_url); + GURL request_url("u2f://accounts.google.com?data=abc&def%26ghi"); + GURL origin_url("https://accounts.google.com"); + GURL xcallback_url = tab_helper()->GetXCallbackUrl(request_url, origin_url); + + NSRegularExpression* regex = [NSRegularExpression + regularExpressionWithPattern:GetRegexString(request_url, origin_url) + options:0 + error:nil]; + + NSArray* matches = + [regex matchesInString:base::SysUTF8ToNSString(xcallback_url.spec()) + options:0 + range:NSMakeRange(0, xcallback_url.spec().length())]; + EXPECT_EQ(1u, [matches count]); +} + +// Tests when request is legal but contains duplicated parameters. +TEST_F(U2FTabHelperTest, TestGetXCallbackUrlWithDuplicatedParams) { + GURL request_url("chromium://u2f-callback?isU2F=0&tabID=1&requestUUID=2" + "&data=abc&def%26ghi"); + GURL origin_url("https://accounts.google.com"); + GURL tab_url("https://accounts.google.com"); + web_state_.SetCurrentURL(tab_url); + GURL xcallback_url = tab_helper()->GetXCallbackUrl(request_url, origin_url); + + NSRegularExpression* regex = [NSRegularExpression + regularExpressionWithPattern:GetRegexString(request_url, origin_url) + options:0 + error:nil]; + + NSArray* matches = + [regex matchesInString:base::SysUTF8ToNSString(xcallback_url.spec()) + options:0 + range:NSMakeRange(0, xcallback_url.spec().length())]; + EXPECT_EQ(1u, [matches count]); +} + +// Tests when request site is not whitelisted. +TEST_F(U2FTabHelperTest, TestGetXCallbackUrlWithNonWhitelistedUrl) { + GURL request_url("u2f://accounts.google.com?data=abc&def%26ghi"); + GURL evil_origin_url("https://evil.appspot.com"); + GURL tab_url("https://accounts.google.com"); + web_state_.SetCurrentURL(tab_url); + GURL evil_xcallback_url = + tab_helper()->GetXCallbackUrl(request_url, evil_origin_url); + EXPECT_EQ(GURL(), evil_xcallback_url); +} + +// Tests when request site does not have secure connection. +TEST_F(U2FTabHelperTest, TestGetXCallbackUrlWithInsecureConnection) { + GURL request_url("u2f://accounts.google.com?data=abc&def%26ghi"); + GURL insecure_origin_url("http://accounts.google.com"); + GURL tab_url("https://accounts.google.com"); + web_state_.SetCurrentURL(tab_url); + GURL insecure_xcallback_url = + tab_helper()->GetXCallbackUrl(request_url, insecure_origin_url); + EXPECT_EQ(GURL(), insecure_xcallback_url); +} + +// Tests when U2F callback has correct information, Tab URL has not changed and +// is trusted. +TEST_F(U2FTabHelperTest, TestEvaluateU2FResultWithCorrectFlowTest) { + GURL request_url("u2f://accounts.google.com?data=abc"); + GURL origin_url("https://accounts.google.com"); + GURL tab_url("https://accounts.google.com"); + web_state_.SetCurrentURL(tab_url); + GURL xcallback_url = tab_helper()->GetXCallbackUrl(request_url, origin_url); + NSString* request_uuid = GetRequestUuidFromXCallbackUrl(xcallback_url); + web_state_.SetTrustLevel(web::URLVerificationTrustLevel::kAbsolute); + GURL correct_request_uuid_url( + "chromium://u2f-callback?requestUUID=" + + base::SysNSStringToUTF8(request_uuid) + + "&requestId=TestID®istrationData=TestData&tabID=" + + base::SysNSStringToUTF8(tab_id())); + + EXPECT_TRUE(web_state_.GetLastExecutedJavascript().empty()); + + tab_helper()->EvaluateU2FResult(correct_request_uuid_url); + std::string last_executed_js = + base::UTF16ToUTF8(web_state_.GetLastExecutedJavascript()); + EXPECT_EQ(0, static_cast<int>(last_executed_js.find("u2f.callbackMap_"))); + + // Test Replay Attack - Subsequent calls with the + // same requestUUID should not do anything. + web_state_.ClearLastExecutedJavascript(); + tab_helper()->EvaluateU2FResult(correct_request_uuid_url); + EXPECT_TRUE(web_state_.GetLastExecutedJavascript().empty()); +} + +// Tests when U2F callback is not formatted correctly. +TEST_F(U2FTabHelperTest, TestEvaluateU2FResultWithBadURLFormat) { + GURL request_url("u2f://accounts.google.com?data=abc"); + GURL origin_url("https://accounts.google.com"); + GURL tab_url("https://accounts.google.com"); + web_state_.SetCurrentURL(tab_url); + GURL xcallback_url = tab_helper()->GetXCallbackUrl(request_url, origin_url); + NSString* request_uuid = GetRequestUuidFromXCallbackUrl(xcallback_url); + web_state_.SetTrustLevel(web::URLVerificationTrustLevel::kAbsolute); + + EXPECT_TRUE(web_state_.GetLastExecutedJavascript().empty()); + + // Test when U2F callback has no requestUUID info. + GURL no_request_uuid_url( + "chromium://" + "u2f-callback?requestId=TestID®istrationData=TestData&tabID=" + + base::SysNSStringToUTF8(tab_id())); + tab_helper()->EvaluateU2FResult(no_request_uuid_url); + EXPECT_TRUE(web_state_.GetLastExecutedJavascript().empty()); + + // Test when U2F callback has wrong requestUUID value. + GURL wrong_request_uuid_url("chromium://" + "u2f-callback?requestId=TestID®istrationData=" + "TestData&requestUUID=123&tabID=" + + base::SysNSStringToUTF8(tab_id())); + tab_helper()->EvaluateU2FResult(wrong_request_uuid_url); + EXPECT_TRUE(web_state_.GetLastExecutedJavascript().empty()); + + // Test when U2F callback has no registrationData value. + GURL no_registration_request_url( + "chromium://u2f-callback?requestUUID=" + + base::SysNSStringToUTF8(request_uuid) + + "&requestId=TestID&tabID=" + base::SysNSStringToUTF8(tab_id())); + + tab_helper()->EvaluateU2FResult(no_registration_request_url); + EXPECT_TRUE(web_state_.GetLastExecutedJavascript().empty()); + + // Test when U2F callback hostname is unexpected. + GURL wrong_host_name_url( + "chromium://" + "evil-callback?requestId=TestID®istrationData=TestData&requestUUID=" + + base::SysNSStringToUTF8(request_uuid) + + "&tabID=" + base::SysNSStringToUTF8(tab_id())); + tab_helper()->EvaluateU2FResult(wrong_host_name_url); + EXPECT_TRUE(web_state_.GetLastExecutedJavascript().empty()); +} + +// Tests when last committed URL is not valid for U2F. +TEST_F(U2FTabHelperTest, TestEvaluateU2FResultWithBadTabState) { + GURL request_url("u2f://accounts.google.com?data=abc"); + GURL origin_url("https://accounts.google.com"); + GURL correct_tab_url("https://accounts.google.com"); + web_state_.SetCurrentURL(correct_tab_url); + GURL xcallback_url = tab_helper()->GetXCallbackUrl(request_url, origin_url); + NSString* request_uuid = GetRequestUuidFromXCallbackUrl(xcallback_url); + + // Verify that last executed javascript is empty. + EXPECT_TRUE(web_state_.GetLastExecutedJavascript().empty()); + + // Test when U2F callback has correct information but Tab URL changed. + web_state_.SetTrustLevel(web::URLVerificationTrustLevel::kAbsolute); + web_state_.SetCurrentURL(GURL("http://www.dummy.com")); + GURL correct_request_uuid_url( + "chromium://" + "u2f-callback?requestId=TestID®istrationData=TestData&requestUUID=" + + base::SysNSStringToUTF8(request_uuid) + + "&tabID=" + base::SysNSStringToUTF8(tab_id())); + + tab_helper()->EvaluateU2FResult(correct_request_uuid_url); + EXPECT_TRUE(web_state_.GetLastExecutedJavascript().empty()); + + // Test when U2F callback has correct information but Tab URL not trusted. + web_state_.SetTrustLevel(web::URLVerificationTrustLevel::kNone); + web_state_.SetCurrentURL(correct_tab_url); + xcallback_url = tab_helper()->GetXCallbackUrl(request_url, origin_url); + request_uuid = GetRequestUuidFromXCallbackUrl(xcallback_url); + correct_request_uuid_url = GURL( + "chromium://" + "u2f-callback?requestId=TestID®istrationData=TestData&requestUUID=" + + base::SysNSStringToUTF8(request_uuid) + + "&tabID=" + base::SysNSStringToUTF8(tab_id())); + + tab_helper()->EvaluateU2FResult(correct_request_uuid_url); + EXPECT_TRUE(web_state_.GetLastExecutedJavascript().empty()); +}
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn index 2336142..d5186a2 100644 --- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn +++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -123,6 +123,7 @@ "//ios/chrome/browser/ui/content_suggestions/identifier", "//ios/chrome/browser/ui/list_model", "//ios/chrome/browser/ui/ntp", + "//ios/chrome/browser/ui/ntp_tile_views", "//ios/chrome/browser/ui/omnibox:omnibox_internal", "//ios/chrome/browser/ui/omnibox:omnibox_popup_shared", "//ios/chrome/browser/ui/overscroll_actions",
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_action_cell.mm b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_action_cell.mm index fd52a90e..46c8ae4 100644 --- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_action_cell.mm +++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_action_cell.mm
@@ -6,7 +6,7 @@ #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_constants.h" #import "ios/chrome/browser/ui/ntp_tile_views/ntp_shortcut_tile_view.h" -#import "ios/chrome/browser/ui/ntp_tile_views/ntp_tile_constants.h" +#import "ios/chrome/browser/ui/ntp_tile_views/ntp_tile_layout_util.h" #include "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/favicon/favicon_view.h" @@ -53,7 +53,8 @@ } + (CGSize)defaultSize { - return MostVisitedCellSize(); + return MostVisitedCellSize( + UIApplication.sharedApplication.preferredContentSizeCategory); } - (CGSize)intrinsicContentSize {
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_cell.mm b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_cell.mm index 0ab6181..2e7e2fc 100644 --- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_cell.mm +++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_cell.mm
@@ -7,7 +7,7 @@ #import "ios/chrome/browser/ui/ntp_tile_views/ntp_most_visited_tile_view.h" #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_constants.h" -#import "ios/chrome/browser/ui/ntp_tile_views/ntp_tile_constants.h" +#import "ios/chrome/browser/ui/ntp_tile_views/ntp_tile_layout_util.h" #include "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/common/favicon/favicon_view.h" #import "ios/chrome/common/material_timing.h" @@ -60,7 +60,8 @@ } + (CGSize)defaultSize { - return MostVisitedCellSize(); + return MostVisitedCellSize( + UIApplication.sharedApplication.preferredContentSizeCategory); } - (CGSize)intrinsicContentSize {
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.h index 673ccee..243871850 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.h
@@ -13,13 +13,6 @@ extern const CGFloat kHintTextScale; -// Returns the spacing between tiles, based on the device. -CGFloat horizontalSpacingBetweenTiles(); -CGFloat verticalSpacingBetweenTiles(); - -// Returns x-offset in order to have the tiles centered in a view with a -// |width|. -CGFloat centeredTilesMarginForWidth(CGFloat width); // Returns the proper height for the doodle. |logoIsShowing| refers to the // Google logo or the doodle. CGFloat doodleHeight(BOOL logoIsShowing);
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm index d535a96..6084acb6 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm
@@ -10,7 +10,6 @@ #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_cell.h" #import "ios/chrome/browser/ui/location_bar/location_bar_constants.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_header_constants.h" -#import "ios/chrome/browser/ui/ntp_tile_views/ntp_tile_constants.h" #import "ios/chrome/browser/ui/toolbar/public/toolbar_utils.h" #include "ios/chrome/browser/ui/ui_feature_flags.h" #include "ios/chrome/browser/ui/util/dynamic_type_util.h" @@ -26,11 +25,6 @@ namespace { -// Spacing between tiles. -const CGFloat kHorizontalSpacingRegularXRegular = 19; -const CGFloat kHorizontalSpacingOther = 9; -const CGFloat kVerticalSpacing = 16; - // Width of search field. const CGFloat kSearchFieldLarge = 432; const CGFloat kSearchFieldSmall = 343; @@ -72,32 +66,6 @@ const int kSearchFieldBackgroundColor = 0xF1F3F4; const CGFloat kHintTextScale = 0.15; -CGFloat horizontalSpacingBetweenTiles() { - return (!IsCompactWidth() && !IsCompactHeight()) - ? kHorizontalSpacingRegularXRegular - : kHorizontalSpacingOther; -} - -CGFloat verticalSpacingBetweenTiles() { - return kVerticalSpacing; -} - -CGFloat centeredTilesMarginForWidth(CGFloat width) { - CGFloat horizontalSpace = horizontalSpacingBetweenTiles(); - NSUInteger columns = NumberOfTilesPerRow(); - CGFloat whitespace = - width - - (columns * [ContentSuggestionsMostVisitedCell defaultSize].width) - - ((columns - 1) * horizontalSpace); - CGFloat margin = AlignValueToPixel(whitespace / 2); - // Allow for less spacing as an edge case on smaller devices. - if (margin < horizontalSpace) { - DCHECK(width < 400); // For now this is only expected on small widths. - return fmaxf(margin, 0); - } - return margin; -} - CGFloat doodleHeight(BOOL logoIsShowing) { if (!IsRegularXRegularSizeClass() && !logoIsShowing) return kNonGoogleSearchDoodleHeight;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils_unittest.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils_unittest.mm index 2db6728..5b96bce 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils_unittest.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils_unittest.mm
@@ -87,22 +87,6 @@ std::unique_ptr<ScopedBlockSwizzler> orientation_swizzler_; }; -TEST_F(ContentSuggestionsCollectionUtilsTest, centeredTilesMarginIPhone6) { - // Setup. - SetAsIPhone(); - - CGFloat result = centeredTilesMarginForWidth(375); - EXPECT_EQ(28, result); -} - -TEST_F(ContentSuggestionsCollectionUtilsTest, centeredTilesMarginIPad) { - // Setup. - SetAsIPad(); - - CGFloat result = centeredTilesMarginForWidth(767); - EXPECT_EQ(209, result); -} - TEST_F(ContentSuggestionsCollectionUtilsTest, doodleFrameIPad) { // Setup. SetAsIPad();
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm index e6df5f4..b39b7dd 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -22,6 +22,7 @@ #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller_audience.h" #import "ios/chrome/browser/ui/content_suggestions/ntp_home_constant.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_header_constants.h" +#import "ios/chrome/browser/ui/ntp_tile_views/ntp_tile_layout_util.h" #import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h" #import "ios/chrome/browser/ui/toolbar/public/toolbar_utils.h" #include "ios/chrome/browser/ui/ui_feature_flags.h" @@ -431,8 +432,8 @@ parentInset.right = 0; } else if ([self.collectionUpdater isMostVisitedSection:section] || [self.collectionUpdater isPromoSection:section]) { - CGFloat margin = content_suggestions::centeredTilesMarginForWidth( - collectionView.frame.size.width); + CGFloat margin = CenteredTilesMarginForWidth( + self.traitCollection, collectionView.frame.size.width); parentInset.left = margin; parentInset.right = margin; if ([self.collectionUpdater isMostVisitedSection:section]) { @@ -455,7 +456,7 @@ collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { if ([self.collectionUpdater isMostVisitedSection:section]) { - return content_suggestions::verticalSpacingBetweenTiles(); + return kNtpTilesVerticalSpacing; } return [super collectionView:collectionView layout:collectionViewLayout
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm b/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm index de0f27b..684c109 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm
@@ -9,6 +9,7 @@ #import "ios/chrome/browser/ui/location_bar/extended_touch_target_button.h" #import "ios/chrome/browser/ui/omnibox/omnibox_constants.h" #import "ios/chrome/browser/ui/toolbar/public/toolbar_constants.h" +#import "ios/chrome/browser/ui/util/dynamic_type_util.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/ui_util/constraints_ui_util.h" #include "ios/chrome/grit/ios_strings.h"
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm index 7aaf050..d178525 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
@@ -476,6 +476,10 @@ [menu setTargetRect:self.locationBarSteadyView.frame inView:self.view]; [menu setMenuVisible:YES animated:YES]; + // When we present the menu manually, it doesn't get focused by Voiceover. + // This notification forces voiceover to select the presented menu. + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, + menu); }); } }
diff --git a/ios/chrome/browser/ui/ntp_tile_views/BUILD.gn b/ios/chrome/browser/ui/ntp_tile_views/BUILD.gn index 4746cd2..228fd5e 100644 --- a/ios/chrome/browser/ui/ntp_tile_views/BUILD.gn +++ b/ios/chrome/browser/ui/ntp_tile_views/BUILD.gn
@@ -9,6 +9,8 @@ "ntp_most_visited_tile_view.mm", "ntp_shortcut_tile_view.h", "ntp_shortcut_tile_view.mm", + "ntp_tile_layout_util.h", + "ntp_tile_layout_util.mm", "ntp_tile_view.h", "ntp_tile_view.mm", ] @@ -19,6 +21,7 @@ "resources:ntp_most_visited_tile", "resources:ntp_readinglist_icon", "resources:ntp_recent_icon", + "//base", "//ios/chrome/browser/ui/util", "//ios/chrome/common/favicon", "//ios/chrome/common/ui_util", @@ -26,6 +29,20 @@ ] } +source_set("unit_tests") { + testonly = true + sources = [ + "ntp_tile_layout_util_unittest.mm", + ] + deps = [ + ":ntp_tile_views", + "//base", + "//testing/gtest", + "//third_party/ocmock", + ] + configs += [ "//build/config/compiler:enable_arc" ] +} + source_set("constants") { configs += [ "//build/config/compiler:enable_arc" ] sources = [
diff --git a/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_constants.h b/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_constants.h index 96912a4..46844b5 100644 --- a/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_constants.h +++ b/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_constants.h
@@ -15,12 +15,6 @@ NTPCollectionShortcutTypeHistory, }; -// Returns the size of most visited cell according to current font size. -CGSize MostVisitedCellSize(); - -// Returns number of tiles per row based on current system font size. -NSUInteger NumberOfTilesPerRow(); - // Returns a localized title for a given collection shortcut type. NSString* TitleForCollectionShortcutType(NTPCollectionShortcutType action); // Returns an icon for a given collection shortcut type to be used in an NTP
diff --git a/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_constants.mm b/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_constants.mm index 7eaf6a2f2..489261b 100644 --- a/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_constants.mm +++ b/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_constants.mm
@@ -13,47 +13,6 @@ #error "This file requires ARC support." #endif -// For font size < UIContentSizeCategoryExtraExtraExtraLarge -const CGSize kMostVisitedCellSizeSmall = {/*width=*/73, /*height=*/100}; -// For font size == UIContentSizeCategoryExtraExtraExtraLarge -const CGSize kMostVisitedCellSizeMedium = {/*width=*/73, /*height=*/112}; -// For font size == UIContentSizeCategoryAccessibilityMedium -const CGSize kMostVisitedCellSizeLarge = {/*width=*/110, /*height=*/140}; -// For font size > UIContentSizeCategoryAccessibilityMedium -const CGSize kMostVisitedCellSizeExtraLarge = {/*width=*/146, /*height=*/150}; - -CGSize MostVisitedCellSize() { - UIContentSizeCategory category = - UIApplication.sharedApplication.preferredContentSizeCategory; - NSComparisonResult result = UIContentSizeCategoryCompareToCategory( - category, UIContentSizeCategoryAccessibilityMedium); - switch (result) { - case NSOrderedAscending: - return ([category - isEqualToString:UIContentSizeCategoryExtraExtraExtraLarge]) - ? kMostVisitedCellSizeMedium - : kMostVisitedCellSizeSmall; - case NSOrderedSame: - return kMostVisitedCellSizeLarge; - case NSOrderedDescending: - return kMostVisitedCellSizeExtraLarge; - } -} - -NSUInteger NumberOfTilesPerRow() { - NSComparisonResult result = UIContentSizeCategoryCompareToCategory( - UIApplication.sharedApplication.preferredContentSizeCategory, - UIContentSizeCategoryAccessibilityMedium); - switch (result) { - case NSOrderedAscending: - return 4; - case NSOrderedSame: - return 3; - case NSOrderedDescending: - return 2; - } -} - // Returns the title to use for a cell with |action|. NSString* TitleForCollectionShortcutType(NTPCollectionShortcutType type) { switch (type) {
diff --git a/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_layout_util.h b/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_layout_util.h new file mode 100644 index 0000000..ff376b22 --- /dev/null +++ b/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_layout_util.h
@@ -0,0 +1,37 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_NTP_TILE_VIEWS_NTP_TILE_LAYOUT_UTIL_H_ +#define IOS_CHROME_BROWSER_UI_NTP_TILE_VIEWS_NTP_TILE_LAYOUT_UTIL_H_ + +#import <UIKit/UIKit.h> + +// Vertical spacing between rows of tiles. +extern const int kNtpTilesVerticalSpacing; +// Vertical spacing between columns of tiles. +extern const int kNtpTilesHorizontalSpacingRegular; +extern const int kNtpTilesHorizontalSpacingCompact; + +// For font size < UIContentSizeCategoryExtraExtraExtraLarge. +extern const CGSize kNtpTileViewSizeSmall; +// For font size == UIContentSizeCategoryExtraExtraExtraLarge. +extern const CGSize kNtpTileViewSizeMedium; +// For font size == UIContentSizeCategoryAccessibilityMedium. +extern const CGSize kNtpTileViewSizeLarge; +// For font size > UIContentSizeCategoryAccessibilityMedium. +extern const CGSize kNtpTileViewSizeExtraLarge; + +// Returns the vertical spacing between columns of tiles under +// |trait_collection|. +CGFloat NtpTilesHorizontalSpacing(UITraitCollection* trait_collection); + +// Returns the size of most visited cell based on |category|. +CGSize MostVisitedCellSize(UIContentSizeCategory category); + +// Returns x-offset in order to have the tiles centered in a view with a +// |width| under |environment|. +CGFloat CenteredTilesMarginForWidth(UITraitCollection* trait_collection, + CGFloat width); + +#endif // IOS_CHROME_BROWSER_UI_NTP_TILE_VIEWS_NTP_TILE_LAYOUT_UTIL_H_
diff --git a/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_layout_util.mm b/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_layout_util.mm new file mode 100644 index 0000000..48c17c8 --- /dev/null +++ b/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_layout_util.mm
@@ -0,0 +1,67 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/ntp_tile_views/ntp_tile_layout_util.h" + +#include "base/logging.h" +#import "ios/chrome/browser/ui/util/uikit_ui_util.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +const int kNtpTilesVerticalSpacing = 16; +const int kNtpTilesHorizontalSpacingRegular = 19; +const int kNtpTilesHorizontalSpacingCompact = 5; + +const CGSize kNtpTileViewSizeSmall = {/*width=*/73, /*height=*/100}; +const CGSize kNtpTileViewSizeMedium = {/*width=*/73, /*height=*/112}; +const CGSize kNtpTileViewSizeLarge = {/*width=*/110, /*height=*/140}; +const CGSize kNtpTileViewSizeExtraLarge = {/*width=*/146, /*height=*/150}; + +namespace { +// Display at most 4 tiles per row. +const int kMaxNumberOfTilesPerRow = 4; +} + +CGFloat NtpTilesHorizontalSpacing(UITraitCollection* trait_collection) { + return (trait_collection.horizontalSizeClass != + UIUserInterfaceSizeClassCompact && + trait_collection.verticalSizeClass != UIUserInterfaceSizeClassCompact) + ? kNtpTilesHorizontalSpacingRegular + : kNtpTilesHorizontalSpacingCompact; +} + +CGSize MostVisitedCellSize(UIContentSizeCategory category) { + NSComparisonResult result = UIContentSizeCategoryCompareToCategory( + category, UIContentSizeCategoryAccessibilityMedium); + switch (result) { + case NSOrderedAscending: + return ([category + isEqualToString:UIContentSizeCategoryExtraExtraExtraLarge]) + ? kNtpTileViewSizeMedium + : kNtpTileViewSizeSmall; + case NSOrderedSame: + return kNtpTileViewSizeLarge; + case NSOrderedDescending: + return kNtpTileViewSizeExtraLarge; + } +} + +CGFloat CenteredTilesMarginForWidth(UITraitCollection* trait_collection, + CGFloat width) { + CGFloat horizontalSpace = NtpTilesHorizontalSpacing(trait_collection); + CGSize cellSize = + MostVisitedCellSize(trait_collection.preferredContentSizeCategory); + for (int columns = kMaxNumberOfTilesPerRow; columns > 0; --columns) { + CGFloat whitespace = + width - (columns * cellSize.width) - ((columns - 1) * horizontalSpace); + CGFloat margin = AlignValueToPixel(whitespace / 2); + if (margin >= horizontalSpace) { + return margin; + } + } + NOTREACHED(); + return 0; +}
diff --git a/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_layout_util_unittest.mm b/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_layout_util_unittest.mm new file mode 100644 index 0000000..b0bd4980 --- /dev/null +++ b/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_layout_util_unittest.mm
@@ -0,0 +1,126 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/ntp_tile_views/ntp_tile_layout_util.h" + +#import <UIKit/UIKit.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 + +using NtpTileLayoutUtilTest = PlatformTest; + +// Tests that MostVisitedCellSize returns correct size for all content size +// categories. +TEST_F(NtpTileLayoutUtilTest, MostVisitedCellSize) { + EXPECT_TRUE( + CGSizeEqualToSize(kNtpTileViewSizeSmall, + MostVisitedCellSize(UIContentSizeCategoryUnspecified))); + EXPECT_TRUE( + CGSizeEqualToSize(kNtpTileViewSizeSmall, + MostVisitedCellSize(UIContentSizeCategoryExtraSmall))); + EXPECT_TRUE(CGSizeEqualToSize( + kNtpTileViewSizeSmall, MostVisitedCellSize(UIContentSizeCategorySmall))); + EXPECT_TRUE(CGSizeEqualToSize( + kNtpTileViewSizeSmall, MostVisitedCellSize(UIContentSizeCategoryMedium))); + EXPECT_TRUE(CGSizeEqualToSize( + kNtpTileViewSizeSmall, MostVisitedCellSize(UIContentSizeCategoryLarge))); + EXPECT_TRUE( + CGSizeEqualToSize(kNtpTileViewSizeSmall, + MostVisitedCellSize(UIContentSizeCategoryExtraLarge))); + EXPECT_TRUE(CGSizeEqualToSize( + kNtpTileViewSizeSmall, + MostVisitedCellSize(UIContentSizeCategoryExtraExtraLarge))); + EXPECT_TRUE(CGSizeEqualToSize( + kNtpTileViewSizeMedium, + MostVisitedCellSize(UIContentSizeCategoryExtraExtraExtraLarge))); + EXPECT_TRUE(CGSizeEqualToSize( + kNtpTileViewSizeLarge, + MostVisitedCellSize(UIContentSizeCategoryAccessibilityMedium))); + EXPECT_TRUE(CGSizeEqualToSize( + kNtpTileViewSizeExtraLarge, + MostVisitedCellSize(UIContentSizeCategoryAccessibilityLarge))); + EXPECT_TRUE(CGSizeEqualToSize( + kNtpTileViewSizeExtraLarge, + MostVisitedCellSize(UIContentSizeCategoryAccessibilityExtraLarge))); + EXPECT_TRUE(CGSizeEqualToSize( + kNtpTileViewSizeExtraLarge, + MostVisitedCellSize(UIContentSizeCategoryAccessibilityExtraExtraLarge))); + EXPECT_TRUE(CGSizeEqualToSize( + kNtpTileViewSizeExtraLarge, + MostVisitedCellSize( + UIContentSizeCategoryAccessibilityExtraExtraExtraLarge))); +} + +// Tests that CenteredTilesMarginForWidth works under various environment. +TEST_F(NtpTileLayoutUtilTest, CenteredTilesMarginForWidth) { + // Set up Regular size class and Large font size. + UITraitCollection* trait_collection = + [UITraitCollection traitCollectionWithTraitsFromCollections:@[ + [UITraitCollection traitCollectionWithHorizontalSizeClass: + UIUserInterfaceSizeClassRegular], + [UITraitCollection traitCollectionWithPreferredContentSizeCategory: + UIContentSizeCategoryLarge] + ]]; + + // Display 4 columns on very big screen. + EXPECT_EQ(200, CenteredTilesMarginForWidth( + trait_collection, + kNtpTileViewSizeSmall.width * 4 + + kNtpTilesHorizontalSpacingRegular * 3 + 200 * 2)); + // Display 4 columns on normal screen. + EXPECT_EQ(20, CenteredTilesMarginForWidth( + trait_collection, + kNtpTileViewSizeSmall.width * 4 + + kNtpTilesHorizontalSpacingRegular * 3 + 20 * 2)); + // Display 3 columns. + EXPECT_EQ(20, CenteredTilesMarginForWidth( + trait_collection, + kNtpTileViewSizeSmall.width * 3 + + kNtpTilesHorizontalSpacingRegular * 2 + 20 * 2)); + // Display 2 columns. + EXPECT_EQ(20, CenteredTilesMarginForWidth( + trait_collection, + kNtpTileViewSizeSmall.width * 2 + + kNtpTilesHorizontalSpacingRegular * 1 + 20 * 2)); + // Display 1 columns. + EXPECT_EQ(20, CenteredTilesMarginForWidth( + trait_collection, + kNtpTileViewSizeSmall.width * 1 + + kNtpTilesHorizontalSpacingRegular * 0 + 20 * 2)); + + // Set up Compact size class and Accessibility Large font size. + trait_collection = + [UITraitCollection traitCollectionWithTraitsFromCollections:@[ + [UITraitCollection traitCollectionWithHorizontalSizeClass: + UIUserInterfaceSizeClassCompact], + [UITraitCollection traitCollectionWithPreferredContentSizeCategory: + UIContentSizeCategoryAccessibilityLarge] + ]]; + + // Display 4 columns. + EXPECT_EQ(20, CenteredTilesMarginForWidth( + trait_collection, + kNtpTileViewSizeExtraLarge.width * 4 + + kNtpTilesHorizontalSpacingCompact * 3 + 20 * 2)); + // Display 3 columns. + EXPECT_EQ(20, CenteredTilesMarginForWidth( + trait_collection, + kNtpTileViewSizeExtraLarge.width * 3 + + kNtpTilesHorizontalSpacingCompact * 2 + 20 * 2)); + // Display 2 columns. + EXPECT_EQ(20, CenteredTilesMarginForWidth( + trait_collection, + kNtpTileViewSizeExtraLarge.width * 2 + + kNtpTilesHorizontalSpacingCompact * 1 + 20 * 2)); + // Display 1 columns. + EXPECT_EQ(20, CenteredTilesMarginForWidth( + trait_collection, + kNtpTileViewSizeExtraLarge.width * 1 + + kNtpTilesHorizontalSpacingCompact * 0 + 20 * 2)); +}
diff --git a/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_view.mm b/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_view.mm index 87a22315..4379e528 100644 --- a/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_view.mm +++ b/ios/chrome/browser/ui/ntp_tile_views/ntp_tile_view.mm
@@ -4,7 +4,7 @@ #import "ios/chrome/browser/ui/ntp_tile_views/ntp_tile_view.h" -#import "ios/chrome/browser/ui/util/uikit_ui_util.h" +#import "ios/chrome/browser/ui/util/dynamic_type_util.h" #import "ios/chrome/common/ui_util/constraints_ui_util.h" #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm index acc5102..b09ae95 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
@@ -21,6 +21,7 @@ #import "ios/chrome/browser/ui/toolbar/public/features.h" #import "ios/chrome/browser/ui/toolbar/public/toolbar_constants.h" #import "ios/chrome/browser/ui/util/animation_util.h" +#import "ios/chrome/browser/ui/util/dynamic_type_util.h" #import "ios/chrome/browser/ui/util/reversed_animation.h" #include "ios/chrome/browser/ui/util/rtl_geometry.h" #include "ios/chrome/browser/ui/util/ui_util.h"
diff --git a/ios/chrome/browser/ui/omnibox/popup/shortcuts/shortcuts_view_controller.mm b/ios/chrome/browser/ui/omnibox/popup/shortcuts/shortcuts_view_controller.mm index b5ceba5..b559c57 100644 --- a/ios/chrome/browser/ui/omnibox/popup/shortcuts/shortcuts_view_controller.mm +++ b/ios/chrome/browser/ui/omnibox/popup/shortcuts/shortcuts_view_controller.mm
@@ -11,6 +11,7 @@ #import "ios/chrome/browser/ui/ntp_tile_views/ntp_most_visited_tile_view.h" #import "ios/chrome/browser/ui/ntp_tile_views/ntp_shortcut_tile_view.h" #import "ios/chrome/browser/ui/ntp_tile_views/ntp_tile_constants.h" +#import "ios/chrome/browser/ui/ntp_tile_views/ntp_tile_layout_util.h" #import "ios/chrome/browser/ui/omnibox/popup/shortcuts/collection_shortcut_cell.h" #import "ios/chrome/browser/ui/omnibox/popup/shortcuts/most_visited_shortcut_cell.h" #import "ios/chrome/browser/ui/omnibox/popup/shortcuts/shortcuts_view_controller_delegate.h" @@ -24,8 +25,6 @@ namespace { const NSInteger kNumberOfItemsPerRow = 4; -const CGFloat kLineSpacing = 30; -const CGFloat kItemSpacing = 10; const CGFloat kTopInset = 10; const NSInteger kMostVisitedSection = 0; @@ -72,10 +71,8 @@ - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; // Calculate insets to center the items in the view. - CGFloat widthInsets = (self.view.bounds.size.width - - MostVisitedCellSize().width * NumberOfTilesPerRow() - - kItemSpacing * (kNumberOfItemsPerRow - 1)) / - 2; + CGFloat widthInsets = CenteredTilesMarginForWidth( + self.traitCollection, self.view.bounds.size.width); self.layout.sectionInset = UIEdgeInsetsMake(kTopInset, widthInsets, 0, widthInsets); } @@ -108,8 +105,11 @@ } _layout = [[UICollectionViewFlowLayout alloc] init]; - _layout.minimumLineSpacing = kLineSpacing; - _layout.itemSize = MostVisitedCellSize(); + _layout.minimumLineSpacing = kNtpTilesVerticalSpacing; + _layout.minimumInteritemSpacing = + NtpTilesHorizontalSpacing(self.traitCollection); + _layout.itemSize = + MostVisitedCellSize(self.traitCollection.preferredContentSizeCategory); return _layout; }
diff --git a/ios/chrome/browser/ui/payments/js_payment_request_manager.mm b/ios/chrome/browser/ui/payments/js_payment_request_manager.mm index be8a633..96a776f7 100644 --- a/ios/chrome/browser/ui/payments/js_payment_request_manager.mm +++ b/ios/chrome/browser/ui/payments/js_payment_request_manager.mm
@@ -69,10 +69,10 @@ (const payments::PaymentResponse&)paymentResponse completionHandler: (ProceduralBlockWithBool)completionHandler { - std::unique_ptr<base::DictionaryValue> paymentResponseData = - payment_request_util::PaymentResponseToDictionaryValue(paymentResponse); + base::Value paymentResponseData = + payment_request_util::PaymentResponseToValue(paymentResponse); std::string paymentResponseDataJSON; - base::JSONWriter::Write(*paymentResponseData, &paymentResponseDataJSON); + base::JSONWriter::Write(paymentResponseData, &paymentResponseDataJSON); NSString* script = [NSString stringWithFormat: @"__gCrWeb['paymentRequestManager'].resolveRequestPromise(%@)",
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn index 38e33b1..52dc9bc 100644 --- a/ios/chrome/browser/ui/settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -88,6 +88,9 @@ "resources:settings_sync", "resources:settings_voice_search", "resources:sync_and_google_services", + "resources:sync_and_google_services_sync_error", + "resources:sync_and_google_services_sync_off", + "resources:sync_and_google_services_sync_on", "//base", "//base:i18n", "//components/autofill/core/browser",
diff --git a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm index 2a7f854..f1fecb2c 100644 --- a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm +++ b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm
@@ -404,6 +404,12 @@ switch (itemType) { case SyncEverythingItemType: self.syncSetupService->SetSyncingAllDataTypes(value); + if (value) { + // When sync everything is turned on, the autocomplete wallet + // should be turned on. This code can be removed once + // crbug.com/937234 is fixed. + self.autocompleteWalletPreference.value = true; + } break; case AutofillDataTypeItemType: case BookmarksDataTypeItemType:
diff --git a/ios/chrome/browser/ui/settings/resources/BUILD.gn b/ios/chrome/browser/ui/settings/resources/BUILD.gn index 2a00f0e6..7024fe9 100644 --- a/ios/chrome/browser/ui/settings/resources/BUILD.gn +++ b/ios/chrome/browser/ui/settings/resources/BUILD.gn
@@ -156,3 +156,27 @@ "sync_and_google_services.imageset/sync_and_google_services@3x.png", ] } + +imageset("sync_and_google_services_sync_error") { + sources = [ + "sync_and_google_services_sync_error.imageset/Contents.json", + "sync_and_google_services_sync_error.imageset/sync_and_google_services_sync_error@2x.png", + "sync_and_google_services_sync_error.imageset/sync_and_google_services_sync_error@3x.png", + ] +} + +imageset("sync_and_google_services_sync_off") { + sources = [ + "sync_and_google_services_sync_off.imageset/Contents.json", + "sync_and_google_services_sync_off.imageset/sync_and_google_services_sync_off@2x.png", + "sync_and_google_services_sync_off.imageset/sync_and_google_services_sync_off@3x.png", + ] +} + +imageset("sync_and_google_services_sync_on") { + sources = [ + "sync_and_google_services_sync_on.imageset/Contents.json", + "sync_and_google_services_sync_on.imageset/sync_and_google_services_sync_on@2x.png", + "sync_and_google_services_sync_on.imageset/sync_and_google_services_sync_on@3x.png", + ] +}
diff --git a/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_error.imageset/Contents.json b/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_error.imageset/Contents.json new file mode 100644 index 0000000..71fa851 --- /dev/null +++ b/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_error.imageset/Contents.json
@@ -0,0 +1,18 @@ +{ + "images": [ + { + "idiom": "universal", + "scale": "2x", + "filename": "sync_and_google_services_sync_error@2x.png" + }, + { + "idiom": "universal", + "scale": "3x", + "filename": "sync_and_google_services_sync_error@3x.png" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +}
diff --git a/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_error.imageset/sync_and_google_services_sync_error@2x.png b/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_error.imageset/sync_and_google_services_sync_error@2x.png new file mode 100644 index 0000000..1e5940a --- /dev/null +++ b/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_error.imageset/sync_and_google_services_sync_error@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_error.imageset/sync_and_google_services_sync_error@3x.png b/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_error.imageset/sync_and_google_services_sync_error@3x.png new file mode 100644 index 0000000..83e49263 --- /dev/null +++ b/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_error.imageset/sync_and_google_services_sync_error@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_off.imageset/Contents.json b/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_off.imageset/Contents.json new file mode 100644 index 0000000..106f625 --- /dev/null +++ b/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_off.imageset/Contents.json
@@ -0,0 +1,18 @@ +{ + "images": [ + { + "idiom": "universal", + "scale": "2x", + "filename": "sync_and_google_services_sync_off@2x.png" + }, + { + "idiom": "universal", + "scale": "3x", + "filename": "sync_and_google_services_sync_off@3x.png" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +}
diff --git a/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_off.imageset/sync_and_google_services_sync_off@2x.png b/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_off.imageset/sync_and_google_services_sync_off@2x.png new file mode 100644 index 0000000..b51d8cc2 --- /dev/null +++ b/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_off.imageset/sync_and_google_services_sync_off@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_off.imageset/sync_and_google_services_sync_off@3x.png b/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_off.imageset/sync_and_google_services_sync_off@3x.png new file mode 100644 index 0000000..beab667 --- /dev/null +++ b/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_off.imageset/sync_and_google_services_sync_off@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_on.imageset/Contents.json b/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_on.imageset/Contents.json new file mode 100644 index 0000000..3eff447 --- /dev/null +++ b/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_on.imageset/Contents.json
@@ -0,0 +1,18 @@ +{ + "images": [ + { + "idiom": "universal", + "scale": "2x", + "filename": "sync_and_google_services_sync_on@2x.png" + }, + { + "idiom": "universal", + "scale": "3x", + "filename": "sync_and_google_services_sync_on@3x.png" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +}
diff --git a/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_on.imageset/sync_and_google_services_sync_on@2x.png b/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_on.imageset/sync_and_google_services_sync_on@2x.png new file mode 100644 index 0000000..385dee3e --- /dev/null +++ b/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_on.imageset/sync_and_google_services_sync_on@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_on.imageset/sync_and_google_services_sync_on@3x.png b/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_on.imageset/sync_and_google_services_sync_on@3x.png new file mode 100644 index 0000000..c14dcbc0 --- /dev/null +++ b/ios/chrome/browser/ui/settings/resources/sync_and_google_services_sync_on.imageset/sync_and_google_services_sync_on@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm index 8200a3b..7d1e862 100644 --- a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm
@@ -95,8 +95,12 @@ const CGFloat kAccountProfilePhotoDimension = 40.0f; NSString* const kSyncAndGoogleServicesImageName = @"sync_and_google_services"; -NSString* const kSyncAndGoogleServicesErrorImageName = - @"google_services_sync_error"; +NSString* const kSyncAndGoogleServicesSyncErrorImageName = + @"sync_and_google_services_sync_error"; +NSString* const kSyncAndGoogleServicesSyncOffImageName = + @"sync_and_google_services_sync_off"; +NSString* const kSyncAndGoogleServicesSyncOnImageName = + @"sync_and_google_services_sync_on"; NSString* const kSettingsSearchEngineImageName = @"settings_search_engine"; NSString* const kSettingsPasswordsImageName = @"settings_passwords"; NSString* const kSettingsAutofillCreditCardImageName = @@ -1032,11 +1036,7 @@ // Updates the Google services item to display the right icon and status message // in the detail text of the cell. - (void)updateGoogleServicesItem:(TableViewImageItem*)googleServicesItem { - // TODO(crbug.com/889470): Needs to include sync off, sync on, and error sync - // badges. googleServicesItem.detailTextColor = nil; - googleServicesItem.image = - [UIImage imageNamed:kSyncAndGoogleServicesImageName]; SyncSetupService* syncSetupService = SyncSetupServiceFactory::GetForBrowserState(_browserState); AuthenticationService* authService = @@ -1044,22 +1044,31 @@ if (!authService->IsAuthenticated()) { // No sync status when the user is not signed-in. googleServicesItem.detailText = nil; + googleServicesItem.image = + [UIImage imageNamed:kSyncAndGoogleServicesImageName]; } else if (!syncSetupService->HasFinishedInitialSetup()) { googleServicesItem.detailText = l10n_util::GetNSString(IDS_IOS_SYNC_SETUP_IN_PROGRESS); + googleServicesItem.image = + [UIImage imageNamed:kSyncAndGoogleServicesSyncOnImageName]; } else if (!IsTransientSyncError(syncSetupService->GetSyncServiceState())) { googleServicesItem.detailTextColor = UIColor.redColor; googleServicesItem.detailText = GetSyncErrorDescriptionForSyncSetupService(syncSetupService); googleServicesItem.image = - [UIImage imageNamed:kSyncAndGoogleServicesErrorImageName]; + [UIImage imageNamed:kSyncAndGoogleServicesSyncErrorImageName]; } else if (syncSetupService->IsSyncEnabled()) { googleServicesItem.detailText = l10n_util::GetNSString(IDS_IOS_SIGN_IN_TO_CHROME_SETTING_SYNC_ON); + googleServicesItem.image = + [UIImage imageNamed:kSyncAndGoogleServicesSyncOnImageName]; } else { googleServicesItem.detailText = l10n_util::GetNSString(IDS_IOS_SIGN_IN_TO_CHROME_SETTING_SYNC_OFF); + googleServicesItem.image = + [UIImage imageNamed:kSyncAndGoogleServicesSyncOffImageName]; } + DCHECK(googleServicesItem.image); } // Updates and reloads the Google service cell.
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_image_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_image_item.mm index 3986051..89a26ea9 100644 --- a/ios/chrome/browser/ui/table_view/cells/table_view_image_item.mm +++ b/ios/chrome/browser/ui/table_view/cells/table_view_image_item.mm
@@ -79,6 +79,7 @@ reuseIdentifier:(NSString*)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { + self.isAccessibilityElement = YES; _imageView = [[UIImageView alloc] init]; // The favicon image is smaller than its UIImageView's bounds, so center it. _imageView.contentMode = UIViewContentModeCenter; @@ -180,4 +181,14 @@ } } +#pragma mark - UIAccessibility + +- (NSString*)accessibilityLabel { + if (self.detailTextLabel.text) { + return [NSString stringWithFormat:@"%@, %@", self.titleLabel.text, + self.detailTextLabel.text]; + } + return self.titleLabel.text; +} + @end
diff --git a/ios/chrome/browser/ui/toolbar/primary_toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/primary_toolbar_coordinator.mm index b9bd780..cc88c196 100644 --- a/ios/chrome/browser/ui/toolbar/primary_toolbar_coordinator.mm +++ b/ios/chrome/browser/ui/toolbar/primary_toolbar_coordinator.mm
@@ -170,6 +170,12 @@ self.enableAnimationsForOmniboxFocus = NO; [self fakeboxFocused]; self.enableAnimationsForOmniboxFocus = YES; + // If the pasteboard is containing a URL, the omnibox popup suggestions are + // displayed as soon as the omnibox is focused. + // If the fake omnibox animation is triggered at the same time, it is possible + // to see the NTP going up where the real omnibox should be displayed. + if ([self.locationBarCoordinator omniboxPopupHasAutocompleteResults]) + [self onFakeboxAnimationComplete]; } - (void)fakeboxFocused {
diff --git a/ios/chrome/browser/ui/util/dynamic_type_util.h b/ios/chrome/browser/ui/util/dynamic_type_util.h index c3f55f6..333bf41 100644 --- a/ios/chrome/browser/ui/util/dynamic_type_util.h +++ b/ios/chrome/browser/ui/util/dynamic_type_util.h
@@ -22,4 +22,11 @@ UIContentSizeCategory min_category, UIContentSizeCategory max_category); +// Returns an UIFont* calculated by |style| and +// min(|currentCategory|,|maxCategory|). +UIFont* PreferredFontForTextStyleWithMaxCategory( + UIFontTextStyle style, + UIContentSizeCategory currentCategory, + UIContentSizeCategory maxCategory); + #endif // IOS_CHROME_BROWSER_UI_UTIL_DYNAMIC_TYPE_UTIL_H_
diff --git a/ios/chrome/browser/ui/util/dynamic_type_util.mm b/ios/chrome/browser/ui/util/dynamic_type_util.mm index 71b5b331..0cda4e79 100644 --- a/ios/chrome/browser/ui/util/dynamic_type_util.mm +++ b/ios/chrome/browser/ui/util/dynamic_type_util.mm
@@ -57,3 +57,17 @@ max_multiplier, std::max(min_multiplier, SystemSuggestedFontSizeMultiplier(category))); } + +UIFont* PreferredFontForTextStyleWithMaxCategory( + UIFontTextStyle style, + UIContentSizeCategory currentCategory, + UIContentSizeCategory maxCategory) { + NSComparisonResult result = + UIContentSizeCategoryCompareToCategory(currentCategory, maxCategory); + UIContentSizeCategory category = + result == NSOrderedDescending ? maxCategory : currentCategory; + return [UIFont preferredFontForTextStyle:style + compatibleWithTraitCollection: + [UITraitCollection + traitCollectionWithPreferredContentSizeCategory:category]]; +}
diff --git a/ios/chrome/browser/ui/util/dynamic_type_util_unittest.mm b/ios/chrome/browser/ui/util/dynamic_type_util_unittest.mm index fb2e783..34cffb73 100644 --- a/ios/chrome/browser/ui/util/dynamic_type_util_unittest.mm +++ b/ios/chrome/browser/ui/util/dynamic_type_util_unittest.mm
@@ -6,6 +6,7 @@ #import <UIKit/UIKit.h> +#include "testing/gtest_mac.h" #include "testing/platform_test.h" #import "third_party/ocmock/OCMock/OCMock.h" #include "third_party/ocmock/gtest_support.h" @@ -16,85 +17,66 @@ // Test fixture for DynamicTypeUtil class. class DynamicTypeUtilTest : public PlatformTest { - public: + protected: DynamicTypeUtilTest() {} ~DynamicTypeUtilTest() override {} - void SetPreferredContentSizeCategory(UILabel* testLabel, - UIViewController* viewController, - UIContentSizeCategory category) { - UITraitCollection* overrideTraitCollection = [UITraitCollection - traitCollectionWithPreferredContentSizeCategory:category]; - [viewController.parentViewController - setOverrideTraitCollection:overrideTraitCollection - forChildViewController:viewController]; - [testLabel removeFromSuperview]; - [viewController.view addSubview:testLabel]; + UIFont* PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyle style, + UIContentSizeCategory category) { + return + [UIFont preferredFontForTextStyle:style + compatibleWithTraitCollection: + [UITraitCollection + traitCollectionWithPreferredContentSizeCategory:category]]; } }; // Checks that the font sizes associated with the "body" // preferredContentSizeCategory aren't changing in new iOS releases. TEST_F(DynamicTypeUtilTest, TestFontSize) { - UIViewController* parentViewController = [[UIViewController alloc] init]; - UIViewController* viewController = [[UIViewController alloc] init]; - [parentViewController addChildViewController:viewController]; - [parentViewController.view addSubview:viewController.view]; - [viewController didMoveToParentViewController:parentViewController]; - - UILabel* testLabel = [[UILabel alloc] init]; - testLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; - testLabel.adjustsFontForContentSizeCategory = YES; - - SetPreferredContentSizeCategory(testLabel, viewController, - UIContentSizeCategoryExtraSmall); - EXPECT_EQ(14.f, testLabel.font.pointSize); - - SetPreferredContentSizeCategory(testLabel, viewController, - UIContentSizeCategorySmall); - EXPECT_EQ(15.f, testLabel.font.pointSize); - - SetPreferredContentSizeCategory(testLabel, viewController, - UIContentSizeCategoryMedium); - EXPECT_EQ(16.f, testLabel.font.pointSize); - - SetPreferredContentSizeCategory(testLabel, viewController, - UIContentSizeCategoryLarge); - EXPECT_EQ(17.f, testLabel.font.pointSize); - - SetPreferredContentSizeCategory(testLabel, viewController, - UIContentSizeCategoryExtraLarge); - EXPECT_EQ(19.f, testLabel.font.pointSize); - - SetPreferredContentSizeCategory(testLabel, viewController, - UIContentSizeCategoryExtraExtraLarge); - EXPECT_EQ(21.f, testLabel.font.pointSize); - - SetPreferredContentSizeCategory(testLabel, viewController, - UIContentSizeCategoryExtraExtraExtraLarge); - EXPECT_EQ(23.f, testLabel.font.pointSize); - - SetPreferredContentSizeCategory(testLabel, viewController, - UIContentSizeCategoryAccessibilityMedium); - EXPECT_EQ(28.f, testLabel.font.pointSize); - - SetPreferredContentSizeCategory(testLabel, viewController, - UIContentSizeCategoryAccessibilityLarge); - EXPECT_EQ(33.f, testLabel.font.pointSize); - - SetPreferredContentSizeCategory(testLabel, viewController, - UIContentSizeCategoryAccessibilityExtraLarge); - EXPECT_EQ(40.f, testLabel.font.pointSize); - - SetPreferredContentSizeCategory( - testLabel, viewController, - UIContentSizeCategoryAccessibilityExtraExtraLarge); - EXPECT_EQ(47.f, testLabel.font.pointSize); - - SetPreferredContentSizeCategory( - testLabel, viewController, - UIContentSizeCategoryAccessibilityExtraExtraExtraLarge); - EXPECT_EQ(53.f, testLabel.font.pointSize); + EXPECT_EQ(14.f, PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, UIContentSizeCategoryExtraSmall) + .pointSize); + EXPECT_EQ(15.f, PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, UIContentSizeCategorySmall) + .pointSize); + EXPECT_EQ(16.f, PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, UIContentSizeCategoryMedium) + .pointSize); + EXPECT_EQ(17.f, PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, UIContentSizeCategoryLarge) + .pointSize); + EXPECT_EQ(19.f, PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, UIContentSizeCategoryExtraLarge) + .pointSize); + EXPECT_EQ(21.f, PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, UIContentSizeCategoryExtraExtraLarge) + .pointSize); + EXPECT_EQ(23.f, + PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, UIContentSizeCategoryExtraExtraExtraLarge) + .pointSize); + EXPECT_EQ(28.f, + PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, UIContentSizeCategoryAccessibilityMedium) + .pointSize); + EXPECT_EQ(33.f, + PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, UIContentSizeCategoryAccessibilityLarge) + .pointSize); + EXPECT_EQ(40.f, PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, + UIContentSizeCategoryAccessibilityExtraLarge) + .pointSize); + EXPECT_EQ(47.f, PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, + UIContentSizeCategoryAccessibilityExtraExtraLarge) + .pointSize); + EXPECT_EQ(53.f, PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, + UIContentSizeCategoryAccessibilityExtraExtraExtraLarge) + .pointSize); } // Tests that the clamped version of the font size multipler is working. @@ -136,3 +118,58 @@ SystemSuggestedFontSizeMultiplier(UIContentSizeCategoryExtraExtraLarge), multiplier); } + +// Tests that |PreferredFontForTextStyleWithMaxCategory| works well with various +// input scenarios. +TEST_F(DynamicTypeUtilTest, PreferredFontSize) { + // Use normal category as maxmium category. + EXPECT_NSEQ(PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, UIContentSizeCategoryExtraSmall), + PreferredFontForTextStyleWithMaxCategory( + UIFontTextStyleBody, UIContentSizeCategoryExtraSmall, + UIContentSizeCategoryMedium)); + + EXPECT_NSEQ(PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, UIContentSizeCategoryMedium), + PreferredFontForTextStyleWithMaxCategory( + UIFontTextStyleBody, UIContentSizeCategoryMedium, + UIContentSizeCategoryMedium)); + + EXPECT_NSEQ(PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, UIContentSizeCategoryMedium), + PreferredFontForTextStyleWithMaxCategory( + UIFontTextStyleBody, UIContentSizeCategoryExtraExtraLarge, + UIContentSizeCategoryMedium)); + + EXPECT_NSEQ(PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, UIContentSizeCategoryMedium), + PreferredFontForTextStyleWithMaxCategory( + UIFontTextStyleBody, UIContentSizeCategoryAccessibilityLarge, + UIContentSizeCategoryMedium)); + + // Use accessibility category as maxmium category. + EXPECT_NSEQ(PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, UIContentSizeCategoryExtraSmall), + PreferredFontForTextStyleWithMaxCategory( + UIFontTextStyleBody, UIContentSizeCategoryExtraSmall, + UIContentSizeCategoryAccessibilityLarge)); + + EXPECT_NSEQ(PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, UIContentSizeCategoryMedium), + PreferredFontForTextStyleWithMaxCategory( + UIFontTextStyleBody, UIContentSizeCategoryMedium, + UIContentSizeCategoryAccessibilityLarge)); + + EXPECT_NSEQ(PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, UIContentSizeCategoryAccessibilityLarge), + PreferredFontForTextStyleWithMaxCategory( + UIFontTextStyleBody, UIContentSizeCategoryAccessibilityLarge, + UIContentSizeCategoryAccessibilityLarge)); + + EXPECT_NSEQ(PreferredFontForTextStyleAndSizeCategory( + UIFontTextStyleBody, UIContentSizeCategoryAccessibilityLarge), + PreferredFontForTextStyleWithMaxCategory( + UIFontTextStyleBody, + UIContentSizeCategoryAccessibilityExtraExtraLarge, + UIContentSizeCategoryAccessibilityLarge)); +}
diff --git a/ios/chrome/browser/ui/util/uikit_ui_util.h b/ios/chrome/browser/ui/util/uikit_ui_util.h index b7ac59bf..ac3b342 100644 --- a/ios/chrome/browser/ui/util/uikit_ui_util.h +++ b/ios/chrome/browser/ui/util/uikit_ui_util.h
@@ -255,9 +255,4 @@ // more than 99 tabs open. NSString* TextForTabCount(long count); -UIFont* PreferredFontForTextStyleWithMaxCategory( - UIFontTextStyle style, - UIContentSizeCategory currentCategory, - UIContentSizeCategory maxCategory); - #endif // IOS_CHROME_BROWSER_UI_UTIL_UIKIT_UI_UTIL_H_
diff --git a/ios/chrome/browser/ui/util/uikit_ui_util.mm b/ios/chrome/browser/ui/util/uikit_ui_util.mm index 96d1b1b..645cd1f 100644 --- a/ios/chrome/browser/ui/util/uikit_ui_util.mm +++ b/ios/chrome/browser/ui/util/uikit_ui_util.mm
@@ -690,20 +690,3 @@ return @":)"; return [NSString stringWithFormat:@"%ld", count]; } - -UIFont* PreferredFontForTextStyleWithMaxCategory( - UIFontTextStyle style, - UIContentSizeCategory currentCategory, - UIContentSizeCategory maxCategory) { - CGFloat maxMultiplier = SystemSuggestedFontSizeMultiplier(maxCategory); - CGFloat currentMultiplier = - SystemSuggestedFontSizeMultiplier(currentCategory); - if (currentMultiplier > maxMultiplier) { - return [UIFont - preferredFontForTextStyle:style - compatibleWithTraitCollection: - [UITraitCollection - traitCollectionWithPreferredContentSizeCategory:maxCategory]]; - } - return [UIFont preferredFontForTextStyle:style]; -}
diff --git a/ios/chrome/browser/web_resource/web_resource_util.cc b/ios/chrome/browser/web_resource/web_resource_util.cc index 349c75a..65c7d1c 100644 --- a/ios/chrome/browser/web_resource/web_resource_util.cc +++ b/ios/chrome/browser/web_resource/web_resource_util.cc
@@ -23,14 +23,6 @@ const char kUnexpectedJSONFormatError[] = "Data from web resource server does not have expected format."; -// Runs |error_callback| with |error| on |task_runner|. -void PostErrorTask(base::TaskRunner* task_runner, - const WebResourceService::ErrorCallback& error_callback, - const char error[]) { - task_runner->PostTask(FROM_HERE, - base::BindOnce(error_callback, std::string(error))); -} - // Parses |data| as a JSON string and calls back on |task_runner|. // Must not be called on the UI thread, for performance reasons. void ParseJSONOnBackgroundThread( @@ -39,24 +31,29 @@ const WebResourceService::SuccessCallback& success_callback, const WebResourceService::ErrorCallback& error_callback) { if (data.empty()) { - PostErrorTask(task_runner, error_callback, kInvalidDataTypeError); + task_runner->PostTask( + FROM_HERE, base::BindOnce(error_callback, kInvalidDataTypeError)); return; } - std::unique_ptr<base::Value> value(base::JSONReader::ReadDeprecated(data)); - if (!value.get()) { + base::Optional<base::Value> value(base::JSONReader::Read(data)); + if (!value) { // Page information not properly read, or corrupted. - PostErrorTask(task_runner, error_callback, kInvalidDataTypeError); + task_runner->PostTask( + FROM_HERE, base::BindOnce(error_callback, kInvalidDataTypeError)); return; } if (!value->is_dict()) { - PostErrorTask(task_runner, error_callback, kUnexpectedJSONFormatError); + task_runner->PostTask( + FROM_HERE, base::BindOnce(error_callback, kUnexpectedJSONFormatError)); return; } - task_runner->PostTask(FROM_HERE, - base::BindOnce(success_callback, std::move(value))); + task_runner->PostTask( + FROM_HERE, + base::BindOnce(success_callback, + base::Value::ToUniquePtrValue(std::move(value).value()))); } // Starts the parsing of |data| as a JSON string asynchronously on a background
diff --git a/ios/chrome/search_widget_extension/BUILD.gn b/ios/chrome/search_widget_extension/BUILD.gn index 946289ae..cb65f7d 100644 --- a/ios/chrome/search_widget_extension/BUILD.gn +++ b/ios/chrome/search_widget_extension/BUILD.gn
@@ -50,12 +50,12 @@ "copied_content_view.mm", "search_action_view.h", "search_action_view.mm", + "search_widget_constants.h", + "search_widget_constants.mm", "search_widget_view.h", "search_widget_view.mm", "search_widget_view_controller.h", "search_widget_view_controller.mm", - "ui_util.h", - "ui_util.mm", ] deps = [
diff --git a/ios/chrome/search_widget_extension/copied_content_view.mm b/ios/chrome/search_widget_extension/copied_content_view.mm index a8630c5..59b221e 100644 --- a/ios/chrome/search_widget_extension/copied_content_view.mm +++ b/ios/chrome/search_widget_extension/copied_content_view.mm
@@ -7,7 +7,8 @@ #import <NotificationCenter/NotificationCenter.h> #include "base/logging.h" -#import "ios/chrome/search_widget_extension/ui_util.h" +#import "ios/chrome/common/ui_util/constraints_ui_util.h" +#import "ios/chrome/search_widget_extension/search_widget_constants.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -41,12 +42,6 @@ @implementation CopiedContentView -@synthesize copiedContentLabel = _copiedContentLabel; -@synthesize copiedText = _copiedText; -@synthesize openCopiedContentTitleLabel = _openCopiedContentTitleLabel; -@synthesize hairlineView = _hairlineView; -@synthesize copiedButtonView = _copiedButtonView; - - (instancetype)initWithActionTarget:(id)target actionSelector:(SEL)actionSelector { DCHECK(target); @@ -71,8 +66,7 @@ @[ primaryEffectView, secondaryEffectView ]) { [self addSubview:effectView]; effectView.translatesAutoresizingMaskIntoConstraints = NO; - [NSLayoutConstraint - activateConstraints:ui_util::CreateSameConstraints(self, effectView)]; + AddSameConstraints(self, effectView); effectView.userInteractionEnabled = NO; } @@ -109,26 +103,24 @@ [_copiedButtonView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor - constant:ui_util::kContentMargin], + constant:kContentMargin], [_copiedButtonView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor - constant:-ui_util::kContentMargin], - [_copiedButtonView.topAnchor - constraintEqualToAnchor:self.topAnchor - constant:ui_util::kContentMargin], - [_copiedButtonView.bottomAnchor - constraintEqualToAnchor:self.bottomAnchor - constant:-ui_util::kContentMargin], + constant:-kContentMargin], + [_copiedButtonView.topAnchor constraintEqualToAnchor:self.topAnchor + constant:kContentMargin], + [_copiedButtonView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor + constant:-kContentMargin], [_openCopiedContentTitleLabel.topAnchor constraintEqualToAnchor:_copiedButtonView.topAnchor constant:kURLButtonMargin], [_openCopiedContentTitleLabel.leadingAnchor constraintEqualToAnchor:_copiedButtonView.leadingAnchor - constant:ui_util::kContentMargin], + constant:kContentMargin], [_openCopiedContentTitleLabel.trailingAnchor constraintEqualToAnchor:_copiedButtonView.trailingAnchor - constant:-ui_util::kContentMargin], + constant:-kContentMargin], [_copiedContentLabel.topAnchor constraintEqualToAnchor:_openCopiedContentTitleLabel.bottomAnchor],
diff --git a/ios/chrome/search_widget_extension/search_action_view.mm b/ios/chrome/search_widget_extension/search_action_view.mm index 2732b7431..e5672dc0 100644 --- a/ios/chrome/search_widget_extension/search_action_view.mm +++ b/ios/chrome/search_widget_extension/search_action_view.mm
@@ -7,7 +7,8 @@ #import <NotificationCenter/NotificationCenter.h> #include "base/logging.h" -#import "ios/chrome/search_widget_extension/ui_util.h" +#import "ios/chrome/common/ui_util/constraints_ui_util.h" +#import "ios/chrome/search_widget_extension/search_widget_constants.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -45,8 +46,7 @@ [self addSubview:effectView]; effectView.translatesAutoresizingMaskIntoConstraints = NO; effectView.userInteractionEnabled = NO; - [NSLayoutConstraint - activateConstraints:ui_util::CreateSameConstraints(self, effectView)]; + AddSameConstraints(self, effectView); } UIView* circleView = [[UIView alloc] initWithFrame:CGRectZero]; @@ -66,12 +66,11 @@ UIStackView* stack = [[UIStackView alloc] initWithArrangedSubviews:@[ circleView, labelView ]]; stack.axis = UILayoutConstraintAxisVertical; - stack.spacing = ui_util::kIconSpacing; + stack.spacing = kIconSpacing; stack.alignment = UIStackViewAlignmentCenter; stack.translatesAutoresizingMaskIntoConstraints = NO; [secondaryEffectView.contentView addSubview:stack]; - [NSLayoutConstraint activateConstraints:ui_util::CreateSameConstraints( - secondaryEffectView, stack)]; + AddSameConstraints(secondaryEffectView, stack); UIImage* iconImage = [UIImage imageNamed:imageName]; iconImage = [iconImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
diff --git a/ios/chrome/search_widget_extension/search_widget_constants.h b/ios/chrome/search_widget_extension/search_widget_constants.h new file mode 100644 index 0000000..44db73f0 --- /dev/null +++ b/ios/chrome/search_widget_extension/search_widget_constants.h
@@ -0,0 +1,14 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_SEARCH_WIDGET_EXTENSION_SEARCH_WIDGET_CONSTANTS_H_ +#define IOS_CHROME_SEARCH_WIDGET_EXTENSION_SEARCH_WIDGET_CONSTANTS_H_ + +// The spacing to use between action icons. +extern CGFloat const kIconSpacing; + +// The spacing between content and edges. +extern CGFloat const kContentMargin; + +#endif // IOS_CHROME_SEARCH_WIDGET_EXTENSION_SEARCH_WIDGET_CONSTANTS_H_
diff --git a/ios/chrome/search_widget_extension/search_widget_constants.mm b/ios/chrome/search_widget_extension/search_widget_constants.mm new file mode 100644 index 0000000..26f301b --- /dev/null +++ b/ios/chrome/search_widget_extension/search_widget_constants.mm
@@ -0,0 +1,14 @@ +// Copyright 2019 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 <UIKit/UIKit.h> + +#include "ios/chrome/search_widget_extension/search_widget_constants.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +CGFloat const kIconSpacing = 5; +CGFloat const kContentMargin = 12;
diff --git a/ios/chrome/search_widget_extension/search_widget_view.mm b/ios/chrome/search_widget_extension/search_widget_view.mm index ca8c427..f6ad453 100644 --- a/ios/chrome/search_widget_extension/search_widget_view.mm +++ b/ios/chrome/search_widget_extension/search_widget_view.mm
@@ -6,7 +6,7 @@ #include "base/logging.h" #import "ios/chrome/search_widget_extension/copied_content_view.h" #import "ios/chrome/search_widget_extension/search_action_view.h" -#import "ios/chrome/search_widget_extension/ui_util.h" +#import "ios/chrome/search_widget_extension/search_widget_constants.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -124,7 +124,7 @@ [self.actionsContent systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] .height; - return height + 2 * ui_util::kContentMargin; + return height + 2 * kContentMargin; } - (CGFloat)copiedURLSectionHeight { @@ -169,7 +169,7 @@ actionsContentStack.axis = UILayoutConstraintAxisHorizontal; actionsContentStack.alignment = UIStackViewAlignmentTop; actionsContentStack.distribution = UIStackViewDistributionFillEqually; - actionsContentStack.spacing = ui_util::kIconSpacing; + actionsContentStack.spacing = kIconSpacing; actionsContentStack.layoutMargins = UIEdgeInsetsZero; actionsContentStack.layoutMarginsRelativeArrangement = YES; actionsContentStack.translatesAutoresizingMaskIntoConstraints = NO; @@ -186,12 +186,12 @@ NSLayoutConstraint* actionsLeadingConstraint = [self.actionsContent.leadingAnchor constraintEqualToAnchor:self.actionsSection.leadingAnchor - constant:ui_util::kContentMargin]; + constant:kContentMargin]; actionsLeadingConstraint.priority = UILayoutPriorityDefaultHigh; NSLayoutConstraint* actionsTrailingConstraint = [self.actionsContent.trailingAnchor constraintEqualToAnchor:self.actionsSection.trailingAnchor - constant:-ui_util::kContentMargin]; + constant:-kContentMargin]; actionsTrailingConstraint.priority = UILayoutPriorityDefaultHigh; [NSLayoutConstraint activateConstraints:@[
diff --git a/ios/chrome/search_widget_extension/search_widget_view_controller.mm b/ios/chrome/search_widget_extension/search_widget_view_controller.mm index 9e080ed..548eaf3 100644 --- a/ios/chrome/search_widget_extension/search_widget_view_controller.mm +++ b/ios/chrome/search_widget_extension/search_widget_view_controller.mm
@@ -39,42 +39,10 @@ @property(nonatomic, assign) BOOL supportsSearchByImage; @property(nonatomic, readonly) BOOL copiedContentBehaviorEnabled; -// Updates the widget with latest data from the clipboard. Returns whether any -// visual updates occurred. -- (BOOL)updateWidget; -// Opens the main application with the given |command|. -- (void)openAppWithCommand:(NSString*)command; -// Opens the main application with the given |command|, |text|, and |image|. -- (void)openAppWithCommand:(NSString*)command - text:(NSString*)text - imageData:(NSData*)imageData; -// Returns the dictionary of commands to pass via user defaults to open the main -// application for a given |command| and optional |text| and |image|. -+ (NSDictionary*)dictForCommand:(NSString*)command - text:(NSString*)text - imageData:(NSData*)imageData; -// Register a display of the widget in the app_group NSUserDefaults. -// Metrics on the widget usage will be sent (if enabled) on the next Chrome -// startup. -- (void)registerWidgetDisplay; -// Sets the copied content type. |copiedText| should be provided if the content -// type requires textual data, otherwise it should be nil. Likewise, -// |copiedImage| should be provided if the content type requires image data. -// Also saves the data and returns YES if the screen needs updating and NO -// otherwise. -- (BOOL)setCopiedContentType:(CopiedContentType)type - copiedText:(NSString*)copiedText - copiedImage:(UIImage*)copiedImage; - @end @implementation SearchWidgetViewController -@synthesize widgetView = _widgetView; -@synthesize copiedText = _copiedText; -@synthesize copiedContentType = _copiedContentType; -@synthesize clipboardRecentContent = _clipboardRecentContent; - - (instancetype)init { self = [super init]; if (self) { @@ -132,6 +100,9 @@ completionHandler([self updateWidget] ? NCUpdateResultNewData : NCUpdateResultNoData); } + +// Updates the widget with latest data from the clipboard. Returns whether any +// visual updates occurred. - (BOOL)updateWidget { NSUserDefaults* sharedDefaults = app_group::GetGroupUserDefaults(); NSString* fieldTrialKey = @@ -271,10 +242,14 @@ #pragma mark - internal +// Opens the main application with the given |command|. - (void)openAppWithCommand:(NSString*)command { return [self openAppWithCommand:command text:nil imageData:nil]; } +// Register a display of the widget in the app_group NSUserDefaults. +// Metrics on the widget usage will be sent (if enabled) on the next Chrome +// startup. - (void)registerWidgetDisplay { NSUserDefaults* sharedDefaults = app_group::GetGroupUserDefaults(); NSInteger numberOfDisplay = @@ -283,6 +258,7 @@ forKey:app_group::kSearchExtensionDisplayCount]; } +// Opens the main application with the given |command|, |text|, and |image|. - (void)openAppWithCommand:(NSString*)command text:(NSString*)text imageData:(NSData*)imageData { @@ -312,6 +288,8 @@ [self.extensionContext openURL:openURL completionHandler:nil]; } +// Returns the dictionary of commands to pass via user defaults to open the main +// application for a given |command| and optional |text| and |image|. + (NSDictionary*)dictForCommand:(NSString*)command text:(NSString*)text imageData:(NSData*)imageData { @@ -343,6 +321,11 @@ return baseKeys; } +// Sets the copied content type. |copiedText| should be provided if the content +// type requires textual data, otherwise it should be nil. Likewise, +// |copiedImage| should be provided if the content type requires image data. +// Also saves the data and returns YES if the screen needs updating and NO +// otherwise. - (BOOL)setCopiedContentType:(CopiedContentType)type copiedText:(NSString*)copiedText copiedImage:(UIImage*)copiedImage {
diff --git a/ios/chrome/search_widget_extension/ui_util.h b/ios/chrome/search_widget_extension/ui_util.h deleted file mode 100644 index 9897552..0000000 --- a/ios/chrome/search_widget_extension/ui_util.h +++ /dev/null
@@ -1,23 +0,0 @@ -// 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_CHROME_SEARCH_WIDGET_EXTENSION_UI_UTIL_H_ -#define IOS_CHROME_SEARCH_WIDGET_EXTENSION_UI_UTIL_H_ - -namespace ui_util { - -// The spacing to use between action icons. -extern CGFloat const kIconSpacing; - -// The spacing between content and edges. -extern CGFloat const kContentMargin; - -// Returns constraints to make two views' size and center equal by pinning -// leading, trailing, top and bottom anchors. -NSArray<NSLayoutConstraint*>* CreateSameConstraints(UIView* view1, - UIView* view2); - -} // namespace ui_util - -#endif // IOS_CHROME_SEARCH_WIDGET_EXTENSION_UI_UTIL_H_
diff --git a/ios/chrome/search_widget_extension/ui_util.mm b/ios/chrome/search_widget_extension/ui_util.mm deleted file mode 100644 index 1b4dae7..0000000 --- a/ios/chrome/search_widget_extension/ui_util.mm +++ /dev/null
@@ -1,28 +0,0 @@ -// 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 <UIKit/UIKit.h> - -#include "ios/chrome/search_widget_extension/ui_util.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace ui_util { - -CGFloat const kIconSpacing = 5; -CGFloat const kContentMargin = 12; - -NSArray<NSLayoutConstraint*>* CreateSameConstraints(UIView* view1, - UIView* view2) { - return @[ - [view1.leadingAnchor constraintEqualToAnchor:view2.leadingAnchor], - [view1.trailingAnchor constraintEqualToAnchor:view2.trailingAnchor], - [view1.topAnchor constraintEqualToAnchor:view2.topAnchor], - [view1.bottomAnchor constraintEqualToAnchor:view2.bottomAnchor] - ]; -} - -} // namespace ui_util
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn index 98c2e32a..883988a8 100644 --- a/ios/chrome/test/BUILD.gn +++ b/ios/chrome/test/BUILD.gn
@@ -213,6 +213,7 @@ "//ios/chrome/browser/ui/main:unit_tests", "//ios/chrome/browser/ui/main_content:unit_tests", "//ios/chrome/browser/ui/ntp:unit_tests", + "//ios/chrome/browser/ui/ntp_tile_views:unit_tests", "//ios/chrome/browser/ui/omnibox:unit_tests", "//ios/chrome/browser/ui/omnibox/popup:unit_tests", "//ios/chrome/browser/ui/payments:unit_tests",
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn index 93a8c08..97b6437a 100644 --- a/ios/chrome/test/earl_grey/BUILD.gn +++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -10,7 +10,6 @@ ":ios_chrome_autofill_automation_egtests", ":ios_chrome_bookmarks_egtests", ":ios_chrome_device_check_egtests", - ":ios_chrome_external_url_egtests", ":ios_chrome_flaky_egtests", ":ios_chrome_integration_egtests", ":ios_chrome_manual_fill_egtests", @@ -20,6 +19,7 @@ ":ios_chrome_settings_egtests", ":ios_chrome_smoke_egtests", ":ios_chrome_tab_grid_egtests", + ":ios_chrome_translate_egtests", ":ios_chrome_ui_egtests", ":ios_chrome_unified_consent_egtests", ":ios_chrome_web_egtests", @@ -195,9 +195,9 @@ libs = [ "XCTest.framework" ] } -chrome_ios_eg_test("ios_chrome_external_url_egtests") { +chrome_ios_eg_test("ios_chrome_translate_egtests") { deps = [ - "//ios/chrome/browser/translate:external_url_eg_tests", + "//ios/chrome/browser/translate:eg_tests", ] }
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn index 7c0c060e..3e5db15 100644 --- a/ios/web/BUILD.gn +++ b/ios/web/BUILD.gn
@@ -176,6 +176,7 @@ "//ios/testing:http_server_bundle_data", "//ios/web/browsing_data:browsing_data_unittests", "//ios/web/download:download_unittests", + "//ios/web/find_in_page:find_in_page_unittests", "//ios/web/interstitials:interstitials_unittests", ] @@ -379,6 +380,7 @@ "//ios/net", "//ios/testing:ocmock_support", "//ios/web", + "//ios/web/find_in_page", "//ios/web/interstitials", "//ios/web/navigation", "//ios/web/navigation:wk_navigation_util",
diff --git a/ios/web/find_in_page/BUILD.gn b/ios/web/find_in_page/BUILD.gn index a876b97..a0721c2c 100644 --- a/ios/web/find_in_page/BUILD.gn +++ b/ios/web/find_in_page/BUILD.gn
@@ -20,3 +20,22 @@ configs += [ "//build/config/compiler:enable_arc" ] } + +source_set("find_in_page_unittests") { + testonly = true + deps = [ + ":find_in_page", + "//base", + "//base/test:test_support", + "//ios/web/public", + "//ios/web/public/test", + "//ios/web/public/test/fakes", + "//testing/gtest", + ] + + sources = [ + "find_in_page_manger_impl_unittest.mm", + ] + + configs += [ "//build/config/compiler:enable_arc" ] +}
diff --git a/ios/web/find_in_page/find_in_page_manger_impl_unittest.mm b/ios/web/find_in_page/find_in_page_manger_impl_unittest.mm new file mode 100644 index 0000000..c625b2a4 --- /dev/null +++ b/ios/web/find_in_page/find_in_page_manger_impl_unittest.mm
@@ -0,0 +1,189 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/web/find_in_page/find_in_page_manager_impl.h" + +#include "base/run_loop.h" +#import "base/test/ios/wait_util.h" +#include "base/values.h" +#import "ios/web/find_in_page/find_in_page_constants.h" +#import "ios/web/public/test/fakes/fake_find_in_page_manager_delegate.h" +#include "ios/web/public/test/fakes/fake_web_frame.h" +#import "ios/web/public/test/fakes/test_web_state.h" +#include "ios/web/public/test/web_test.h" +#include "ios/web/public/web_state/web_frame_util.h" +#import "ios/web/public/web_state/web_frames_manager.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +using base::test::ios::kWaitForJSCompletionTimeout; +using base::test::ios::WaitUntilConditionOrTimeout; + +namespace { + +// Frame ids of fake web frames used in this test class. +const char kOneMatchFrameId[] = "frame_with_one_match"; +const char kTwoMatchesFrameId[] = "frame_with_two_matches"; + +} // namespace + +namespace web { + +// Tests FindInPageManagerImpl and verifies that the state of +// FindInPageManagerDelegate is correct depending on what web frames return. +class FindInPageManagerImplTest : public WebTest { + protected: + FindInPageManagerImplTest() + : test_web_state_(std::make_unique<TestWebState>()) { + test_web_state_->CreateWebFramesManager(); + FindInPageManagerImpl::CreateForWebState(test_web_state_.get()); + GetFindInPageManager()->SetDelegate(&fake_delegate_); + } + + // Returns the FindInPageManager associated with |test_web_state_|. + FindInPageManager* GetFindInPageManager() { + return FindInPageManager::FromWebState(test_web_state_.get()); + } + // Returns a FakeWebFrame with id |frame_id| that will return |js_result| for + // the function call "findInString.findString". + std::unique_ptr<FakeWebFrame> CreateWebFrameWithJsResultForFind( + std::unique_ptr<base::Value> js_result, + const std::string& frame_id) { + auto frame_with_one_match = + std::make_unique<FakeWebFrame>(frame_id, + /*is_main_frame=*/false, GURL()); + frame_with_one_match->AddJsResultForFunctionCall(std::move(js_result), + kFindInPageSearch); + return frame_with_one_match; + } + + std::unique_ptr<TestWebState> test_web_state_; + FakeFindInPageManagerDelegate fake_delegate_; +}; + +// Tests that Find In Page responds with a total match count of three when a +// frame has one match and another frame has two matches. +TEST_F(FindInPageManagerImplTest, FindMatchesMultipleFrames) { + auto frame_with_one_match = CreateWebFrameWithJsResultForFind( + std::make_unique<base::Value>(1.0), kOneMatchFrameId); + FakeWebFrame* frame_with_one_match_ptr = frame_with_one_match.get(); + auto frame_with_two_matches = CreateWebFrameWithJsResultForFind( + std::make_unique<base::Value>(2.0), kTwoMatchesFrameId); + FakeWebFrame* frame_with_two_matches_ptr = frame_with_two_matches.get(); + test_web_state_->AddWebFrame(std::move(frame_with_one_match)); + test_web_state_->AddWebFrame(std::move(frame_with_two_matches)); + + GetFindInPageManager()->Find(@"foo", FindInPageOptions::FindInPageSearch); + + EXPECT_EQ("__gCrWeb.findInPage.findString(\"foo\", 100.0);", + frame_with_one_match_ptr->last_javascript_call()); + EXPECT_EQ("__gCrWeb.findInPage.findString(\"foo\", 100.0);", + frame_with_two_matches_ptr->last_javascript_call()); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool { + base::RunLoop().RunUntilIdle(); + return fake_delegate_.state(); + })); + EXPECT_EQ(3, fake_delegate_.state()->match_count); +} + +// Tests that Find In Page responds with a total match count of one when a frame +// has one match but find in one frame was cancelled. This can occur if the +// frame becomes unavailable. +TEST_F(FindInPageManagerImplTest, FrameCancelFind) { + auto frame_with_null_result = CreateWebFrameWithJsResultForFind( + std::make_unique<base::Value>(), "frame"); + FakeWebFrame* frame_with_null_result_ptr = frame_with_null_result.get(); + auto frame_with_one_match = CreateWebFrameWithJsResultForFind( + std::make_unique<base::Value>(1.0), kOneMatchFrameId); + FakeWebFrame* frame_with_one_match_ptr = frame_with_one_match.get(); + test_web_state_->AddWebFrame(std::move(frame_with_null_result)); + test_web_state_->AddWebFrame(std::move(frame_with_one_match)); + + GetFindInPageManager()->Find(@"foo", FindInPageOptions::FindInPageSearch); + + EXPECT_EQ("__gCrWeb.findInPage.findString(\"foo\", 100.0);", + frame_with_null_result_ptr->last_javascript_call()); + EXPECT_EQ("__gCrWeb.findInPage.findString(\"foo\", 100.0);", + frame_with_one_match_ptr->last_javascript_call()); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool { + base::RunLoop().RunUntilIdle(); + return fake_delegate_.state(); + })); + EXPECT_EQ(1, fake_delegate_.state()->match_count); +} + +// Tests that Find in Page returns a total match count matching the latest find +// if two finds are called. +TEST_F(FindInPageManagerImplTest, ReturnLatestFind) { + auto frame_with_one_match = CreateWebFrameWithJsResultForFind( + std::make_unique<base::Value>(1.0), kOneMatchFrameId); + FakeWebFrame* frame_with_one_match_ptr = frame_with_one_match.get(); + auto frame_with_two_matches = CreateWebFrameWithJsResultForFind( + std::make_unique<base::Value>(2.0), kTwoMatchesFrameId); + FakeWebFrame* frame_with_two_matches_ptr = frame_with_two_matches.get(); + test_web_state_->AddWebFrame(std::move(frame_with_one_match)); + test_web_state_->AddWebFrame(std::move(frame_with_two_matches)); + + GetFindInPageManager()->Find(@"foo", FindInPageOptions::FindInPageSearch); + + EXPECT_EQ("__gCrWeb.findInPage.findString(\"foo\", 100.0);", + frame_with_one_match_ptr->last_javascript_call()); + EXPECT_EQ("__gCrWeb.findInPage.findString(\"foo\", 100.0);", + frame_with_two_matches_ptr->last_javascript_call()); + test_web_state_->RemoveWebFrame(kOneMatchFrameId); + GetFindInPageManager()->Find(@"foo", FindInPageOptions::FindInPageSearch); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool { + base::RunLoop().RunUntilIdle(); + return fake_delegate_.state(); + })); + EXPECT_EQ(2, fake_delegate_.state()->match_count); +} + +// Tests that Find In Page should not return if the web state is destroyed +// during a find. +TEST_F(FindInPageManagerImplTest, DestroyWebStateDuringFind) { + auto frame_with_one_match = CreateWebFrameWithJsResultForFind( + std::make_unique<base::Value>(1.0), kOneMatchFrameId); + FakeWebFrame* frame_with_one_match_ptr = frame_with_one_match.get(); + test_web_state_->AddWebFrame(std::move(frame_with_one_match)); + + GetFindInPageManager()->Find(@"foo", FindInPageOptions::FindInPageSearch); + + EXPECT_EQ("__gCrWeb.findInPage.findString(\"foo\", 100.0);", + frame_with_one_match_ptr->last_javascript_call()); + test_web_state_ = nullptr; + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(fake_delegate_.state()); +} + +// Tests that Find in Page updates total match count when a frame with matches +// becomes unavailable during find. +TEST_F(FindInPageManagerImplTest, FrameUnavailableAfterDelegateCallback) { + auto frame_with_one_match = CreateWebFrameWithJsResultForFind( + std::make_unique<base::Value>(1.0), kOneMatchFrameId); + FakeWebFrame* frame_with_one_match_ptr = frame_with_one_match.get(); + auto frame_with_two_matches = CreateWebFrameWithJsResultForFind( + std::make_unique<base::Value>(2.0), kTwoMatchesFrameId); + FakeWebFrame* frame_with_two_matches_ptr = frame_with_two_matches.get(); + test_web_state_->AddWebFrame(std::move(frame_with_one_match)); + test_web_state_->AddWebFrame(std::move(frame_with_two_matches)); + + GetFindInPageManager()->Find(@"foo", FindInPageOptions::FindInPageSearch); + + EXPECT_EQ("__gCrWeb.findInPage.findString(\"foo\", 100.0);", + frame_with_one_match_ptr->last_javascript_call()); + EXPECT_EQ("__gCrWeb.findInPage.findString(\"foo\", 100.0);", + frame_with_two_matches_ptr->last_javascript_call()); + test_web_state_->RemoveWebFrame(kTwoMatchesFrameId); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool { + base::RunLoop().RunUntilIdle(); + return fake_delegate_.state(); + })); + EXPECT_EQ(1, fake_delegate_.state()->match_count); +} + +} // namespace web
diff --git a/ios/web/shell/test/BUILD.gn b/ios/web/shell/test/BUILD.gn index 4cf9c16b..e05de3f 100644 --- a/ios/web/shell/test/BUILD.gn +++ b/ios/web/shell/test/BUILD.gn
@@ -20,7 +20,6 @@ sources = [ "context_menu_egtest.mm", "page_state_egtest.mm", - "redirect_egtest.mm", "service_manager_egtest.mm", ]
diff --git a/ios/web/shell/test/redirect_egtest.mm b/ios/web/shell/test/redirect_egtest.mm deleted file mode 100644 index 0c32da3..0000000 --- a/ios/web/shell/test/redirect_egtest.mm +++ /dev/null
@@ -1,105 +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. - -#import <EarlGrey/EarlGrey.h> - -#import "ios/web/public/test/http_server/html_response_provider.h" -#import "ios/web/public/test/http_server/html_response_provider_impl.h" -#import "ios/web/public/test/http_server/http_server.h" -#include "ios/web/public/test/http_server/http_server_util.h" -#import "ios/web/shell/test/earl_grey/shell_earl_grey.h" -#import "ios/web/shell/test/earl_grey/shell_matchers.h" -#import "ios/web/shell/test/earl_grey/shell_matchers_shorthand.h" -#import "ios/web/shell/test/earl_grey/web_shell_test_case.h" -#include "net/http/http_status_code.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -using web::AddressFieldText; -using web::test::HttpServer; - -// Redirect test cases for the web shell. -@interface RedirectTestCase : WebShellTestCase -@end - -@implementation RedirectTestCase - -// Tests loading of page that is redirected 3 times using a 301 redirect. -- (void)testMultipleRedirects { - // Create map of canned responses and set up the test HTML server. - std::map<GURL, HtmlResponseProviderImpl::Response> responses; - const GURL firstRedirectURL = HttpServer::MakeUrl("http://firstRedirect/"); - const GURL secondRedirectURL = HttpServer::MakeUrl("http://secondRedirect/"); - const GURL thirdRedirectURL = HttpServer::MakeUrl("http://thirdRedirect/"); - const GURL destinationURL = HttpServer::MakeUrl("http://destination/"); - - responses[firstRedirectURL] = HtmlResponseProviderImpl::GetRedirectResponse( - secondRedirectURL, net::HTTP_MOVED_PERMANENTLY); - responses[secondRedirectURL] = HtmlResponseProviderImpl::GetRedirectResponse( - thirdRedirectURL, net::HTTP_MOVED_PERMANENTLY); - responses[thirdRedirectURL] = HtmlResponseProviderImpl::GetRedirectResponse( - destinationURL, net::HTTP_MOVED_PERMANENTLY); - const char kFinalPageContent[] = "testMultipleRedirects complete"; - responses[destinationURL] = - HtmlResponseProviderImpl::GetSimpleResponse(kFinalPageContent); - std::unique_ptr<web::DataResponseProvider> provider( - new HtmlResponseProvider(responses)); - web::test::SetUpHttpServer(std::move(provider)); - - // Load first URL and expect destination URL to load. - [ShellEarlGrey loadURL:firstRedirectURL]; - [[EarlGrey selectElementWithMatcher:AddressFieldText(destinationURL.spec())] - assertWithMatcher:grey_notNil()]; - [ShellEarlGrey waitForWebViewContainingText:kFinalPageContent]; -} - -// Tests simple 301 redirection. -- (void)testRedirection301 { - // Create map of canned responses and set up the test HTML server. - std::map<GURL, HtmlResponseProviderImpl::Response> responses; - const GURL firstRedirectURL = HttpServer::MakeUrl("http://firstRedirect/"); - const GURL destinationURL = HttpServer::MakeUrl("http://destination/"); - - responses[firstRedirectURL] = HtmlResponseProviderImpl::GetRedirectResponse( - destinationURL, net::HTTP_MOVED_PERMANENTLY); - const char kFinalPageContent[] = "testRedirection301 complete"; - responses[destinationURL] = - HtmlResponseProviderImpl::GetSimpleResponse(kFinalPageContent); - std::unique_ptr<web::DataResponseProvider> provider( - new HtmlResponseProvider(responses)); - web::test::SetUpHttpServer(std::move(provider)); - - // Load first URL and expect destination URL to load. - [ShellEarlGrey loadURL:firstRedirectURL]; - [[EarlGrey selectElementWithMatcher:AddressFieldText(destinationURL.spec())] - assertWithMatcher:grey_notNil()]; - [ShellEarlGrey waitForWebViewContainingText:kFinalPageContent]; -} - -// Tests simple 302 redirection. -- (void)testRedirection302 { - // Create map of canned responses and set up the test HTML server. - std::map<GURL, HtmlResponseProviderImpl::Response> responses; - const GURL firstRedirectURL = HttpServer::MakeUrl("http://firstRedirect/"); - const GURL destinationURL = HttpServer::MakeUrl("http://destination/"); - - responses[firstRedirectURL] = HtmlResponseProviderImpl::GetRedirectResponse( - destinationURL, net::HTTP_FOUND); - const char kFinalPageContent[] = "testRedirection302 complete"; - responses[destinationURL] = - HtmlResponseProviderImpl::GetSimpleResponse(kFinalPageContent); - std::unique_ptr<web::DataResponseProvider> provider( - new HtmlResponseProvider(responses)); - web::test::SetUpHttpServer(std::move(provider)); - - // Load first URL and expect destination URL to load. - [ShellEarlGrey loadURL:firstRedirectURL]; - [[EarlGrey selectElementWithMatcher:AddressFieldText(destinationURL.spec())] - assertWithMatcher:grey_notNil()]; - [ShellEarlGrey waitForWebViewContainingText:kFinalPageContent]; -} - -@end
diff --git a/ios/web/web_state/ui/crw_web_controller.h b/ios/web/web_state/ui/crw_web_controller.h index cff7966..1acaa6b7 100644 --- a/ios/web/web_state/ui/crw_web_controller.h +++ b/ios/web/web_state/ui/crw_web_controller.h
@@ -43,7 +43,6 @@ namespace web { class NavigationItem; -class WebState; class WebStateImpl; } @@ -56,8 +55,7 @@ // TODO(stuartmorgan): Move all of the navigation APIs out of this class. @interface CRWWebController : NSObject <CRWJSInjectionEvaluator, CRWSessionControllerDelegate, - CRWTouchTrackingDelegate, - UIGestureRecognizerDelegate> + CRWTouchTrackingDelegate> // Whether or not a UIWebView is allowed to exist in this CRWWebController. // Defaults to NO; this should be enabled before attempting to access the view. @@ -66,8 +64,6 @@ @property(nonatomic, weak) id<CRWNativeContentProvider> nativeProvider; @property(nonatomic, weak) id<CRWSwipeRecognizerProvider> swipeRecognizerProvider; -@property(nonatomic, readonly) web::WebState* webState; -@property(nonatomic, readonly) web::WebStateImpl* webStateImpl; // The container view used to display content. If the view has been purged due // to low memory, this will recreate it. @@ -91,9 +87,6 @@ // (nothing loaded) and 1.0 (fully loaded). @property(nonatomic, readonly) double loadingProgress; -// Returns the x, y offset the content has been scrolled. -@property(nonatomic, readonly) CGPoint scrollPosition; - // YES if the web process backing WebView is believed to currently be crashed. @property(nonatomic, assign, getter=isWebProcessCrashed) BOOL webProcessCrashed; @@ -105,6 +98,10 @@ // back-forward list navigations. @property(nonatomic) BOOL allowsBackForwardNavigationGestures; +// The receiver of JavaScripts. +@property(nonatomic, strong, readonly) + CRWJSInjectionReceiver* jsInjectionReceiver; + // Designated initializer. Initializes web controller with |webState|. The // calling code must retain the ownership of |webState|. - (instancetype)initWithWebState:(web::WebStateImpl*)webState; @@ -155,9 +152,6 @@ // navigation. |isRendererInitiated| is NO for browser-initiated navigation. - (void)reloadWithRendererInitiatedNavigation:(BOOL)isRendererInitiated; -// Stops web view loading. -- (void)stopLoading; - // Loads the URL indicated by current session state. - (void)loadCurrentURLWithRendererInitiatedNavigation:(BOOL)rendererInitiated; @@ -203,8 +197,6 @@ // Removes |recognizer| from the web view. - (void)removeGestureRecognizerFromWebView:(UIGestureRecognizer*)recognizer; -- (CRWJSInjectionReceiver*)jsInjectionReceiver; - // Returns the native controller (if any) current mananging the content. - (id<CRWNativeContent>)nativeController; @@ -236,6 +228,9 @@ @interface CRWWebController (UsedOnlyForTesting) // Testing or internal API. +@property(nonatomic, readonly) web::WebState* webState; +@property(nonatomic, readonly) web::WebStateImpl* webStateImpl; + // Returns whether the user is interacting with the page. @property(nonatomic, readonly) BOOL userIsInteracting;
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index 9c936f0..3723b93 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -222,12 +222,6 @@ @end @implementation CRWWebControllerPendingNavigationInfo -@synthesize referrer = _referrer; -@synthesize MIMEType = _MIMEType; -@synthesize navigationType = _navigationType; -@synthesize HTTPMethod = _HTTPMethod; -@synthesize cancelled = _cancelled; -@synthesize hasUserGesture = _hasUserGesture; - (instancetype)init { if ((self = [super init])) { @@ -246,8 +240,6 @@ CRWWebViewScrollViewProxyObserver, WKNavigationDelegate, WKUIDelegate> { - // The WKWebView managed by this instance. - WKWebView* _webView; // The view used to display content. Must outlive |_webViewProxy|. The // container view should be accessed through this property rather than // |self.view| from within this class, as |self.view| triggers creation while @@ -257,14 +249,8 @@ // and after web usage was disabled. Used by |-loadCurrentURLIfNecessary| to // prevent extra loads. BOOL _currentURLLoadWasTrigerred; - // If |_contentView| contains a native view rather than a web view, this - // is its controller. If it's a web view, this is nil. - id<CRWNativeContent> _nativeController; BOOL _isHalted; // YES if halted. Halting happens prior to destruction. BOOL _isBeingDestroyed; // YES if in the process of closing. - // YES if a user interaction has been registered at any time once the page has - // loaded. - BOOL _userInteractionRegistered; // YES if the user has interacted with the content area since the last URL // change. BOOL _interactionRegisteredSinceLastURLChange; @@ -287,9 +273,6 @@ NSMutableArray* _gestureRecognizers; // Flag to say if browsing is enabled. BOOL _webUsageEnabled; - // The touch tracking recognizer allowing us to decide if a navigation is - // started by the user. - CRWTouchTrackingRecognizer* _touchTrackingRecognizer; // The controller that tracks long press and check context menu trigger. CRWContextMenuController* _contextMenuController; // Whether a click is in progress. @@ -315,10 +298,6 @@ // Object for loading POST requests with body. CRWJSPOSTRequestLoader* _POSTRequestLoader; - // WebStateImpl instance associated with this CRWWebController, web controller - // does not own this pointer. - WebStateImpl* _webStateImpl; - // A set of script managers whose scripts have been injected into the current // page. // TODO(stuartmorgan): Revisit this approach; it's intended only as a stopgap @@ -332,9 +311,6 @@ // Script manager for setting the windowID. CRWJSWindowIDManager* _windowIDJSManager; - // The receiver of JavaScripts. - CRWJSInjectionReceiver* _jsInjectionReceiver; - // Backs up property with the same name. std::unique_ptr<web::MojoFacade> _mojoFacade; @@ -391,12 +367,6 @@ @property(nonatomic, readwrite) web::PageDisplayState pageDisplayState; // The currently displayed native controller, if any. @property(weak, nonatomic, readwrite) id<CRWNativeContent> nativeController; -// Returns NavigationManager's session controller. -@property(weak, nonatomic, readonly) CRWSessionController* sessionController; -// The associated NavigationManagerImpl. -@property(nonatomic, readonly) NavigationManagerImpl* navigationManagerImpl; -// Whether the associated WebState has an opener. -@property(nonatomic, readonly) BOOL hasOpener; // Dictionary where keys are the names of WKWebView properties and values are // selector names which should be called when a corresponding property has // changed. e.g. @{ @"URL" : @"webViewURLDidChange" } means that @@ -425,6 +395,31 @@ // Facade for Mojo API. @property(nonatomic, readonly) web::MojoFacade* mojoFacade; +// YES if a user interaction has been registered at any time since the page has +// loaded. +@property(nonatomic, readwrite) BOOL userInteractionRegistered; + +@property(nonatomic, readonly) web::WebState* webState; +// WebStateImpl instance associated with this CRWWebController, web controller +// does not own this pointer. +@property(nonatomic, readonly) web::WebStateImpl* webStateImpl; + +// Returns the x, y offset the content has been scrolled. +@property(nonatomic, readonly) CGPoint scrollPosition; + +// The touch tracking recognizer allowing us to decide if a navigation has user +// gesture. Lazily created. +@property(nonatomic, strong, readonly) + CRWTouchTrackingRecognizer* touchTrackingRecognizer; + +// Session Information +// ------------------- +// Returns NavigationManager's session controller. +@property(weak, nonatomic, readonly) CRWSessionController* sessionController; +// The associated NavigationManagerImpl. +@property(nonatomic, readonly) NavigationManagerImpl* navigationManagerImpl; +// Whether the associated WebState has an opener. +@property(nonatomic, readonly) BOOL hasOpener; // TODO(crbug.com/692871): Remove these functions and replace with more // appropriate NavigationItem getters. // Returns the navigation item for the current page. @@ -437,10 +432,6 @@ // unless the request was a POST. @property(weak, nonatomic, readonly) NSDictionary* currentHTTPHeaders; -// YES if a user interaction has been registered at any time since the page has -// loaded. -@property(nonatomic, readwrite) BOOL userInteractionRegistered; - // Called when the web page has changed document and/or URL, and so the page // navigation should be reported to the delegate, and internal state updated to // reflect the fact that the navigation has occurred. |context| contains @@ -458,8 +449,6 @@ - (void)didStartLoading; // Returns YES if the URL looks like it is one CRWWebController can show. + (BOOL)webControllerCanShow:(const GURL&)url; -// Returns a lazily created CRWTouchTrackingRecognizer. -- (CRWTouchTrackingRecognizer*)touchTrackingRecognizer; // Creates a container view if it's not yet created. - (void)ensureContainerViewCreated; // Creates a web view if it's not yet created. @@ -659,14 +648,6 @@ - (void)injectHTML5HistoryScriptWithHashChange:(BOOL)dispatchHashChange sameDocumentNavigation:(BOOL)sameDocumentNavigation; -// WKNavigation objects are used as a weak key to store web::NavigationContext. -// WKWebView manages WKNavigation lifetime and destroys them after the -// navigation is finished. However for window opening navigations WKWebView -// passes null WKNavigation to WKNavigationDelegate callbacks and strong key is -// used to store web::NavigationContext. Those "null" navigations have to be -// cleaned up manually by calling this method. -- (void)forgetNullWKNavigation:(WKNavigation*)navigation; - // Returns YES if the current live view is a web view with an image MIME type. - (BOOL)contentIsImage; // Restores the state for this page from session history. @@ -697,8 +678,6 @@ // Sets scroll offset value for webview scroll view from |scrollState|. - (void)applyWebViewScrollOffsetFromScrollState: (const web::PageScrollState&)scrollState; -// Returns the referrer for the current page. -- (web::Referrer)currentReferrer; // Adds a new NavigationItem with the given URL and state object to the history // stack. A state object is a serialized generic JavaScript object that contains // details of the UI's state for a given NavigationItem/URL. @@ -758,38 +737,9 @@ completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential*))completionHandler; -// Helper to respond to |webView:runJavaScript...| delegate methods. -// |completionHandler| must not be nil. -- (void)runJavaScriptDialogOfType:(web::JavaScriptDialogType)type - initiatedByFrame:(WKFrameInfo*)frame - message:(NSString*)message - defaultText:(NSString*)defaultText - completion:(void (^)(BOOL, NSString*))completionHandler; - -// Called when WKWebView estimatedProgress has been changed. -- (void)webViewEstimatedProgressDidChange; -// Called when WKWebView certificateChain or hasOnlySecureContent property has -// changed. -- (void)webViewSecurityFeaturesDidChange; -// Called when WKWebView loading state has been changed. -- (void)webViewLoadingStateDidChange; -// Called when WKWebView title has been changed. -- (void)webViewTitleDidChange; -// Called when WKWebView canGoForward/canGoBack state has been changed. -- (void)webViewBackForwardStateDidChange; -// Called when WKWebView URL has been changed. -- (void)webViewURLDidChange; -// Returns YES if a KVO change to |newURL| could be a 'navigation' within the -// document (hash change, pushState/replaceState, etc.). This should only be -// used in the context of a URL KVO callback firing, and only if |isLoading| is -// YES for the web view (since if it's not, no guesswork is needed). -- (BOOL)isKVOChangePotentialSameDocumentNavigationToURL:(const GURL&)newURL; // Returns YES if a SafeBrowsing warning is currently displayed within // WKWebView. - (BOOL)isSafeBrowsingWarningDisplayedInWebView; -// Called when a non-document-changing URL change occurs. Updates the -// _documentURL, and informs the superclass of the change. -- (void)URLDidChangeWithoutDocumentChange:(const GURL&)URL; // Returns context for pending navigation that has |URL|. null if there is no // matching pending navigation. - (web::NavigationContextImpl*)contextForPendingMainFrameNavigationWithURL: @@ -922,15 +872,10 @@ @implementation CRWWebController -@synthesize webUsageEnabled = _webUsageEnabled; -@synthesize loadPhase = _loadPhase; -@synthesize webProcessCrashed = _webProcessCrashed; -@synthesize visible = _visible; -@synthesize nativeProvider = _nativeProvider; -@synthesize swipeRecognizerProvider = _swipeRecognizerProvider; -@synthesize webViewProxy = _webViewProxy; -@synthesize allowsBackForwardNavigationGestures = - _allowsBackForwardNavigationGestures; +// Synthesize as it is readonly. +@synthesize touchTrackingRecognizer = _touchTrackingRecognizer; + +#pragma mark - Object lifecycle - (instancetype)initWithWebState:(WebStateImpl*)webState { self = [super init]; @@ -970,38 +915,121 @@ return self; } -- (WebState*)webState { - return _webStateImpl; -} - -- (WebStateImpl*)webStateImpl { - return _webStateImpl; -} - -- (void)clearTransientContentView { - // Early return if there is no transient content view. - if (![_containerView transientContentView]) - return; - - // Remove the transient content view from the hierarchy. - [_containerView clearTransientContentView]; -} - -- (void)showTransientContentView:(CRWContentView*)contentView { - DCHECK(contentView); - DCHECK(contentView.scrollView); - // TODO(crbug.com/556848) Reenable DCHECK when |CRWWebControllerContainerView| - // is restructured so that subviews are not added during |layoutSubviews|. - // DCHECK([contentView.scrollView isDescendantOfView:contentView]); - [_containerView displayTransientContent:contentView]; -} - - (void)dealloc { DCHECK([NSThread isMainThread]); DCHECK(_isBeingDestroyed); // 'close' must have been called already. DCHECK(!_webView); } +#pragma mark - Public property accessors + +- (void)setWebUsageEnabled:(BOOL)enabled { + if (_webUsageEnabled == enabled) + return; + // WKWebView autoreleases its WKProcessPool on removal from superview. + // Deferring WKProcessPool deallocation may lead to issues with cookie + // clearing and and Browsing Data Partitioning implementation. + @autoreleasepool { + if (!enabled) { + [self removeWebView]; + } + } + + _webUsageEnabled = enabled; + + // WKWebView autoreleases its WKProcessPool on removal from superview. + // Deferring WKProcessPool deallocation may lead to issues with cookie + // clearing and and Browsing Data Partitioning implementation. + @autoreleasepool { + [self setNativeControllerWebUsageEnabled:_webUsageEnabled]; + if (enabled) { + // Don't create the web view; let it be lazy created as needed. + } else { + self.webStateImpl->ClearTransientContent(); + _touchTrackingRecognizer.touchTrackingDelegate = nil; + _touchTrackingRecognizer = nil; + _currentURLLoadWasTrigerred = NO; + } + } +} + +- (UIView*)view { + [self ensureContainerViewCreated]; + DCHECK(_containerView); + return _containerView; +} + +- (id<CRWWebViewNavigationProxy>)webViewNavigationProxy { + return static_cast<id<CRWWebViewNavigationProxy>>(self.webView); +} + +- (UIView*)viewForPrinting { + // Printing is not supported for native controllers. + return self.webView; +} + +- (double)loadingProgress { + return [self.webView estimatedProgress]; +} + +- (void)setAllowsBackForwardNavigationGestures: + (BOOL)allowsBackForwardNavigationGestures { + // Store it to an instance variable as well as + // self.webView.allowsBackForwardNavigationGestures because self.webView may + // be nil. When self.webView is nil, it will be set later in -setWebView:. + _allowsBackForwardNavigationGestures = allowsBackForwardNavigationGestures; + self.webView.allowsBackForwardNavigationGestures = + allowsBackForwardNavigationGestures; +} + +#pragma mark - Private properties accessors + +- (UIScrollView*)webScrollView { + return self.webView.scrollView; +} + +- (web::PageDisplayState)pageDisplayState { + web::PageDisplayState displayState; + // If a native controller is present, record its display state instead of that + // of the underlying placeholder webview. + if (self.nativeController) { + if ([self.nativeController respondsToSelector:@selector(contentOffset)]) { + displayState.scroll_state().set_content_offset( + [self.nativeController contentOffset]); + } + if ([self.nativeController respondsToSelector:@selector(contentInset)]) { + displayState.scroll_state().set_content_inset( + [self.nativeController contentInset]); + } + } else if (self.webView) { + displayState.set_scroll_state(web::PageScrollState( + self.scrollPosition, self.webScrollView.contentInset)); + UIScrollView* scrollView = self.webScrollView; + displayState.zoom_state().set_minimum_zoom_scale( + scrollView.minimumZoomScale); + displayState.zoom_state().set_maximum_zoom_scale( + scrollView.maximumZoomScale); + displayState.zoom_state().set_zoom_scale(scrollView.zoomScale); + } + return displayState; +} + +- (void)setPageDisplayState:(web::PageDisplayState)displayState { + if (!displayState.IsValid()) + return; + if (self.webView) { + // Page state is restored after a page load completes. If the user has + // scrolled or changed the zoom scale while the page is still loading, don't + // restore any state since it will confuse the user. + web::PageDisplayState currentPageDisplayState = self.pageDisplayState; + if (currentPageDisplayState.scroll_state() == + _displayStateOnStartLoading.scroll_state() && + !_pageHasZoomed) { + [self applyPageDisplayState:displayState]; + } + } +} + - (id<CRWNativeContent>)nativeController { return [_containerView nativeController]; } @@ -1032,185 +1060,6 @@ }; } -// NativeControllerDelegate method, called to inform that title has changed. -- (void)nativeContent:(id)content titleDidChange:(NSString*)title { - [self setNavigationItemTitle:title]; -} - -- (void)setNativeControllerWebUsageEnabled:(BOOL)webUsageEnabled { - if ([self.nativeController - respondsToSelector:@selector(setWebUsageEnabled:)]) { - [self.nativeController setWebUsageEnabled:webUsageEnabled]; - } -} - -- (void)setWebUsageEnabled:(BOOL)enabled { - if (_webUsageEnabled == enabled) - return; - // WKWebView autoreleases its WKProcessPool on removal from superview. - // Deferring WKProcessPool deallocation may lead to issues with cookie - // clearing and and Browsing Data Partitioning implementation. - @autoreleasepool { - if (!enabled) { - [self removeWebView]; - } - } - - _webUsageEnabled = enabled; - - // WKWebView autoreleases its WKProcessPool on removal from superview. - // Deferring WKProcessPool deallocation may lead to issues with cookie - // clearing and and Browsing Data Partitioning implementation. - @autoreleasepool { - [self setNativeControllerWebUsageEnabled:_webUsageEnabled]; - if (enabled) { - // Don't create the web view; let it be lazy created as needed. - } else { - _webStateImpl->ClearTransientContent(); - _touchTrackingRecognizer.touchTrackingDelegate = nil; - _touchTrackingRecognizer = nil; - _currentURLLoadWasTrigerred = NO; - } - } -} - -- (void)requirePageReconstruction { - // TODO(crbug.com/736103): Removing web view will destroy session history for - // WKBasedNavigationManager. - if (!web::GetWebClient()->IsSlimNavigationManagerEnabled()) - [self removeWebView]; -} - -- (BOOL)isViewAlive { - return !_webProcessCrashed && [_containerView isViewAlive]; -} - -- (BOOL)isSafeBrowsingWarningDisplayedInWebView { - // A SafeBrowsing warning is a UIScrollView that is inserted on top of - // WKWebView's scroll view. This method uses heuristics to detect this view. - // It may break in the future if WebKit's implementation of SafeBrowsing - // warnings changes. - UIView* containingView = _webView.scrollView.superview; - if (!containingView) - return NO; - - UIView* topView = containingView.subviews.lastObject; - - if (topView == _webView.scrollView) - return NO; - - return - [topView isKindOfClass:[UIScrollView class]] && - [NSStringFromClass([topView class]) containsString:@"Warning"] && - topView.subviews.count > 0 && - [topView.subviews[0].subviews.lastObject isKindOfClass:[UIButton class]]; -} - -- (BOOL)contentIsHTML { - if (!_webView) - return NO; - - std::string MIMEType = self.webState->GetContentsMimeType(); - return MIMEType == "text/html" || MIMEType == "application/xhtml+xml" || - MIMEType == "application/xml"; -} - -// Stop doing stuff, especially network stuff. Close the request tracker. -- (void)terminateNetworkActivity { - DCHECK(!_isHalted); - _isHalted = YES; - - // Cancel all outstanding perform requests, and clear anything already queued - // (since this may be called from within the handling loop) to prevent any - // asynchronous JavaScript invocation handling from continuing. - [NSObject cancelPreviousPerformRequestsWithTarget:self]; -} - -- (void)dismissModals { - if ([self.nativeController respondsToSelector:@selector(dismissModals)]) - [self.nativeController dismissModals]; -} - -// Caller must reset the delegate before calling. -- (void)close { - _webStateImpl->CancelDialogs(); - - _SSLStatusUpdater = nil; - - self.nativeProvider = nil; - self.swipeRecognizerProvider = nil; - if ([self.nativeController respondsToSelector:@selector(close)]) - [self.nativeController close]; - - if (!_isHalted) { - [self terminateNetworkActivity]; - } - - // Mark the destruction sequence has started, in case someone else holds a - // strong reference and tries to continue using the tab. - DCHECK(!_isBeingDestroyed); - _isBeingDestroyed = YES; - - // Remove the web view now. Otherwise, delegate callbacks occur. - [self removeWebView]; - - // Explicitly reset content to clean up views and avoid dangling KVO - // observers. - [_containerView resetContent]; - - _webStateImpl = nullptr; - - DCHECK(!_webView); - // TODO(crbug.com/662860): Don't set the delegate to nil. - [_containerView setDelegate:nil]; - if ([self.nativeController respondsToSelector:@selector(setDelegate:)]) { - [self.nativeController setDelegate:nil]; - } - _touchTrackingRecognizer.touchTrackingDelegate = nil; - [[_webViewProxy scrollViewProxy] removeObserver:self]; - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -- (CGPoint)scrollPosition { - return self.webScrollView.contentOffset; -} - -- (GURL)currentURLWithTrustLevel:(web::URLVerificationTrustLevel*)trustLevel { - DCHECK(trustLevel) << "Verification of the trustLevel state is mandatory"; - - // The web view URL is the current URL only if it is neither a placeholder URL - // (used to hold WKBackForwardListItem for WebUI and Native Content views) nor - // a restore_session.html (used to replay session history in WKWebView). - // TODO(crbug.com/738020): Investigate if this method is still needed and if - // it can be implemented using NavigationManager API after removal of legacy - // navigation stack. - GURL webViewURL = net::GURLWithNSURL(_webView.URL); - if (_webView && !IsWKInternalUrl(webViewURL)) { - return [self webURLWithTrustLevel:trustLevel]; - } - // Any non-web URL source is trusted. - *trustLevel = web::URLVerificationTrustLevel::kAbsolute; - if (self.nativeController) { - if ([self.nativeController respondsToSelector:@selector(virtualURL)]) { - return [self.nativeController virtualURL]; - } else { - return [self.nativeController url]; - } - } - web::NavigationItem* item = - self.navigationManagerImpl - ->GetLastCommittedItemInCurrentOrRestoredSession(); - return item ? item->GetVirtualURL() : GURL::EmptyGURL(); -} - -- (WKWebView*)webView { - return _webView; -} - -- (UIScrollView*)webScrollView { - return [_webView scrollView]; -} - - (GURL)currentURL { web::URLVerificationTrustLevel trustLevel = web::URLVerificationTrustLevel::kNone; @@ -1248,20 +1097,708 @@ web::ReferrerPolicyAlways); } +- (BOOL)userClickedRecently { + // Scrolling generates a pair of touch on/off event which causes + // _lastUserInteraction to register that there was user interaction. + // Checks for scrolling first to override time-based click heuristics. + BOOL scrolling = [[self webScrollView] isDragging] || + [[self webScrollView] isDecelerating]; + if (scrolling) + return NO; + if (!_lastUserInteraction) + return NO; + return _clickInProgress || + ((CFAbsoluteTimeGetCurrent() - _lastUserInteraction->time) < + kMaximumDelayForUserInteractionInSeconds); +} + +- (web::UserAgentType)userAgentType { + web::NavigationItem* item = self.currentNavItem; + return item ? item->GetUserAgentType() : web::UserAgentType::MOBILE; +} + +- (web::MojoFacade*)mojoFacade { + if (!_mojoFacade) { + service_manager::mojom::InterfaceProvider* interfaceProvider = + self.webStateImpl->GetWebStateInterfaceProvider(); + _mojoFacade.reset(new web::MojoFacade(interfaceProvider, self)); + } + return _mojoFacade.get(); +} + +- (void)setUserInteractionRegistered:(BOOL)flag { + _userInteractionRegistered = flag; + if (flag) + _interactionRegisteredSinceLastURLChange = YES; +} + +- (WebState*)webState { + return _webStateImpl; +} + +- (CGPoint)scrollPosition { + return self.webScrollView.contentOffset; +} + +- (CRWTouchTrackingRecognizer*)touchTrackingRecognizer { + if (!_touchTrackingRecognizer) { + _touchTrackingRecognizer = + [[CRWTouchTrackingRecognizer alloc] initWithDelegate:self]; + } + return _touchTrackingRecognizer; +} + +#pragma mark Session Information + +- (CRWSessionController*)sessionController { + NavigationManagerImpl* navigationManager = self.navigationManagerImpl; + return navigationManager ? navigationManager->GetSessionController() : nil; +} + +- (NavigationManagerImpl*)navigationManagerImpl { + return self.webStateImpl ? &(self.webStateImpl->GetNavigationManagerImpl()) + : nil; +} + +- (BOOL)hasOpener { + return self.webStateImpl ? self.webStateImpl->HasOpener() : NO; +} + +- (web::NavigationItemImpl*)currentNavItem { + return self.navigationManagerImpl + ? self.navigationManagerImpl->GetCurrentItemImpl() + : nullptr; +} + +- (ui::PageTransition)currentTransition { + if (self.currentNavItem) + return self.currentNavItem->GetTransitionType(); + else + return ui::PageTransitionFromInt(0); +} + +- (web::Referrer)currentNavItemReferrer { + web::NavigationItem* currentItem = self.currentNavItem; + return currentItem ? currentItem->GetReferrer() : web::Referrer(); +} + +- (NSDictionary*)currentHTTPHeaders { + web::NavigationItem* currentItem = self.currentNavItem; + return currentItem ? currentItem->GetHttpRequestHeaders() : nil; +} + +#pragma mark - ** Public Methods ** + +#pragma mark - Header public methods + +- (void)showTransientContentView:(CRWContentView*)contentView { + DCHECK(contentView); + DCHECK(contentView.scrollView); + // TODO(crbug.com/556848) Reenable DCHECK when |CRWWebControllerContainerView| + // is restructured so that subviews are not added during |layoutSubviews|. + // DCHECK([contentView.scrollView isDescendantOfView:contentView]); + [_containerView displayTransientContent:contentView]; +} + +- (void)clearTransientContentView { + // Early return if there is no transient content view. + if (![_containerView transientContentView]) + return; + + // Remove the transient content view from the hierarchy. + [_containerView clearTransientContentView]; +} + +// Stop doing stuff, especially network stuff. Close the request tracker. +- (void)terminateNetworkActivity { + DCHECK(!_isHalted); + _isHalted = YES; + + // Cancel all outstanding perform requests, and clear anything already queued + // (since this may be called from within the handling loop) to prevent any + // asynchronous JavaScript invocation handling from continuing. + [NSObject cancelPreviousPerformRequestsWithTarget:self]; +} + +- (void)dismissModals { + if ([self.nativeController respondsToSelector:@selector(dismissModals)]) + [self.nativeController dismissModals]; +} + +// Caller must reset the delegate before calling. +- (void)close { + self.webStateImpl->CancelDialogs(); + + _SSLStatusUpdater = nil; + + self.nativeProvider = nil; + self.swipeRecognizerProvider = nil; + if ([self.nativeController respondsToSelector:@selector(close)]) + [self.nativeController close]; + + if (!_isHalted) { + [self terminateNetworkActivity]; + } + + // Mark the destruction sequence has started, in case someone else holds a + // strong reference and tries to continue using the tab. + DCHECK(!_isBeingDestroyed); + _isBeingDestroyed = YES; + + // Remove the web view now. Otherwise, delegate callbacks occur. + [self removeWebView]; + + // Explicitly reset content to clean up views and avoid dangling KVO + // observers. + [_containerView resetContent]; + + _webStateImpl = nullptr; + + DCHECK(!self.webView); + // TODO(crbug.com/662860): Don't set the delegate to nil. + [_containerView setDelegate:nil]; + if ([self.nativeController respondsToSelector:@selector(setDelegate:)]) { + [self.nativeController setDelegate:nil]; + } + _touchTrackingRecognizer.touchTrackingDelegate = nil; + [[_webViewProxy scrollViewProxy] removeObserver:self]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (BOOL)isViewAlive { + return !_webProcessCrashed && [_containerView isViewAlive]; +} + +- (BOOL)contentIsHTML { + if (!self.webView) + return NO; + + std::string MIMEType = self.webState->GetContentsMimeType(); + return MIMEType == "text/html" || MIMEType == "application/xhtml+xml" || + MIMEType == "application/xml"; +} + +- (GURL)currentURLWithTrustLevel:(web::URLVerificationTrustLevel*)trustLevel { + DCHECK(trustLevel) << "Verification of the trustLevel state is mandatory"; + + // The web view URL is the current URL only if it is neither a placeholder URL + // (used to hold WKBackForwardListItem for WebUI and Native Content views) nor + // a restore_session.html (used to replay session history in WKWebView). + // TODO(crbug.com/738020): Investigate if this method is still needed and if + // it can be implemented using NavigationManager API after removal of legacy + // navigation stack. + GURL webViewURL = net::GURLWithNSURL(self.webView.URL); + if (self.webView && !IsWKInternalUrl(webViewURL)) { + return [self webURLWithTrustLevel:trustLevel]; + } + // Any non-web URL source is trusted. + *trustLevel = web::URLVerificationTrustLevel::kAbsolute; + if (self.nativeController) { + if ([self.nativeController respondsToSelector:@selector(virtualURL)]) { + return [self.nativeController virtualURL]; + } else { + return [self.nativeController url]; + } + } + web::NavigationItem* item = + self.navigationManagerImpl + ->GetLastCommittedItemInCurrentOrRestoredSession(); + return item ? item->GetVirtualURL() : GURL::EmptyGURL(); +} + +- (void)reloadWithRendererInitiatedNavigation:(BOOL)rendererInitiated { + // Clear last user interaction. + // TODO(crbug.com/546337): Move to after the load commits, in the subclass + // implementation. This will be inaccurate if the reload fails or is + // cancelled. + _lastUserInteraction = nullptr; + base::RecordAction(base::UserMetricsAction("Reload")); + GURL URL = self.currentNavItem->GetURL(); + if ([self shouldLoadURLInNativeView:URL]) { + std::unique_ptr<web::NavigationContextImpl> navigationContext = [self + registerLoadRequestForURL:URL + referrer:self.currentNavItemReferrer + transition:ui::PageTransition::PAGE_TRANSITION_RELOAD + sameDocumentNavigation:NO + hasUserGesture:YES + rendererInitiated:rendererInitiated + placeholderNavigation:NO]; + self.webStateImpl->OnNavigationStarted(navigationContext.get()); + [self didStartLoading]; + self.navigationManagerImpl->CommitPendingItem( + navigationContext->ReleaseItem()); + [self.nativeController reload]; + navigationContext->SetHasCommitted(true); + self.webStateImpl->OnNavigationFinished(navigationContext.get()); + [self loadCompleteWithSuccess:YES forContext:nullptr]; + } else { + web::NavigationItem* transientItem = + self.navigationManagerImpl->GetTransientItem(); + if (transientItem) { + // If there's a transient item, a reload is considered a new navigation to + // the transient item's URL (as on other platforms). + NavigationManager::WebLoadParams reloadParams(transientItem->GetURL()); + reloadParams.transition_type = ui::PAGE_TRANSITION_RELOAD; + reloadParams.extra_headers = + [transientItem->GetHttpRequestHeaders() copy]; + self.webState->GetNavigationManager()->LoadURLWithParams(reloadParams); + } else { + self.currentNavItem->SetTransitionType( + ui::PageTransition::PAGE_TRANSITION_RELOAD); + if (web::GetWebClient()->IsSlimNavigationManagerEnabled() && + !web::GetWebClient()->IsAppSpecificURL( + net::GURLWithNSURL(self.webView.URL))) { + // New navigation manager can delegate directly to WKWebView to reload + // for non-app-specific URLs. The necessary navigation states will be + // updated in WKNavigationDelegate callbacks. + WKNavigation* navigation = [self.webView reload]; + [_navigationStates setState:web::WKNavigationState::REQUESTED + forNavigation:navigation]; + std::unique_ptr<web::NavigationContextImpl> navigationContext = [self + registerLoadRequestForURL:URL + referrer:self.currentNavItemReferrer + transition:ui::PageTransition::PAGE_TRANSITION_RELOAD + sameDocumentNavigation:NO + hasUserGesture:YES + rendererInitiated:rendererInitiated + placeholderNavigation:NO]; + [_navigationStates setContext:std::move(navigationContext) + forNavigation:navigation]; + } else { + [self loadCurrentURLWithRendererInitiatedNavigation:rendererInitiated]; + } + } + } +} + +- (void)stopLoading { + _stoppedWKNavigation = [_navigationStates lastAddedNavigation]; + + base::RecordAction(base::UserMetricsAction("Stop")); + // Discard the pending and transient entried before notifying the tab model + // observers of the change via |-abortLoad|. + self.navigationManagerImpl->DiscardNonCommittedItems(); + [self abortLoad]; + web::NavigationItem* item = self.currentNavItem; + GURL navigationURL = item ? item->GetVirtualURL() : GURL::EmptyGURL(); + // If discarding the non-committed entries results in an app-specific URL, + // reload it in its native view. + if (!self.nativeController && + [self shouldLoadURLInNativeView:navigationURL]) { + // RendererInitiated flag is meaningless for showing previous native + // content page. RendererInitiated is used as less previledged. + [self loadCurrentURLInNativeViewWithRendererInitiatedNavigation:YES]; + } +} + +- (void)loadCurrentURLWithRendererInitiatedNavigation:(BOOL)rendererInitiated { + // If the content view doesn't exist, the tab has either been evicted, or + // never displayed. Bail, and let the URL be loaded when the tab is shown. + if (!_containerView) + return; + + // WKBasedNavigationManagerImpl needs WKWebView to load native views, but + // WKWebView cannot be created while web usage is disabled to avoid breaking + // clearing browser data. Bail now and let the URL be loaded when web + // usage is enabled again. This can happen when purging web pages when an + // interstitial is presented over a native view. See https://crbug.com/865985 + // for details. + if (web::GetWebClient()->IsSlimNavigationManagerEnabled() && + !_webUsageEnabled) + return; + + _currentURLLoadWasTrigerred = YES; + + // Reset current WebUI if one exists. + [self clearWebUI]; + + // Abort any outstanding page load. This ensures the delegate gets informed + // about the outgoing page, and further messages from the page are suppressed. + if (_loadPhase != web::PAGE_LOADED) + [self abortLoad]; + + DCHECK(!_isHalted); + self.webStateImpl->ClearTransientContent(); + + web::NavigationItem* item = self.currentNavItem; + const GURL currentURL = item ? item->GetURL() : GURL::EmptyGURL(); + const bool isCurrentURLAppSpecific = + web::GetWebClient()->IsAppSpecificURL(currentURL); + // If it's a chrome URL, but not a native one, create the WebUI instance. + if (isCurrentURLAppSpecific && + ![_nativeProvider hasControllerForURL:currentURL]) { + if (!(item->GetTransitionType() & ui::PAGE_TRANSITION_TYPED || + item->GetTransitionType() & ui::PAGE_TRANSITION_AUTO_BOOKMARK) && + self.hasOpener) { + // WebUI URLs can not be opened by DOM to prevent cross-site scripting as + // they have increased power. WebUI URLs may only be opened when the user + // types in the URL or use bookmarks. + self.navigationManagerImpl->DiscardNonCommittedItems(); + return; + } else { + [self createWebUIForURL:currentURL]; + } + } + + // Loading a new url, must check here if it's a native chrome URL and + // replace the appropriate view if so, or transition back to a web view from + // a native view. + if ([self shouldLoadURLInNativeView:currentURL]) { + [self loadCurrentURLInNativeViewWithRendererInitiatedNavigation: + rendererInitiated]; + } else if (web::GetWebClient()->IsSlimNavigationManagerEnabled() && + isCurrentURLAppSpecific && self.webStateImpl->HasWebUI() && + !web::features::WebUISchemeHandlingEnabled()) { + [self loadPlaceholderInWebViewForURL:currentURL + rendererInitiated:rendererInitiated + forContext:nullptr]; + } else { + [self loadCurrentURLInWebView]; + } +} + +- (void)loadCurrentURLIfNecessary { + if (_webProcessCrashed) { + [self loadCurrentURLWithRendererInitiatedNavigation:NO]; + } else if (!_currentURLLoadWasTrigerred) { + [self ensureContainerViewCreated]; + + // This method reloads last committed item, so make than item also pending. + self.sessionController.pendingItemIndex = + self.sessionController.lastCommittedItemIndex; + + // TODO(crbug.com/796608): end the practice of calling |loadCurrentURL| + // when it is possible there is no current URL. If the call performs + // necessary initialization, break that out. + [self loadCurrentURLWithRendererInitiatedNavigation:NO]; + } +} + +- (void)loadData:(NSData*)data + MIMEType:(NSString*)MIMEType + forURL:(const GURL&)URL { + web::NavigationItemImpl* item = + self.navigationManagerImpl->GetLastCommittedItemImpl(); + auto navigationContext = web::NavigationContextImpl::CreateNavigationContext( + self.webStateImpl, URL, + /*has_user_gesture=*/true, item->GetTransitionType(), + /*is_renderer_initiated=*/false); + _loadPhase = web::LOAD_REQUESTED; + navigationContext->SetNavigationItemUniqueID(item->GetUniqueID()); + + item->SetNavigationInitiationType( + web::NavigationInitiationType::BROWSER_INITIATED); + // The error_retry_state_machine may still be in the + // |kDisplayingWebErrorForFailedNavigation| from the navigation that is being + // replaced. As the navigation is now successful, the error can be cleared. + item->error_retry_state_machine().SetNoNavigationError(); + // The load data call will replace the current navigation and the webView URL + // of the navigation will be replaced by |URL|. Set the URL of the + // navigationItem to keep them synced. + // Note: it is possible that the URL in item already match |url|. But item can + // also contain a placeholder URL intended to be replaced. + item->SetURL(URL); + navigationContext->SetMimeType(MIMEType); + if (item->GetUserAgentType() == web::UserAgentType::NONE && + web::wk_navigation_util::URLNeedsUserAgentType(URL)) { + item->SetUserAgentType(web::UserAgentType::MOBILE); + } + + WKNavigation* navigation = + [self.webView loadData:data + MIMEType:MIMEType + characterEncodingName:base::SysUTF8ToNSString(base::kCodepageUTF8) + baseURL:net::NSURLWithGURL(URL)]; + + [_navigationStates setContext:std::move(navigationContext) + forNavigation:navigation]; + [_navigationStates setState:web::WKNavigationState::REQUESTED + forNavigation:navigation]; +} + +- (void)loadHTML:(NSString*)HTML forAppSpecificURL:(const GURL&)URL { + CHECK(web::GetWebClient()->IsAppSpecificURL(URL)); + [self loadHTML:HTML forURL:URL]; +} + +- (void)executeUserJavaScript:(NSString*)script + completionHandler:(web::JavaScriptResultBlock)completion { + // For security reasons, executing JavaScript on pages with app-specific URLs + // is not allowed, because those pages may have elevated privileges. + GURL lastCommittedURL = self.webState->GetLastCommittedURL(); + if (web::GetWebClient()->IsAppSpecificURL(lastCommittedURL)) { + if (completion) { + dispatch_async(dispatch_get_main_queue(), ^{ + NSError* error = [[NSError alloc] + initWithDomain:web::kJSEvaluationErrorDomain + code:web::JS_EVALUATION_ERROR_CODE_NO_WEB_VIEW + userInfo:nil]; + completion(nil, error); + }); + } + return; + } + + [self touched:YES]; + [self executeJavaScript:script completionHandler:completion]; +} + +- (void)requirePageReconstruction { + // TODO(crbug.com/736103): Removing web view will destroy session history for + // WKBasedNavigationManager. + if (!web::GetWebClient()->IsSlimNavigationManagerEnabled()) + [self removeWebView]; +} + +- (void)recordStateInHistory { + // Only record the state if: + // - the current NavigationItem's URL matches the current URL, and + // - the user has interacted with the page. + web::NavigationItem* item = self.currentNavItem; + if (item && item->GetURL() == [self currentURL] && + self.userInteractionRegistered) { + item->SetPageDisplayState(self.pageDisplayState); + } +} + +- (void)wasShown { + self.visible = YES; + if ([self.nativeController respondsToSelector:@selector(wasShown)]) { + [self.nativeController wasShown]; + } +} + +- (void)wasHidden { + self.visible = NO; + if (_isHalted) + return; + [self recordStateInHistory]; + if ([self.nativeController respondsToSelector:@selector(wasHidden)]) { + [self.nativeController wasHidden]; + } +} + +- (void)addGestureRecognizerToWebView:(UIGestureRecognizer*)recognizer { + if ([_gestureRecognizers containsObject:recognizer]) + return; + + [self.webView addGestureRecognizer:recognizer]; + [_gestureRecognizers addObject:recognizer]; +} + +- (void)removeGestureRecognizerFromWebView:(UIGestureRecognizer*)recognizer { + if (![_gestureRecognizers containsObject:recognizer]) + return; + + [self.webView removeGestureRecognizer:recognizer]; + [_gestureRecognizers removeObject:recognizer]; +} + +- (void)didFinishGoToIndexSameDocumentNavigationWithType: + (web::NavigationInitiationType)type + hasUserGesture:(BOOL)hasUserGesture { + web::NavigationItem* item = + self.webStateImpl->GetNavigationManager()->GetLastCommittedItem(); + GURL URL = item->GetVirtualURL(); + std::unique_ptr<web::NavigationContextImpl> context = + web::NavigationContextImpl::CreateNavigationContext( + self.webStateImpl, URL, hasUserGesture, + static_cast<ui::PageTransition>( + item->GetTransitionType() | + ui::PageTransition::PAGE_TRANSITION_FORWARD_BACK), + type == web::NavigationInitiationType::RENDERER_INITIATED); + context->SetIsSameDocument(true); + self.webStateImpl->SetIsLoading(true); + self.webStateImpl->OnNavigationStarted(context.get()); + [self updateHTML5HistoryState]; + [self setDocumentURL:URL context:context.get()]; + context->SetHasCommitted(true); + self.webStateImpl->OnNavigationFinished(context.get()); + [self didFinishWithURL:URL loadSuccess:YES context:context.get()]; +} + +- (void)goToBackForwardListItem:(WKBackForwardListItem*)wk_item + navigationItem:(web::NavigationItem*)item + navigationInitiationType:(web::NavigationInitiationType)type + hasUserGesture:(BOOL)hasUserGesture { + WKNavigation* navigation = [self.webView goToBackForwardListItem:wk_item]; + + GURL URL = net::GURLWithNSURL(wk_item.URL); + if (IsPlaceholderUrl(URL)) { + // No need to create navigation context for placeholder back forward + // navigations. Future callbacks do not expect that context will exist. + return; + } + + // This navigation can be an iframe navigation, but it's not possible to + // distinguish it from the main frame navigation, so context still has to be + // created. + std::unique_ptr<web::NavigationContextImpl> context = + web::NavigationContextImpl::CreateNavigationContext( + self.webStateImpl, URL, hasUserGesture, + static_cast<ui::PageTransition>( + item->GetTransitionType() | + ui::PageTransition::PAGE_TRANSITION_FORWARD_BACK), + type == web::NavigationInitiationType::RENDERER_INITIATED); + context->SetNavigationItemUniqueID(item->GetUniqueID()); + if (!navigation) { + // goToBackForwardListItem: returns nil for same-document back forward + // navigations. + context->SetIsSameDocument(true); + } else { + self.webStateImpl->SetIsLoading(true); + _loadPhase = web::LOAD_REQUESTED; + } + + web::WKBackForwardListItemHolder* holder = + web::WKBackForwardListItemHolder::FromNavigationItem(item); + holder->set_navigation_type(WKNavigationTypeBackForward); + context->SetIsPost((holder && [holder->http_method() isEqual:@"POST"]) || + item->HasPostData()); + + if (holder) { + context->SetMimeType(holder->mime_type()); + } + + [_navigationStates setContext:std::move(context) forNavigation:navigation]; + [_navigationStates setState:web::WKNavigationState::REQUESTED + forNavigation:navigation]; +} + +- (void)takeSnapshotWithRect:(CGRect)rect + completion:(void (^)(UIImage*))completion { + if (@available(iOS 11, *)) { + if (self.webView) { + WKSnapshotConfiguration* configuration = + [[WKSnapshotConfiguration alloc] init]; + configuration.rect = [self.webView convertRect:rect fromView:self.view]; + __weak CRWWebController* weakSelf = self; + [self.webView + takeSnapshotWithConfiguration:configuration + completionHandler:^(UIImage* snapshot, NSError* error) { + // Pass nil to the completion block if there is an error + // or if the web view has been removed before the + // snapshot is finished. |snapshot| can sometimes be + // corrupt if it's sent due to the WKWebView's + // deallocation, so callbacks received after + // |-removeWebView| are ignored to prevent crashing. + if (error || !weakSelf.webView) { + if (error) { + DLOG(ERROR) << "WKWebView snapshot error: " + << error.description; + } + completion(nil); + } else { + completion(snapshot); + } + }]; + return; + } + } + dispatch_async(dispatch_get_main_queue(), ^{ + completion(nil); + }); +} + +#pragma mark - CRWJSInjectionEvaluator (Public) + +- (void)executeJavaScript:(NSString*)script + completionHandler:(web::JavaScriptResultBlock)completionHandler { + NSString* safeScript = [self scriptByAddingWindowIDCheckForScript:script]; + web::ExecuteJavaScript(self.webView, safeScript, completionHandler); +} + +- (BOOL)scriptHasBeenInjectedForClass:(Class)injectionManagerClass { + return [_injectedScriptManagers containsObject:injectionManagerClass]; +} + +- (void)injectScript:(NSString*)script forClass:(Class)JSInjectionManagerClass { + DCHECK(script.length); + // Script execution is an asynchronous operation which may pass sensitive + // data to the page. executeJavaScript:completionHandler makes sure that + // receiver page did not change by checking its window id. + // |[self.webView executeJavaScript:completionHandler:]| is not used here + // because it does not check that page is the same. + [self executeJavaScript:script completionHandler:nil]; + [_injectedScriptManagers addObject:JSInjectionManagerClass]; +} + +#pragma mark - CRWSessionControllerDelegate (Public) + +- (web::NavigationItemImpl*)pendingItemForSessionController: + (CRWSessionController*)sessionController { + WKNavigation* navigation = + [_navigationStates lastNavigationWithPendingItemInNavigationContext]; + if (!navigation) + return nullptr; + return [_navigationStates contextForNavigation:navigation] -> GetItem(); +} + +#pragma mark - CRWTouchTrackingDelegate (Public) + +- (void)touched:(BOOL)touched { + _clickInProgress = touched; + if (touched) { + self.userInteractionRegistered = YES; + _userInteractedWithWebController = YES; + if (_isBeingDestroyed) + return; + const NavigationManagerImpl* navigationManager = self.navigationManagerImpl; + GURL mainDocumentURL = + navigationManager->GetLastCommittedItem() + ? navigationManager->GetLastCommittedItem()->GetURL() + : [self currentURL]; + _lastUserInteraction = + std::make_unique<UserInteractionEvent>(mainDocumentURL); + } +} + +#pragma mark - ** Private Methods ** + +#pragma mark - + +- (void)setNativeControllerWebUsageEnabled:(BOOL)webUsageEnabled { + if ([self.nativeController + respondsToSelector:@selector(setWebUsageEnabled:)]) { + [self.nativeController setWebUsageEnabled:webUsageEnabled]; + } +} + +- (BOOL)isSafeBrowsingWarningDisplayedInWebView { + // A SafeBrowsing warning is a UIScrollView that is inserted on top of + // WKWebView's scroll view. This method uses heuristics to detect this view. + // It may break in the future if WebKit's implementation of SafeBrowsing + // warnings changes. + UIView* containingView = self.webView.scrollView.superview; + if (!containingView) + return NO; + + UIView* topView = containingView.subviews.lastObject; + + if (topView == self.webView.scrollView) + return NO; + + return + [topView isKindOfClass:[UIScrollView class]] && + [NSStringFromClass([topView class]) containsString:@"Warning"] && + topView.subviews.count > 0 && + [topView.subviews[0].subviews.lastObject isKindOfClass:[UIButton class]]; +} + - (void)pushStateWithPageURL:(const GURL&)pageURL stateObject:(NSString*)stateObject transition:(ui::PageTransition)transition hasUserGesture:(BOOL)hasUserGesture { std::unique_ptr<web::NavigationContextImpl> context = web::NavigationContextImpl::CreateNavigationContext( - _webStateImpl, pageURL, hasUserGesture, transition, + self.webStateImpl, pageURL, hasUserGesture, transition, /*is_renderer_initiated=*/true); context->SetIsSameDocument(true); - _webStateImpl->OnNavigationStarted(context.get()); + self.webStateImpl->OnNavigationStarted(context.get()); self.navigationManagerImpl->AddPushStateItemIfNecessary(pageURL, stateObject, transition); context->SetHasCommitted(true); - _webStateImpl->OnNavigationFinished(context.get()); + self.webStateImpl->OnNavigationFinished(context.get()); self.userInteractionRegistered = NO; } @@ -1270,15 +1807,15 @@ hasUserGesture:(BOOL)hasUserGesture { std::unique_ptr<web::NavigationContextImpl> context = web::NavigationContextImpl::CreateNavigationContext( - _webStateImpl, pageURL, hasUserGesture, + self.webStateImpl, pageURL, hasUserGesture, ui::PageTransition::PAGE_TRANSITION_CLIENT_REDIRECT, /*is_renderer_initiated=*/true); context->SetIsSameDocument(true); - _webStateImpl->OnNavigationStarted(context.get()); + self.webStateImpl->OnNavigationStarted(context.get()); self.navigationManagerImpl->UpdateCurrentItemForReplaceState(pageURL, stateObject); context->SetHasCommitted(true); - _webStateImpl->OnNavigationFinished(context.get()); + self.webStateImpl->OnNavigationFinished(context.get()); } - (void)setDocumentURL:(const GURL&)newURL @@ -1290,10 +1827,10 @@ if (web::GetWebClient()->IsSlimNavigationManagerEnabled() && context && !context->IsLoadingHtmlString() && !context->IsLoadingErrorPage() && !IsWKInternalUrl(newURL) && !newURL.SchemeIs(url::kAboutScheme) && - _webView) { + self.webView) { GURL documentOrigin = newURL.GetOrigin(); web::NavigationItem* committedItem = - _webStateImpl->GetNavigationManager()->GetLastCommittedItem(); + self.webStateImpl->GetNavigationManager()->GetLastCommittedItem(); GURL committedOrigin = committedItem ? committedItem->GetURL().GetOrigin() : GURL::EmptyGURL(); DCHECK_EQ(documentOrigin, committedOrigin) @@ -1317,7 +1854,7 @@ return; item->SetTitle(base::SysNSStringToUTF16(title)); - _webStateImpl->OnTitleChanged(); + self.webStateImpl->OnTitleChanged(); } - (BOOL)isCurrentNavigationItemPOST { @@ -1347,31 +1884,12 @@ - (BOOL)isBackForwardListItemValid:(WKBackForwardListItem*)item { // The current back-forward list item MUST be in the WKWebView's back-forward // list to be valid. - WKBackForwardList* list = [_webView backForwardList]; + WKBackForwardList* list = self.webView.backForwardList; return list.currentItem == item || [list.forwardList indexOfObject:item] != NSNotFound || [list.backList indexOfObject:item] != NSNotFound; } -- (UIView*)view { - [self ensureContainerViewCreated]; - DCHECK(_containerView); - return _containerView; -} - -- (id<CRWWebViewNavigationProxy>)webViewNavigationProxy { - return static_cast<id<CRWWebViewNavigationProxy>>(self.webView); -} - -- (UIView*)viewForPrinting { - // Printing is not supported for native controllers. - return _webView; -} - -- (double)loadingProgress { - return [_webView estimatedProgress]; -} - - (std::unique_ptr<web::NavigationContextImpl>) registerLoadRequestForURL:(const GURL&)URL sameDocumentNavigation:(BOOL)sameDocumentNavigation @@ -1388,9 +1906,9 @@ if (web::GetWebClient()->IsSlimNavigationManagerEnabled() && navigationType == WKNavigationTypeBackForward && - _webView.backForwardList.currentItem) { + self.webView.backForwardList.currentItem) { web::NavigationItem* currentItem = [[CRWNavigationItemHolder - holderForBackForwardListItem:_webView.backForwardList.currentItem] + holderForBackForwardListItem:self.webView.backForwardList.currentItem] navigationItem]; if (currentItem) { transition = ui::PageTransitionFromInt(transition | @@ -1475,7 +1993,7 @@ std::unique_ptr<web::NavigationContextImpl> context = web::NavigationContextImpl::CreateNavigationContext( - _webStateImpl, requestURL, hasUserGesture, transition, + self.webStateImpl, requestURL, hasUserGesture, transition, rendererInitiated); context->SetPlaceholderNavigation(placeholderNavigation); @@ -1492,7 +2010,7 @@ context->SetIsSameDocument(sameDocumentNavigation); if (!IsWKInternalUrl(requestURL) && !placeholderNavigation) { - _webStateImpl->SetIsLoading(true); + self.webStateImpl->SetIsLoading(true); // WKBasedNavigationManager triggers HTML load when placeholder navigation // finishes. @@ -1546,48 +2064,6 @@ } } -- (void)loadData:(NSData*)data - MIMEType:(NSString*)MIMEType - forURL:(const GURL&)URL { - web::NavigationItemImpl* item = - self.navigationManagerImpl->GetLastCommittedItemImpl(); - auto navigationContext = web::NavigationContextImpl::CreateNavigationContext( - _webStateImpl, URL, - /*has_user_gesture=*/true, item->GetTransitionType(), - /*is_renderer_initiated=*/false); - _loadPhase = web::LOAD_REQUESTED; - navigationContext->SetNavigationItemUniqueID(item->GetUniqueID()); - - item->SetNavigationInitiationType( - web::NavigationInitiationType::BROWSER_INITIATED); - // The error_retry_state_machine may still be in the - // |kDisplayingWebErrorForFailedNavigation| from the navigation that is being - // replaced. As the navigation is now successful, the error can be cleared. - item->error_retry_state_machine().SetNoNavigationError(); - // The load data call will replace the current navigation and the webView URL - // of the navigation will be replaced by |URL|. Set the URL of the - // navigationItem to keep them synced. - // Note: it is possible that the URL in item already match |url|. But item can - // also contain a placeholder URL intended to be replaced. - item->SetURL(URL); - navigationContext->SetMimeType(MIMEType); - if (item->GetUserAgentType() == web::UserAgentType::NONE && - web::wk_navigation_util::URLNeedsUserAgentType(URL)) { - item->SetUserAgentType(web::UserAgentType::MOBILE); - } - - WKNavigation* navigation = - [_webView loadData:data - MIMEType:MIMEType - characterEncodingName:base::SysUTF8ToNSString(base::kCodepageUTF8) - baseURL:net::NSURLWithGURL(URL)]; - - [_navigationStates setContext:std::move(navigationContext) - forNavigation:navigation]; - [_navigationStates setState:web::WKNavigationState::REQUESTED - forNavigation:navigation]; -} - // TODO(crbug.com/788465): Verify that the history state management here are not // needed for WKBasedNavigationManagerImpl and delete this method. The // OnNavigationItemCommitted() call is likely the only thing that needs to be @@ -1689,8 +2165,8 @@ // session history and UI. if (!targetURL.is_valid()) { [self didFinishWithURL:targetURL loadSuccess:NO context:nullptr]; - _webStateImpl->SetIsLoading(false); - _webStateImpl->OnPageLoaded(targetURL, NO); + self.webStateImpl->SetIsLoading(false); + self.webStateImpl->OnPageLoaded(targetURL, NO); return; } @@ -1703,6 +2179,228 @@ [self loadRequestForCurrentNavigationItem]; } +- (void)loadRequestForCurrentNavigationItem { + DCHECK(self.webView); + DCHECK(self.currentNavItem); + // If a load is kicked off on a WKWebView with a frame whose size is {0, 0} or + // that has a negative dimension for a size, rendering issues occur that + // manifest in erroneous scrolling and tap handling (crbug.com/574996, + // crbug.com/577793). + DCHECK_GT(CGRectGetWidth(self.webView.frame), 0.0); + DCHECK_GT(CGRectGetHeight(self.webView.frame), 0.0); + + // If the current item uses a different user agent from that is currently used + // in the web view, update |customUserAgent| property, which will be used by + // the next request sent by this web view. + web::UserAgentType itemUserAgentType = + self.currentNavItem->GetUserAgentType(); + if (itemUserAgentType != web::UserAgentType::NONE) { + NSString* userAgentString = base::SysUTF8ToNSString( + web::GetWebClient()->GetUserAgent(itemUserAgentType)); + if (![self.webView.customUserAgent isEqualToString:userAgentString]) { + self.webView.customUserAgent = userAgentString; + } + } + + web::WKBackForwardListItemHolder* holder = + [self currentBackForwardListItemHolder]; + BOOL repostedForm = + [holder->http_method() isEqual:@"POST"] && + (holder->navigation_type() == WKNavigationTypeFormResubmitted || + holder->navigation_type() == WKNavigationTypeFormSubmitted); + web::NavigationItemImpl* currentItem = self.currentNavItem; + NSData* POSTData = currentItem->GetPostData(); + NSMutableURLRequest* request = [self requestForCurrentNavigationItem]; + + BOOL sameDocumentNavigation = currentItem->IsCreatedFromPushState() || + currentItem->IsCreatedFromHashChange(); + + if (holder->back_forward_list_item()) { + // Check if holder's WKBackForwardListItem still correctly represents + // navigation item. With LegacyNavigationManager, replaceState operation + // creates a new navigation item, leaving the old item committed. That + // old committed item will be associated with WKBackForwardListItem whose + // state was replaced. So old item won't have correct WKBackForwardListItem. + if (net::GURLWithNSURL(holder->back_forward_list_item().URL) != + currentItem->GetURL()) { + // The state was replaced for this item. The item should not be a part of + // committed items, but it's too late to remove the item. Cleaup + // WKBackForwardListItem and mark item with "state replaced" flag. + currentItem->SetHasStateBeenReplaced(true); + holder->set_back_forward_list_item(nil); + } + } + + // If the request has POST data and is not a repost form, configure and + // run the POST request. + if (POSTData.length && !repostedForm) { + [request setHTTPMethod:@"POST"]; + [request setHTTPBody:POSTData]; + [request setAllHTTPHeaderFields:self.currentHTTPHeaders]; + // As of iOS 11, WKWebView supports requests with POST data, so the + // Javascript POST workaround only needs to be used if the OS version is + // less than iOS 11. + // TODO(crbug.com/740987): Remove POST workaround once iOS 10 is dropped. + if (!base::ios::IsRunningOnIOS11OrLater()) { + GURL navigationURL = + currentItem ? currentItem->GetURL() : GURL::EmptyGURL(); + std::unique_ptr<web::NavigationContextImpl> navigationContext = + [self registerLoadRequestForURL:navigationURL + referrer:self.currentNavItemReferrer + transition:self.currentTransition + sameDocumentNavigation:sameDocumentNavigation + hasUserGesture:YES + rendererInitiated:NO + placeholderNavigation:NO]; + WKNavigation* navigation = [self loadPOSTRequest:request]; + [_navigationStates setContext:std::move(navigationContext) + forNavigation:navigation]; + [_navigationStates setState:web::WKNavigationState::REQUESTED + forNavigation:navigation]; + return; + } + } + + ProceduralBlock defaultNavigationBlock = ^{ + web::NavigationItem* item = self.currentNavItem; + GURL navigationURL = item ? item->GetURL() : GURL::EmptyGURL(); + GURL contextURL = IsPlaceholderUrl(navigationURL) + ? ExtractUrlFromPlaceholderUrl(navigationURL) + : navigationURL; + std::unique_ptr<web::NavigationContextImpl> navigationContext = + [self registerLoadRequestForURL:contextURL + referrer:self.currentNavItemReferrer + transition:self.currentTransition + sameDocumentNavigation:sameDocumentNavigation + hasUserGesture:YES + rendererInitiated:NO + placeholderNavigation:IsPlaceholderUrl(navigationURL)]; + + WKNavigation* navigation = nil; + GURL virtualURL = item ? item->GetVirtualURL() : GURL::EmptyGURL(); + if (navigationURL.SchemeIsFile() && + web::GetWebClient()->IsAppSpecificURL(virtualURL)) { + // file:// URL navigations are allowed for app-specific URLs, which + // already have elevated privileges. + NSURL* navigationNSURL = net::NSURLWithGURL(navigationURL); + navigation = [self.webView loadFileURL:navigationNSURL + allowingReadAccessToURL:navigationNSURL]; + } else { + navigation = [self.webView loadRequest:request]; + } + [_navigationStates setState:web::WKNavigationState::REQUESTED + forNavigation:navigation]; + [_navigationStates setContext:std::move(navigationContext) + forNavigation:navigation]; + [self reportBackForwardNavigationTypeForFastNavigation:NO]; + }; + + // When navigating via WKBackForwardListItem to pages created or updated by + // calls to pushState() and replaceState(), sometimes web_bundle.js is not + // injected correctly. This means that calling window.history navigation + // functions will invoke WKWebView's non-overridden implementations, causing a + // mismatch between the WKBackForwardList and NavigationManager. + // TODO(crbug.com/659816): Figure out how to prevent web_bundle.js injection + // flake. + if (currentItem->HasStateBeenReplaced() || + currentItem->IsCreatedFromPushState()) { + defaultNavigationBlock(); + return; + } + + // If there is no corresponding WKBackForwardListItem, or the item is not in + // the current WKWebView's back-forward list, navigating using WKWebView API + // is not possible. In this case, fall back to the default navigation + // mechanism. + if (!holder->back_forward_list_item() || + ![self isBackForwardListItemValid:holder->back_forward_list_item()]) { + defaultNavigationBlock(); + return; + } + + ProceduralBlock webViewNavigationBlock = ^{ + // If the current navigation URL is the same as the URL of the visible + // page, that means the user requested a reload. |goToBackForwardListItem| + // will be a no-op when it is passed the current back forward list item, + // so |reload| must be explicitly called. + web::NavigationItem* item = self.currentNavItem; + GURL navigationURL = item ? item->GetURL() : GURL::EmptyGURL(); + std::unique_ptr<web::NavigationContextImpl> navigationContext = + [self registerLoadRequestForURL:navigationURL + referrer:self.currentNavItemReferrer + transition:self.currentTransition + sameDocumentNavigation:sameDocumentNavigation + hasUserGesture:YES + rendererInitiated:NO + placeholderNavigation:NO]; + WKNavigation* navigation = nil; + if (navigationURL == net::GURLWithNSURL(self.webView.URL)) { + navigation = [self.webView reload]; + } else { + // |didCommitNavigation:| may not be called for fast navigation, so update + // the navigation type now as it is already known. + navigationContext->SetWKNavigationType(WKNavigationTypeBackForward); + navigationContext->SetMimeType(holder->mime_type()); + holder->set_navigation_type(WKNavigationTypeBackForward); + navigation = [self.webView + goToBackForwardListItem:holder->back_forward_list_item()]; + [self reportBackForwardNavigationTypeForFastNavigation:YES]; + } + [_navigationStates setState:web::WKNavigationState::REQUESTED + forNavigation:navigation]; + [_navigationStates setContext:std::move(navigationContext) + forNavigation:navigation]; + }; + + // If the request is not a form submission or resubmission, or the user + // doesn't need to confirm the load, then continue right away. + + if (!repostedForm || currentItem->ShouldSkipRepostFormConfirmation()) { + webViewNavigationBlock(); + return; + } + + // If the request is form submission or resubmission, then prompt the + // user before proceeding. + DCHECK(repostedForm); + DCHECK(!web::GetWebClient()->IsSlimNavigationManagerEnabled()); + self.webStateImpl->ShowRepostFormWarningDialog( + base::BindOnce(^(bool shouldContinue) { + if (_isBeingDestroyed) + return; + + if (shouldContinue) + webViewNavigationBlock(); + else + [self stopLoading]; + })); +} + +- (void)reportBackForwardNavigationTypeForFastNavigation:(BOOL)isFast { + // TODO(crbug.com/665189): Use NavigationManager::GetPendingItemIndex() once + // it returns correct result. + int pendingIndex = self.sessionController.pendingItemIndex; + if (pendingIndex == -1) { + // Pending navigation is not a back forward navigation. + return; + } + + BOOL isBack = + pendingIndex < self.navigationManagerImpl->GetLastCommittedItemIndex(); + BackForwardNavigationType type = BackForwardNavigationType::FAST_BACK; + if (isBack) { + type = isFast ? BackForwardNavigationType::FAST_BACK + : BackForwardNavigationType::SLOW_BACK; + } else { + type = isFast ? BackForwardNavigationType::FAST_FORWARD + : BackForwardNavigationType::SLOW_FORWARD; + } + + UMA_HISTOGRAM_ENUMERATION( + "Navigation.IOSWKWebViewSlowFastBackForward", type, + BackForwardNavigationType::BACK_FORWARD_NAVIGATION_TYPE_COUNT); +} + - (void)updatePendingNavigationInfoFromNavigationAction: (WKNavigationAction*)action { if (action.targetFrame.mainFrame) { @@ -1767,6 +2465,26 @@ return request; } +- (web::NavigationContextImpl*)contextForPendingMainFrameNavigationWithURL: + (const GURL&)URL { + // Here the enumeration variable |navigation| is __strong to allow setting it + // to nil. + for (__strong id navigation in [_navigationStates pendingNavigations]) { + if (navigation == [NSNull null]) { + // null is a valid navigation object passed to WKNavigationDelegate + // callbacks and represents window opening action. + navigation = nil; + } + + web::NavigationContextImpl* context = + [_navigationStates contextForNavigation:navigation]; + if (context && context->GetUrl() == URL) { + return context; + } + } + return nullptr; +} + - (web::WKBackForwardListItemHolder*)currentBackForwardListItemHolder { web::NavigationItem* item = self.currentNavItem; DCHECK(item); @@ -1795,7 +2513,7 @@ WKNavigationType navigationType = _pendingNavigationInfo ? [_pendingNavigationInfo navigationType] : WKNavigationTypeOther; - holder->set_back_forward_list_item([_webView backForwardList].currentItem); + holder->set_back_forward_list_item(self.webView.backForwardList.currentItem); holder->set_navigation_type(navigationType); holder->set_http_method([_pendingNavigationInfo HTTPMethod]); @@ -1828,16 +2546,16 @@ NSString* failing_url = error.userInfo[NSURLErrorFailingURLStringErrorKey]; NSString* errorHTML = nil; web::GetWebClient()->PrepareErrorPage( - _webStateImpl, GURL(base::SysNSStringToUTF8(failing_url)), error, - context->IsPost(), _webStateImpl->GetBrowserState()->IsOffTheRecord(), + self.webStateImpl, GURL(base::SysNSStringToUTF8(failing_url)), error, + context->IsPost(), self.webStateImpl->GetBrowserState()->IsOffTheRecord(), &errorHTML); WKNavigation* navigation = - [_webView loadHTMLString:errorHTML - baseURL:net::NSURLWithGURL(currentURL)]; + [self.webView loadHTMLString:errorHTML + baseURL:net::NSURLWithGURL(currentURL)]; auto loadHTMLContext = web::NavigationContextImpl::CreateNavigationContext( - _webStateImpl, currentURL, + self.webStateImpl, currentURL, /*has_user_gesture=*/false, ui::PAGE_TRANSITION_FIRST, /*is_renderer_initiated=*/false); loadHTMLContext->SetLoadingErrorPage(true); @@ -1866,12 +2584,12 @@ context->SetUrl(item->GetURL()); context->SetPlaceholderNavigation(false); context->SetHasCommitted(true); - _webStateImpl->OnNavigationFinished(context); + self.webStateImpl->OnNavigationFinished(context); } [self loadCompleteWithSuccess:NO forContext:context]; - _webStateImpl->SetIsLoading(false); - _webStateImpl->OnPageLoaded(currentURL, NO); + self.webStateImpl->SetIsLoading(false); + self.webStateImpl->OnPageLoaded(currentURL, NO); } // Loads the current URL in a native controller if using the legacy navigation @@ -1929,11 +2647,11 @@ rendererInitiated:rendererInitiated placeholderNavigation:NO]; - _webStateImpl->OnNavigationStarted(context.get()); + self.webStateImpl->OnNavigationStarted(context.get()); [self didStartLoading]; self.navigationManagerImpl->CommitPendingItem(); context->SetHasCommitted(true); - _webStateImpl->OnNavigationFinished(context.get()); + self.webStateImpl->OnNavigationFinished(context.get()); if (item && web::GetWebClient()->IsAppSpecificURL(item->GetURL())) { // Report the successful navigation to the ErrorRetryStateMachine. @@ -1963,7 +2681,7 @@ NSURLRequest* request = [NSURLRequest requestWithURL:net::NSURLWithGURL(placeholderURL)]; - WKNavigation* navigation = [_webView loadRequest:request]; + WKNavigation* navigation = [self.webView loadRequest:request]; [_navigationStates setState:web::WKNavigationState::REQUESTED forNavigation:navigation]; std::unique_ptr<web::NavigationContextImpl> navigationContext; @@ -2007,7 +2725,7 @@ break; case web::ErrorRetryCommand::kReload: - [_webView reload]; + [self.webView reload]; break; case web::ErrorRetryCommand::kRewriteWebViewURL: { @@ -2018,8 +2736,8 @@ rendererInitiated:context->IsRendererInitiated() placeholderNavigation:NO]; WKNavigation* navigation = - [_webView loadHTMLString:@"" - baseURL:net::NSURLWithGURL(item->GetURL())]; + [self.webView loadHTMLString:@"" + baseURL:net::NSURLWithGURL(item->GetURL())]; navigationContext->SetError(context->GetError()); navigationContext->SetIsPost(context->IsPost()); [_navigationStates setContext:std::move(navigationContext) @@ -2031,89 +2749,6 @@ } } -- (void)loadCurrentURLWithRendererInitiatedNavigation:(BOOL)rendererInitiated { - // If the content view doesn't exist, the tab has either been evicted, or - // never displayed. Bail, and let the URL be loaded when the tab is shown. - if (!_containerView) - return; - - // WKBasedNavigationManagerImpl needs WKWebView to load native views, but - // WKWebView cannot be created while web usage is disabled to avoid breaking - // clearing browser data. Bail now and let the URL be loaded when web - // usage is enabled again. This can happen when purging web pages when an - // interstitial is presented over a native view. See https://crbug.com/865985 - // for details. - if (web::GetWebClient()->IsSlimNavigationManagerEnabled() && - !_webUsageEnabled) - return; - - _currentURLLoadWasTrigerred = YES; - - // Reset current WebUI if one exists. - [self clearWebUI]; - - // Abort any outstanding page load. This ensures the delegate gets informed - // about the outgoing page, and further messages from the page are suppressed. - if (_loadPhase != web::PAGE_LOADED) - [self abortLoad]; - - DCHECK(!_isHalted); - _webStateImpl->ClearTransientContent(); - - web::NavigationItem* item = self.currentNavItem; - const GURL currentURL = item ? item->GetURL() : GURL::EmptyGURL(); - const bool isCurrentURLAppSpecific = - web::GetWebClient()->IsAppSpecificURL(currentURL); - // If it's a chrome URL, but not a native one, create the WebUI instance. - if (isCurrentURLAppSpecific && - ![_nativeProvider hasControllerForURL:currentURL]) { - if (!(item->GetTransitionType() & ui::PAGE_TRANSITION_TYPED || - item->GetTransitionType() & ui::PAGE_TRANSITION_AUTO_BOOKMARK) && - self.hasOpener) { - // WebUI URLs can not be opened by DOM to prevent cross-site scripting as - // they have increased power. WebUI URLs may only be opened when the user - // types in the URL or use bookmarks. - self.navigationManagerImpl->DiscardNonCommittedItems(); - return; - } else { - [self createWebUIForURL:currentURL]; - } - } - - // Loading a new url, must check here if it's a native chrome URL and - // replace the appropriate view if so, or transition back to a web view from - // a native view. - if ([self shouldLoadURLInNativeView:currentURL]) { - [self loadCurrentURLInNativeViewWithRendererInitiatedNavigation: - rendererInitiated]; - } else if (web::GetWebClient()->IsSlimNavigationManagerEnabled() && - isCurrentURLAppSpecific && _webStateImpl->HasWebUI() && - !web::features::WebUISchemeHandlingEnabled()) { - [self loadPlaceholderInWebViewForURL:currentURL - rendererInitiated:rendererInitiated - forContext:nullptr]; - } else { - [self loadCurrentURLInWebView]; - } -} - -- (void)loadCurrentURLIfNecessary { - if (_webProcessCrashed) { - [self loadCurrentURLWithRendererInitiatedNavigation:NO]; - } else if (!_currentURLLoadWasTrigerred) { - [self ensureContainerViewCreated]; - - // This method reloads last committed item, so make than item also pending. - self.sessionController.pendingItemIndex = - self.sessionController.lastCommittedItemIndex; - - // TODO(crbug.com/796608): end the practice of calling |loadCurrentURL| - // when it is possible there is no current URL. If the call performs - // necessary initialization, break that out. - [self loadCurrentURLWithRendererInitiatedNavigation:NO]; - } -} - - (GURL)webURLWithTrustLevel:(web::URLVerificationTrustLevel*)trustLevel { DCHECK(trustLevel); *trustLevel = web::URLVerificationTrustLevel::kAbsolute; @@ -2127,77 +2762,12 @@ - (BOOL)shouldLoadURLInNativeView:(const GURL&)url { // App-specific URLs that don't require WebUI are loaded in native views. return web::GetWebClient()->IsAppSpecificURL(url) && - !_webStateImpl->HasWebUI() && + !self.webStateImpl->HasWebUI() && [_nativeProvider hasControllerForURL:url]; } -- (void)reloadWithRendererInitiatedNavigation:(BOOL)rendererInitiated { - // Clear last user interaction. - // TODO(crbug.com/546337): Move to after the load commits, in the subclass - // implementation. This will be inaccurate if the reload fails or is - // cancelled. - _lastUserInteraction = nullptr; - base::RecordAction(base::UserMetricsAction("Reload")); - GURL URL = self.currentNavItem->GetURL(); - if ([self shouldLoadURLInNativeView:URL]) { - std::unique_ptr<web::NavigationContextImpl> navigationContext = [self - registerLoadRequestForURL:URL - referrer:self.currentNavItemReferrer - transition:ui::PageTransition::PAGE_TRANSITION_RELOAD - sameDocumentNavigation:NO - hasUserGesture:YES - rendererInitiated:rendererInitiated - placeholderNavigation:NO]; - _webStateImpl->OnNavigationStarted(navigationContext.get()); - [self didStartLoading]; - self.navigationManagerImpl->CommitPendingItem( - navigationContext->ReleaseItem()); - [self.nativeController reload]; - navigationContext->SetHasCommitted(true); - _webStateImpl->OnNavigationFinished(navigationContext.get()); - [self loadCompleteWithSuccess:YES forContext:nullptr]; - } else { - web::NavigationItem* transientItem = - self.navigationManagerImpl->GetTransientItem(); - if (transientItem) { - // If there's a transient item, a reload is considered a new navigation to - // the transient item's URL (as on other platforms). - NavigationManager::WebLoadParams reloadParams(transientItem->GetURL()); - reloadParams.transition_type = ui::PAGE_TRANSITION_RELOAD; - reloadParams.extra_headers = - [transientItem->GetHttpRequestHeaders() copy]; - self.webState->GetNavigationManager()->LoadURLWithParams(reloadParams); - } else { - self.currentNavItem->SetTransitionType( - ui::PageTransition::PAGE_TRANSITION_RELOAD); - if (web::GetWebClient()->IsSlimNavigationManagerEnabled() && - !web::GetWebClient()->IsAppSpecificURL( - net::GURLWithNSURL(_webView.URL))) { - // New navigation manager can delegate directly to WKWebView to reload - // for non-app-specific URLs. The necessary navigation states will be - // updated in WKNavigationDelegate callbacks. - WKNavigation* navigation = [_webView reload]; - [_navigationStates setState:web::WKNavigationState::REQUESTED - forNavigation:navigation]; - std::unique_ptr<web::NavigationContextImpl> navigationContext = [self - registerLoadRequestForURL:URL - referrer:self.currentNavItemReferrer - transition:ui::PageTransition::PAGE_TRANSITION_RELOAD - sameDocumentNavigation:NO - hasUserGesture:YES - rendererInitiated:rendererInitiated - placeholderNavigation:NO]; - [_navigationStates setContext:std::move(navigationContext) - forNavigation:navigation]; - } else { - [self loadCurrentURLWithRendererInitiatedNavigation:rendererInitiated]; - } - } - } -} - - (void)abortLoad { - [_webView stopLoading]; + [self.webView stopLoading]; [_pendingNavigationInfo setCancelled:YES]; _certVerificationErrors->Clear(); [self loadCancelled]; @@ -2209,13 +2779,13 @@ if (_loadPhase != web::PAGE_LOADED) { _loadPhase = web::PAGE_LOADED; if (!_isHalted) { - _webStateImpl->SetIsLoading(false); + self.webStateImpl->SetIsLoading(false); } } } - (BOOL)contentIsImage { - if (!_webView) + if (!self.webView) return NO; const std::string image = "image"; @@ -2316,7 +2886,7 @@ if (context && IsRestoreSessionUrl(context->GetUrl())) return; - if (IsRestoreSessionUrl(net::GURLWithNSURL(_webView.URL))) + if (IsRestoreSessionUrl(net::GURLWithNSURL(self.webView.URL))) return; if (context && context->IsLoadingErrorPage()) @@ -2328,8 +2898,8 @@ return; } - _webStateImpl->SetIsLoading(false); - _webStateImpl->OnPageLoaded(currentURL, YES); + self.webStateImpl->SetIsLoading(false); + self.webStateImpl->OnPageLoaded(currentURL, YES); } - (void)rendererInitiatedGoDelta:(int)delta @@ -2350,26 +2920,6 @@ } } -- (void)addGestureRecognizerToWebView:(UIGestureRecognizer*)recognizer { - if ([_gestureRecognizers containsObject:recognizer]) - return; - - [_webView addGestureRecognizer:recognizer]; - [_gestureRecognizers addObject:recognizer]; -} - -- (void)removeGestureRecognizerFromWebView:(UIGestureRecognizer*)recognizer { - if (![_gestureRecognizers containsObject:recognizer]) - return; - - [_webView removeGestureRecognizer:recognizer]; - [_gestureRecognizers removeObject:recognizer]; -} - -- (CRWJSInjectionReceiver*)jsInjectionReceiver { - return _jsInjectionReceiver; -} - - (BOOL)shouldClosePageOnNativeApplicationLoad { // The page should be closed if it was initiated by the DOM and there has been // no user interaction with the page since the web view was created, or if @@ -2381,20 +2931,6 @@ return rendererInitiatedWithoutInteraction || noNavigationItems; } -- (web::UserAgentType)userAgentType { - web::NavigationItem* item = self.currentNavItem; - return item ? item->GetUserAgentType() : web::UserAgentType::MOBILE; -} - -- (web::MojoFacade*)mojoFacade { - if (!_mojoFacade) { - service_manager::mojom::InterfaceProvider* interfaceProvider = - _webStateImpl->GetWebStateInterfaceProvider(); - _mojoFacade.reset(new web::MojoFacade(interfaceProvider, self)); - } - return _mojoFacade.get(); -} - - (void)updateDesktopUserAgentForItem:(web::NavigationItem*)item previousUserAgentType:(web::UserAgentType)userAgentType { if (!item) @@ -2414,43 +2950,7 @@ self.navigationManagerImpl->DiscardNonCommittedItems(); } -- (void)takeSnapshotWithRect:(CGRect)rect - completion:(void (^)(UIImage*))completion { - if (@available(iOS 11, *)) { - if (_webView) { - WKSnapshotConfiguration* configuration = - [[WKSnapshotConfiguration alloc] init]; - configuration.rect = [_webView convertRect:rect fromView:self.view]; - __weak CRWWebController* weakSelf = self; - [_webView - takeSnapshotWithConfiguration:configuration - completionHandler:^(UIImage* snapshot, NSError* error) { - // Pass nil to the completion block if there is an error - // or if the web view has been removed before the - // snapshot is finished. |snapshot| can sometimes be - // corrupt if it's sent due to the WKWebView's - // deallocation, so callbacks received after - // |-removeWebView| are ignored to prevent crashing. - if (error || !weakSelf.webView) { - if (error) { - DLOG(ERROR) << "WKWebView snapshot error: " - << error.description; - } - completion(nil); - } else { - completion(snapshot); - } - }]; - return; - } - } - dispatch_async(dispatch_get_main_queue(), ^{ - completion(nil); - }); -} - -#pragma mark - -#pragma mark CRWWebControllerContainerViewDelegate +#pragma mark - CRWWebControllerContainerViewDelegate - (CRWWebViewProxyImpl*)contentViewProxyForContainerView: (CRWWebControllerContainerView*)containerView { @@ -2462,53 +2962,7 @@ return [self.nativeProvider nativeContentInsetForWebState:self.webState]; } -#pragma mark - -#pragma mark CRWJSInjectionEvaluator Methods - -- (void)executeJavaScript:(NSString*)script - completionHandler:(web::JavaScriptResultBlock)completionHandler { - NSString* safeScript = [self scriptByAddingWindowIDCheckForScript:script]; - web::ExecuteJavaScript(_webView, safeScript, completionHandler); -} - -- (BOOL)scriptHasBeenInjectedForClass:(Class)injectionManagerClass { - return [_injectedScriptManagers containsObject:injectionManagerClass]; -} - -- (void)injectScript:(NSString*)script forClass:(Class)JSInjectionManagerClass { - DCHECK(script.length); - // Script execution is an asynchronous operation which may pass sensitive - // data to the page. executeJavaScript:completionHandler makes sure that - // receiver page did not change by checking its window id. - // |[_webView executeJavaScript:completionHandler:]| is not used here because - // it does not check that page is the same. - [self executeJavaScript:script completionHandler:nil]; - [_injectedScriptManagers addObject:JSInjectionManagerClass]; -} - -#pragma mark - - -- (void)executeUserJavaScript:(NSString*)script - completionHandler:(web::JavaScriptResultBlock)completion { - // For security reasons, executing JavaScript on pages with app-specific URLs - // is not allowed, because those pages may have elevated privileges. - GURL lastCommittedURL = self.webState->GetLastCommittedURL(); - if (web::GetWebClient()->IsAppSpecificURL(lastCommittedURL)) { - if (completion) { - dispatch_async(dispatch_get_main_queue(), ^{ - NSError* error = [[NSError alloc] - initWithDomain:web::kJSEvaluationErrorDomain - code:web::JS_EVALUATION_ERROR_CODE_NO_WEB_VIEW - userInfo:nil]; - completion(nil, error); - }); - } - return; - } - - [self touched:YES]; - [self executeJavaScript:script completionHandler:completion]; -} +#pragma mark - CRWJSInjectionEvaluator helper methods (Private) - (BOOL)respondToMessage:(base::DictionaryValue*)message userIsInteracting:(BOOL)userIsInteracting @@ -2647,13 +3101,22 @@ } return [self respondToMessage:command userIsInteracting:[self userIsInteracting] - originURL:net::GURLWithNSURL([_webView URL]) + originURL:net::GURLWithNSURL(self.webView.URL) isMainFrame:scriptMessage.frameInfo.mainFrame senderFrame:senderFrame]; } -#pragma mark - -#pragma mark Web frames management +- (BOOL)userIsInteracting { + // If page transfer started after last click, user is deemed to be no longer + // interacting. + if (!_lastUserInteraction || + _lastTransferTimeInSeconds > _lastUserInteraction->time) { + return NO; + } + return [self userClickedRecently]; +} + +#pragma mark - Web frames management - (void)frameBecameAvailableWithMessage:(WKScriptMessage*)message { // Validate all expected message components because any frame could falsify @@ -2698,7 +3161,8 @@ } framesManager->AddFrame(std::move(newFrame)); - _webStateImpl->OnWebFrameAvailable(framesManager->GetFrameWithId(frameID)); + self.webStateImpl->OnWebFrameAvailable( + framesManager->GetFrameWithId(frameID)); } } @@ -2712,7 +3176,7 @@ web::WebFramesManagerImpl::FromWebState([self webState]); if (framesManager->GetFrameWithId(frameID)) { - _webStateImpl->OnWebFrameUnavailable( + self.webStateImpl->OnWebFrameUnavailable( framesManager->GetFrameWithId(frameID)); framesManager->RemoveFrameWithId(frameID); } @@ -2722,20 +3186,19 @@ web::WebFramesManagerImpl* framesManager = web::WebFramesManagerImpl::FromWebState([self webState]); for (auto* frame : framesManager->GetAllWebFrames()) { - _webStateImpl->OnWebFrameUnavailable(frame); + self.webStateImpl->OnWebFrameUnavailable(frame); } framesManager->RemoveAllWebFrames(); } -#pragma mark - -#pragma mark JavaScript message handlers +#pragma mark - JavaScript message handlers - (BOOL)handleChromeSendMessage:(base::DictionaryValue*)message context:(NSDictionary*)context { // Chrome message are only handled if sent from the main frame. if (![context[kIsMainFrame] boolValue]) return NO; - if (_webStateImpl->HasWebUI()) { + if (self.webStateImpl->HasWebUI()) { const GURL currentURL([self currentURL]); if (web::GetWebClient()->IsAppSpecificURL(currentURL)) { std::string messageContent; @@ -2750,11 +3213,11 @@ } // WebFrame messaging is not supported in WebUI (as window.isSecureContext // is false. Pass nullptr as sender_frame. - _webStateImpl->OnScriptCommandReceived( + self.webStateImpl->OnScriptCommandReceived( messageContent, *message, currentURL, context[kUserIsInteractingKey], [context[kIsMainFrame] boolValue], nullptr); - _webStateImpl->ProcessWebUIMessage(currentURL, messageContent, - *arguments); + self.webStateImpl->ProcessWebUIMessage(currentURL, messageContent, + *arguments); return YES; } } @@ -2780,7 +3243,7 @@ return NO; if (!URLs.empty()) - _webStateImpl->OnFaviconUrlUpdated(URLs); + self.webStateImpl->OnFaviconUrlUpdated(URLs); return YES; } @@ -3058,23 +3521,6 @@ _pageHasZoomed = NO; } -- (void)wasShown { - self.visible = YES; - if ([self.nativeController respondsToSelector:@selector(wasShown)]) { - [self.nativeController wasShown]; - } -} - -- (void)wasHidden { - self.visible = NO; - if (_isHalted) - return; - [self recordStateInHistory]; - if ([self.nativeController respondsToSelector:@selector(wasHidden)]) { - [self.nativeController wasHidden]; - } -} - + (BOOL)webControllerCanShow:(const GURL&)url { return web::UrlHasWebScheme(url) || web::GetWebClient()->IsAppSpecificURL(url) || @@ -3082,16 +3528,6 @@ url.SchemeIs(url::kBlobScheme); } -- (void)setUserInteractionRegistered:(BOOL)flag { - _userInteractionRegistered = flag; - if (flag) - _interactionRegisteredSinceLastURLChange = YES; -} - -- (BOOL)userInteractionRegistered { - return _userInteractionRegistered; -} - - (void)cachePOSTDataForRequest:(NSURLRequest*)request inNavigationItem:(web::NavigationItemImpl*)item { NSUInteger maxPOSTDataSizeInBytes = 4096; @@ -3140,7 +3576,7 @@ GURL requestURL = net::GURLWithNSURL(action.request.URL); DCHECK(web::GetWebClient()->IsAppSpecificURL(requestURL)); if (web::GetWebClient()->IsAppSpecificURL( - _webStateImpl->GetLastCommittedURL())) { + self.webStateImpl->GetLastCommittedURL())) { // Last committed page is also app specific and navigation should be // allowed. return YES; @@ -3224,7 +3660,7 @@ // Universal Link and called webView:didFailProvisionalNavigation:. self.navigationManagerImpl->DiscardNonCommittedItems(); } - _webStateImpl->SetIsLoading(false); + self.webStateImpl->SetIsLoading(false); return; } } @@ -3236,7 +3672,7 @@ // status for error pages. if (!lastCommittedItem->GetSSL().Equals(web::SSLStatus())) { lastCommittedItem->GetSSL() = web::SSLStatus(); - _webStateImpl->DidChangeVisibleSecurityState(); + self.webStateImpl->DidChangeVisibleSecurityState(); } } @@ -3249,10 +3685,10 @@ web::ErrorRetryCommand command = web::ErrorRetryCommand::kDoNothing; if (provisionalLoad) { command = item->error_retry_state_machine().DidFailProvisionalNavigation( - net::GURLWithNSURL(_webView.URL), errorURL); + net::GURLWithNSURL(self.webView.URL), errorURL); } else { command = item->error_retry_state_machine().DidFailNavigation( - net::GURLWithNSURL(_webView.URL), errorURL); + net::GURLWithNSURL(self.webView.URL), errorURL); } [self handleErrorRetryCommand:command navigationItem:item @@ -3287,7 +3723,7 @@ } if (provisionalLoad) { - _webStateImpl->OnNavigationFinished(navigationContext); + self.webStateImpl->OnNavigationFinished(navigationContext); } } } @@ -3319,7 +3755,7 @@ } BOOL mainFrame = WKResponse.forMainFrame; - if (!_webStateImpl->ShouldAllowResponse(WKResponse.response, mainFrame)) { + if (!self.webStateImpl->ShouldAllowResponse(WKResponse.response, mainFrame)) { return NO; } @@ -3355,7 +3791,7 @@ [self contextForPendingMainFrameNavigationWithURL:responseURL]; context->SetIsDownload(true); // Navigation callbacks can only be called for the main frame. - _webStateImpl->OnNavigationFinished(context); + self.webStateImpl->OnNavigationFinished(context); transition = context->GetPageTransition(); bool transitionIsLink = ui::PageTransitionTypeIncludingQualifiersIs( transition, ui::PAGE_TRANSITION_LINK); @@ -3367,32 +3803,32 @@ transition = ui::PAGE_TRANSITION_CLIENT_REDIRECT; } } - web::DownloadController::FromBrowserState(_webStateImpl->GetBrowserState()) - ->CreateDownloadTask(_webStateImpl, [NSUUID UUID].UUIDString, responseURL, - contentDisposition, contentLength, MIMEType, - transition); + web::DownloadController::FromBrowserState( + self.webStateImpl->GetBrowserState()) + ->CreateDownloadTask(self.webStateImpl, [NSUUID UUID].UUIDString, + responseURL, contentDisposition, contentLength, + MIMEType, transition); } -#pragma mark - -#pragma mark WebUI +#pragma mark - WebUI - (void)createWebUIForURL:(const GURL&)URL { // |CreateWebUI| will do nothing if |URL| is not a WebUI URL and then // |HasWebUI| will return false. - _webStateImpl->CreateWebUI(URL); - bool isWebUIURL = _webStateImpl->HasWebUI(); + self.webStateImpl->CreateWebUI(URL); + bool isWebUIURL = self.webStateImpl->HasWebUI(); if (isWebUIURL && !web::features::WebUISchemeHandlingEnabled()) { - _webUIManager = [[CRWWebUIManager alloc] initWithWebState:_webStateImpl]; + _webUIManager = + [[CRWWebUIManager alloc] initWithWebState:self.webStateImpl]; } } - (void)clearWebUI { - _webStateImpl->ClearWebUI(); + self.webStateImpl->ClearWebUI(); _webUIManager = nil; } -#pragma mark - -#pragma mark Auth Challenge +#pragma mark - Auth Challenge - (void)processAuthChallenge:(NSURLAuthenticationChallenge*)challenge forCertAcceptPolicy:(web::CertAcceptPolicy)policy @@ -3442,7 +3878,7 @@ [space.authenticationMethod isEqual:NSURLAuthenticationMethodNTLM] || [space.authenticationMethod isEqual:NSURLAuthenticationMethodHTTPDigest]); - _webStateImpl->OnAuthRequired( + self.webStateImpl->OnAuthRequired( space, challenge.proposedCredential, base::BindRepeating(^(NSString* user, NSString* password) { [CRWWebController processHTTPAuthForUser:user @@ -3469,133 +3905,10 @@ persistence:NSURLCredentialPersistenceForSession]); } -#pragma mark - -#pragma mark JavaScript Dialog - -- (void)runJavaScriptDialogOfType:(web::JavaScriptDialogType)type - initiatedByFrame:(WKFrameInfo*)frame - message:(NSString*)message - defaultText:(NSString*)defaultText - completion:(void (^)(BOOL, NSString*))completionHandler { - DCHECK(completionHandler); - - // JavaScript dialogs should not be presented if there is no information about - // the requesting page's URL. - GURL requestURL = net::GURLWithNSURL(frame.request.URL); - if (!requestURL.is_valid()) { - completionHandler(NO, nil); - return; - } - - self.webStateImpl->RunJavaScriptDialog( - requestURL, type, message, defaultText, - base::BindOnce(^(bool success, NSString* input) { - completionHandler(success, input); - })); -} - -#pragma mark - -#pragma mark TouchTracking - -- (void)touched:(BOOL)touched { - _clickInProgress = touched; - if (touched) { - self.userInteractionRegistered = YES; - _userInteractedWithWebController = YES; - if (_isBeingDestroyed) - return; - const NavigationManagerImpl* navigationManager = self.navigationManagerImpl; - GURL mainDocumentURL = - navigationManager->GetLastCommittedItem() - ? navigationManager->GetLastCommittedItem()->GetURL() - : [self currentURL]; - _lastUserInteraction = - std::make_unique<UserInteractionEvent>(mainDocumentURL); - } -} - -- (CRWTouchTrackingRecognizer*)touchTrackingRecognizer { - if (!_touchTrackingRecognizer) { - _touchTrackingRecognizer = - [[CRWTouchTrackingRecognizer alloc] initWithDelegate:self]; - } - return _touchTrackingRecognizer; -} - -- (BOOL)userIsInteracting { - // If page transfer started after last click, user is deemed to be no longer - // interacting. - if (!_lastUserInteraction || - _lastTransferTimeInSeconds > _lastUserInteraction->time) { - return NO; - } - return [self userClickedRecently]; -} - -- (BOOL)userClickedRecently { - // Scrolling generates a pair of touch on/off event which causes - // _lastUserInteraction to register that there was user interaction. - // Checks for scrolling first to override time-based click heuristics. - BOOL scrolling = [[self webScrollView] isDragging] || - [[self webScrollView] isDecelerating]; - if (scrolling) - return NO; - if (!_lastUserInteraction) - return NO; - return _clickInProgress || - ((CFAbsoluteTimeGetCurrent() - _lastUserInteraction->time) < - kMaximumDelayForUserInteractionInSeconds); -} - -#pragma mark - -#pragma mark Session Information - -- (CRWSessionController*)sessionController { - NavigationManagerImpl* navigationManager = self.navigationManagerImpl; - return navigationManager ? navigationManager->GetSessionController() : nil; -} - -- (NavigationManagerImpl*)navigationManagerImpl { - return _webStateImpl ? &(_webStateImpl->GetNavigationManagerImpl()) : nil; -} - -- (BOOL)hasOpener { - return _webStateImpl ? _webStateImpl->HasOpener() : NO; -} - -- (web::NavigationItemImpl*)currentNavItem { - return self.navigationManagerImpl - ? self.navigationManagerImpl->GetCurrentItemImpl() - : nullptr; -} - -- (ui::PageTransition)currentTransition { - if (self.currentNavItem) - return self.currentNavItem->GetTransitionType(); - else - return ui::PageTransitionFromInt(0); -} - -- (web::Referrer)currentNavItemReferrer { - web::NavigationItem* currentItem = self.currentNavItem; - return currentItem ? currentItem->GetReferrer() : web::Referrer(); -} - -- (NSDictionary*)currentHTTPHeaders { - web::NavigationItem* currentItem = self.currentNavItem; - return currentItem ? currentItem->GetHttpRequestHeaders() : nil; -} - -- (void)forgetNullWKNavigation:(WKNavigation*)navigation { - if (!navigation) - [_navigationStates removeNavigation:navigation]; -} - -#pragma mark - -#pragma mark CRWWebViewScrollViewProxyObserver +#pragma mark - CRWWebViewScrollViewProxyObserver - (void)webViewScrollViewDidZoom: - (CRWWebViewScrollViewProxy*)webViewScrollViewProxy { + (CRWWebViewScrollViewProxy*)webViewScrollViewProxy { _pageHasZoomed = YES; __weak UIScrollView* weakScrollView = self.webScrollView; @@ -3634,9 +3947,6 @@ } } -#pragma mark - -#pragma mark CRWWebViewScrollViewProxyObserver - // Under WKWebView, JavaScript can execute asynchronously. User can start // scrolling and calls to window.scrollTo executed during scrolling will be // treated as "during user interaction" and can cause app to go fullscreen. @@ -3655,19 +3965,7 @@ completionHandler:nil]; } -#pragma mark - -#pragma mark Page State - -- (void)recordStateInHistory { - // Only record the state if: - // - the current NavigationItem's URL matches the current URL, and - // - the user has interacted with the page. - web::NavigationItem* item = self.currentNavItem; - if (item && item->GetURL() == [self currentURL] && - self.userInteractionRegistered) { - item->SetPageDisplayState(self.pageDisplayState); - } -} +#pragma mark - Page State - (void)restoreStateFromHistory { web::NavigationItem* item = self.currentNavItem; @@ -3675,48 +3973,6 @@ self.pageDisplayState = item->GetPageDisplayState(); } -- (web::PageDisplayState)pageDisplayState { - web::PageDisplayState displayState; - // If a native controller is present, record its display state instead of that - // of the underlying placeholder webview. - if (self.nativeController) { - if ([self.nativeController respondsToSelector:@selector(contentOffset)]) { - displayState.scroll_state().set_content_offset( - [self.nativeController contentOffset]); - } - if ([self.nativeController respondsToSelector:@selector(contentInset)]) { - displayState.scroll_state().set_content_inset( - [self.nativeController contentInset]); - } - } else if (_webView) { - displayState.set_scroll_state(web::PageScrollState( - self.scrollPosition, self.webScrollView.contentInset)); - UIScrollView* scrollView = self.webScrollView; - displayState.zoom_state().set_minimum_zoom_scale( - scrollView.minimumZoomScale); - displayState.zoom_state().set_maximum_zoom_scale( - scrollView.maximumZoomScale); - displayState.zoom_state().set_zoom_scale(scrollView.zoomScale); - } - return displayState; -} - -- (void)setPageDisplayState:(web::PageDisplayState)displayState { - if (!displayState.IsValid()) - return; - if (_webView) { - // Page state is restored after a page load completes. If the user has - // scrolled or changed the zoom scale while the page is still loading, don't - // restore any state since it will confuse the user. - web::PageDisplayState currentPageDisplayState = self.pageDisplayState; - if (currentPageDisplayState.scroll_state() == - _displayStateOnStartLoading.scroll_state() && - !_pageHasZoomed) { - [self applyPageDisplayState:displayState]; - } - } -} - - (void)extractViewportTagWithCompletion:(ViewportStateCompletion)completion { DCHECK(completion); web::NavigationItem* currentItem = self.currentNavItem; @@ -3751,7 +4007,7 @@ // - After zooming occurs in a UIWebView that's displaying a page with a hard- // coded viewport width, the zoom will not be updated upon rotation // ( crbug.com/485055 ). - if (!_webView) + if (!self.webView) return; web::NavigationItem* currentItem = self.currentNavItem; if (!currentItem) @@ -3807,7 +4063,7 @@ } - (void)prepareToApplyWebViewScrollZoomScale { - id webView = _webView; + id webView = self.webView; if (![webView respondsToSelector:@selector(viewForZoomingInScrollView:)]) { return; } @@ -3822,7 +4078,7 @@ } - (void)finishApplyingWebViewScrollZoomScale { - id webView = _webView; + id webView = self.webView; if ([webView respondsToSelector:@selector(scrollViewDidEndZooming: withView: atScale:)] && @@ -3873,8 +4129,7 @@ } } -#pragma mark - -#pragma mark Fullscreen +#pragma mark - Fullscreen - (void)optOutScrollsToTopForSubviews { NSMutableArray* stack = @@ -3888,8 +4143,7 @@ } } -#pragma mark - -#pragma mark WebDelegate Calls +#pragma mark - WebDelegate Calls - (BOOL)isMainFrameNavigationAction:(WKNavigationAction*)action { if (action.targetFrame) { @@ -3919,9 +4173,9 @@ [_SSLStatusUpdater setDelegate:self]; } NSString* host = base::SysUTF8ToNSString(_documentURL.host()); - BOOL hasOnlySecureContent = [_webView hasOnlySecureContent]; + BOOL hasOnlySecureContent = [self.webView hasOnlySecureContent]; base::ScopedCFTypeRef<SecTrustRef> trust; - trust.reset([_webView serverTrust], base::scoped_policy::RETAIN); + trust.reset([self.webView serverTrust], base::scoped_policy::RETAIN); [_SSLStatusUpdater updateSSLStatusForNavigationItem:currentNavItem withCertHost:host @@ -3994,7 +4248,7 @@ // Ask web client if this cert error should be allowed. web::GetWebClient()->AllowCertificateError( - _webStateImpl, net::MapCertStatusToNetError(info.cert_status), info, + self.webStateImpl, net::MapCertStatusToNetError(info.cert_status), info, net::GURLWithNSURL(requestURL), recoverable, base::BindRepeating(^(bool proceed) { if (proceed) { @@ -4002,7 +4256,7 @@ [_certVerificationController allowCert:leafCert forHost:host status:info.cert_status]; - _webStateImpl->GetSessionCertificatePolicyCacheImpl() + self.webStateImpl->GetSessionCertificatePolicyCacheImpl() .RegisterAllowedCertificate( leafCert, base::SysNSStringToUTF8(host), info.cert_status); // New navigation is a different navigation from the original one. @@ -4079,16 +4333,16 @@ } - (void)ensureWebViewCreatedWithConfiguration:(WKWebViewConfiguration*)config { - if (!_webView) { + if (!self.webView) { [self setWebView:[self webViewWithConfiguration:config]]; // The following is not called in -setWebView: as the latter used in unit // tests with fake web view, which cannot be added to view hierarchy. CHECK(_webUsageEnabled) << "Tried to create a web view while suspended!"; - DCHECK(_webView); + DCHECK(self.webView); - [_webView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleHeight]; + [self.webView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight]; // Create a dependency between the |webView| pan gesture and BVC side swipe // gestures. Note: This needs to be added before the longPress recognizers @@ -4102,19 +4356,19 @@ web::BrowserState* browserState = self.webStateImpl->GetBrowserState(); _contextMenuController = - [[CRWContextMenuController alloc] initWithWebView:_webView + [[CRWContextMenuController alloc] initWithWebView:self.webView browserState:browserState injectionEvaluator:self delegate:self]; // Add all additional gesture recognizers to the web view. for (UIGestureRecognizer* recognizer in _gestureRecognizers) { - [_webView addGestureRecognizer:recognizer]; + [self.webView addGestureRecognizer:recognizer]; } // WKWebViews with invalid or empty frames have exhibited rendering bugs, so // resize the view to match the container view upon creation. - [_webView setFrame:[_containerView bounds]]; + [self.webView setFrame:[_containerView bounds]]; } // If web view is not currently displayed and if the visible NavigationItem @@ -4197,20 +4451,20 @@ return; CRWWebViewContentView* webViewContentView = - [[CRWWebViewContentView alloc] initWithWebView:_webView + [[CRWWebViewContentView alloc] initWithWebView:self.webView scrollView:self.webScrollView]; [_containerView displayWebViewContentView:webViewContentView]; } - (void)removeWebView { - if (!_webView) + if (!self.webView) return; - _webStateImpl->CancelDialogs(); + self.webStateImpl->CancelDialogs(); self.navigationManagerImpl->DetachFromWebView(); [self abortLoad]; - [_webView removeFromSuperview]; + [self.webView removeFromSuperview]; [_containerView resetContent]; [self setWebView:nil]; @@ -4231,8 +4485,8 @@ [self removeWebView]; } _webProcessCrashed = YES; - _webStateImpl->CancelDialogs(); - _webStateImpl->OnRenderProcessGone(); + self.webStateImpl->CancelDialogs(); + self.webStateImpl->OnRenderProcessGone(); } - (web::WKWebViewConfigurationProvider&)webViewConfigurationProvider { @@ -4250,7 +4504,7 @@ return [_POSTRequestLoader loadPOSTRequest:request - inWebView:_webView + inWebView:self.webView messageRouter:messageRouter completionHandler:^(NSError* loadError) { if (loadError) @@ -4265,28 +4519,28 @@ - (void)loadHTML:(NSString*)HTML forURL:(const GURL&)URL { DCHECK(HTML.length); // Remove the transient content view. - _webStateImpl->ClearTransientContent(); + self.webStateImpl->ClearTransientContent(); _loadPhase = web::LOAD_REQUESTED; // Web View should not be created for App Specific URLs. if (!web::GetWebClient()->IsAppSpecificURL(URL)) { [self ensureWebViewCreated]; - DCHECK(_webView) << "_webView null while trying to load HTML"; + DCHECK(self.webView) << "self.webView null while trying to load HTML"; } WKNavigation* navigation = - [_webView loadHTMLString:HTML baseURL:net::NSURLWithGURL(URL)]; + [self.webView loadHTMLString:HTML baseURL:net::NSURLWithGURL(URL)]; [_navigationStates setState:web::WKNavigationState::REQUESTED forNavigation:navigation]; std::unique_ptr<web::NavigationContextImpl> context; const ui::PageTransition loadHTMLTransition = ui::PageTransition::PAGE_TRANSITION_TYPED; - if (_webStateImpl->HasWebUI()) { + if (self.webStateImpl->HasWebUI()) { // WebUI uses |loadHTML:forURL:| to feed the content to web view. This // should not be treated as a navigation, but WKNavigationDelegate callbacks // still expect a valid context. context = web::NavigationContextImpl::CreateNavigationContext( - _webStateImpl, URL, /*has_user_gesture=*/true, loadHTMLTransition, + self.webStateImpl, URL, /*has_user_gesture=*/true, loadHTMLTransition, /*is_renderer_initiated=*/false); context->SetNavigationItemUniqueID(self.currentNavItem->GetUniqueID()); if (web::features::StorePendingItemInContext()) { @@ -4309,33 +4563,7 @@ [_navigationStates setContext:std::move(context) forNavigation:navigation]; } -- (void)loadHTML:(NSString*)HTML forAppSpecificURL:(const GURL&)URL { - CHECK(web::GetWebClient()->IsAppSpecificURL(URL)); - [self loadHTML:HTML forURL:URL]; -} - -- (void)stopLoading { - _stoppedWKNavigation = [_navigationStates lastAddedNavigation]; - - base::RecordAction(base::UserMetricsAction("Stop")); - // Discard the pending and transient entried before notifying the tab model - // observers of the change via |-abortLoad|. - self.navigationManagerImpl->DiscardNonCommittedItems(); - [self abortLoad]; - web::NavigationItem* item = self.currentNavItem; - GURL navigationURL = item ? item->GetVirtualURL() : GURL::EmptyGURL(); - // If discarding the non-committed entries results in an app-specific URL, - // reload it in its native view. - if (!self.nativeController && - [self shouldLoadURLInNativeView:navigationURL]) { - // RendererInitiated flag is meaningless for showing previous native - // content page. RendererInitiated is used as less previledged. - [self loadCurrentURLInNativeViewWithRendererInitiatedNavigation:YES]; - } -} - -#pragma mark - -#pragma mark WKUIDelegate Methods +#pragma mark - WKUIDelegate Methods - (WKWebView*)webView:(WKWebView*)webView createWebViewWithConfiguration:(WKWebViewConfiguration*)configuration @@ -4368,8 +4596,8 @@ web::NavigationActionInitiationType::kUserInitiated; } - WebState* childWebState = - _webStateImpl->CreateNewWebState(requestURL, openerURL, initiatedByUser); + WebState* childWebState = self.webStateImpl->CreateNewWebState( + requestURL, openerURL, initiatedByUser); if (!childWebState) return nil; @@ -4390,7 +4618,7 @@ - (void)webViewDidClose:(WKWebView*)webView { if (self.hasOpener) - _webStateImpl->CloseWebState(); + self.webStateImpl->CloseWebState(); } - (void)webView:(WKWebView*)webView @@ -4474,8 +4702,33 @@ previewingViewController); } -#pragma mark - -#pragma mark WKNavigationDelegate Methods +#pragma mark - WKUIDelegate helper methods + +// Helper to respond to |webView:runJavaScript...| delegate methods. +// |completionHandler| must not be nil. +- (void)runJavaScriptDialogOfType:(web::JavaScriptDialogType)type + initiatedByFrame:(WKFrameInfo*)frame + message:(NSString*)message + defaultText:(NSString*)defaultText + completion:(void (^)(BOOL, NSString*))completionHandler { + DCHECK(completionHandler); + + // JavaScript dialogs should not be presented if there is no information about + // the requesting page's URL. + GURL requestURL = net::GURLWithNSURL(frame.request.URL); + if (!requestURL.is_valid()) { + completionHandler(NO, nil); + return; + } + + self.webStateImpl->RunJavaScriptDialog( + requestURL, type, message, defaultText, + base::BindOnce(^(bool success, NSString* input) { + completionHandler(success, input); + })); +} + +#pragma mark - WKNavigationDelegate Methods - (void)webView:(WKWebView*)webView decidePolicyForNavigationAction:(WKNavigationAction*)action @@ -4576,7 +4829,7 @@ // be detected. Display the confirmation dialog. if ([action.request.HTTPMethod isEqual:@"POST"] && (action.navigationType == WKNavigationTypeFormResubmitted)) { - _webStateImpl->ShowRepostFormWarningDialog( + self.webStateImpl->ShowRepostFormWarningDialog( base::BindOnce(^(bool shouldContinue) { if (shouldContinue) { decisionHandler(WKNavigationActionPolicyAllow); @@ -4584,7 +4837,7 @@ decisionHandler(WKNavigationActionPolicyCancel); if (action.targetFrame.mainFrame) { [_pendingNavigationInfo setCancelled:YES]; - _webStateImpl->SetIsLoading(false); + self.webStateImpl->SetIsLoading(false); } } })); @@ -4683,7 +4936,7 @@ [self discardNonCommittedItemsIfLastCommittedWasNotNativeView]; if (!_isBeingDestroyed && [self shouldClosePageOnNativeApplicationLoad]) - _webStateImpl->CloseWebState(); + self.webStateImpl->CloseWebState(); } if (!_isBeingDestroyed) { @@ -4691,7 +4944,7 @@ // stopped because no other WKWebView callbacks are called. // TODO(crbug.com/767092): Loading should not start until webView.loading // is changed to YES. - _webStateImpl->SetIsLoading(false); + self.webStateImpl->SetIsLoading(false); } } @@ -4769,13 +5022,8 @@ static_cast<NSHTTPURLResponse*>(WKResponse.response)); // TODO(crbug.com/551677): remove |OnHttpResponseHeadersReceived| and attach // headers to web::NavigationContext. - _webStateImpl->OnHttpResponseHeadersReceived(headers.get(), responseURL); - } - - if (WKResponse.forMainFrame) { - web::NavigationContextImpl* context = - [self contextForPendingMainFrameNavigationWithURL:responseURL]; - context->SetMimeType(WKResponse.response.MIMEType); + self.webStateImpl->OnHttpResponseHeadersReceived(headers.get(), + responseURL); } // The page will not be changed until this navigation is committed, so the @@ -4797,17 +5045,17 @@ // Loading will be stopped in webView:didFinishNavigation: callback. This // call is here to preserve the original behavior when pending item is not // stored in NavigationContext. - _webStateImpl->SetIsLoading(false); + self.webStateImpl->SetIsLoading(false); } } else if (!shouldRenderResponse && WKResponse.forMainFrame) { [_pendingNavigationInfo setCancelled:YES]; } if (web::GetWebClient()->IsSlimNavigationManagerEnabled() && - !WKResponse.forMainFrame && !_webView.loading) { + !WKResponse.forMainFrame && !self.webView.loading) { // This is the terminal callback for iframe navigation and there is no // pending main frame navigation. Last chance to flip IsLoading to false. - _webStateImpl->SetIsLoading(false); + self.webStateImpl->SetIsLoading(false); } handler(shouldRenderResponse ? WKNavigationResponsePolicyAllow @@ -4854,7 +5102,7 @@ context->SetUrl(webViewURL); } } - _webStateImpl->OnNavigationStarted(context); + self.webStateImpl->OnNavigationStarted(context); return; } @@ -4897,7 +5145,7 @@ return; } - _webStateImpl->GetNavigationManagerImpl() + self.webStateImpl->GetNavigationManagerImpl() .OnRendererInitiatedNavigationStarted(webViewURL); std::unique_ptr<web::NavigationContextImpl> navigationContext = @@ -4911,7 +5159,7 @@ // association between NavigationContextImpl and WKNavigation. [_navigationStates setContext:std::move(navigationContext) forNavigation:navigation]; - _webStateImpl->OnNavigationStarted(navigationContextPtr); + self.webStateImpl->OnNavigationStarted(navigationContextPtr); DCHECK(self.loadPhase == web::LOAD_REQUESTED); } @@ -4972,7 +5220,7 @@ forNavigation:navigation provisionalLoad:YES]; } else if (error.code == NSURLErrorUnsupportedURL && - _webStateImpl->HasWebUI()) { + self.webStateImpl->HasWebUI()) { // This is a navigation to WebUI page. DCHECK(web::GetWebClient()->IsAppSpecificURL( net::GURLWithNSURL(error.userInfo[NSURLErrorFailingURLErrorKey]))); @@ -5020,7 +5268,7 @@ forNavigation:navigation]; } - DCHECK_EQ(_webView, webView); + DCHECK_EQ(self.webView, webView); _certVerificationErrors->Clear(); // Invariant: Every |navigation| should have a |context|. Note that violation @@ -5055,13 +5303,16 @@ webViewURL = currentWKItemURL; } + if (_pendingNavigationInfo.MIMEType) + context->SetMimeType(_pendingNavigationInfo.MIMEType); + // Don't show webview for placeholder navigation to avoid covering the native // content, which may have already been shown. if (!IsPlaceholderUrl(webViewURL)) [self displayWebView]; // Update HTTP response headers. - _webStateImpl->UpdateHttpResponseHeaders(webViewURL); + self.webStateImpl->UpdateHttpResponseHeaders(webViewURL); if (@available(iOS 11.3, *)) { // On iOS 11.3 didReceiveServerRedirectForProvisionalNavigation: is not @@ -5079,7 +5330,7 @@ // finished. if (context) { web::NavigationManager* navigationManager = - _webStateImpl->GetNavigationManager(); + self.webStateImpl->GetNavigationManager(); if ((navigationManager->GetPendingItem() && navigationManager->GetPendingItem()->GetURL() == webViewURL) || (context->IsLoadingHtmlString()) || @@ -5097,7 +5348,7 @@ // crbug.com/676129) context->SetHasCommitted(true); } - context->SetResponseHeaders(_webStateImpl->GetHttpResponseHeaders()); + context->SetResponseHeaders(self.webStateImpl->GetHttpResponseHeaders()); self.webStateImpl->SetContentsMimeType( base::SysNSStringToUTF8(context->GetMimeType())); } @@ -5192,90 +5443,19 @@ [self updateSSLStatusForCurrentNavigationItem]; [self updateHTML5HistoryState]; if (!context->IsLoadingErrorPage() && !IsRestoreSessionUrl(webViewURL)) { - [self setNavigationItemTitle:[_webView title]]; + [self setNavigationItemTitle:self.webView.title]; } } // Report cases where SSL cert is missing for a secure connection. if (_documentURL.SchemeIsCryptographic()) { scoped_refptr<net::X509Certificate> cert; - cert = web::CreateCertFromTrust([_webView serverTrust]); + cert = web::CreateCertFromTrust(self.webView.serverTrust); UMA_HISTOGRAM_BOOLEAN("WebController.WKWebViewHasCertForSecureConnection", static_cast<bool>(cert)); } } -- (void)didFinishGoToIndexSameDocumentNavigationWithType: - (web::NavigationInitiationType)type - hasUserGesture:(BOOL)hasUserGesture { - web::NavigationItem* item = - _webStateImpl->GetNavigationManager()->GetLastCommittedItem(); - GURL URL = item->GetVirtualURL(); - std::unique_ptr<web::NavigationContextImpl> context = - web::NavigationContextImpl::CreateNavigationContext( - _webStateImpl, URL, hasUserGesture, - static_cast<ui::PageTransition>( - item->GetTransitionType() | - ui::PageTransition::PAGE_TRANSITION_FORWARD_BACK), - type == web::NavigationInitiationType::RENDERER_INITIATED); - context->SetIsSameDocument(true); - _webStateImpl->SetIsLoading(true); - _webStateImpl->OnNavigationStarted(context.get()); - [self updateHTML5HistoryState]; - [self setDocumentURL:URL context:context.get()]; - context->SetHasCommitted(true); - _webStateImpl->OnNavigationFinished(context.get()); - [self didFinishWithURL:URL loadSuccess:YES context:context.get()]; -} - -- (void)goToBackForwardListItem:(WKBackForwardListItem*)wk_item - navigationItem:(web::NavigationItem*)item - navigationInitiationType:(web::NavigationInitiationType)type - hasUserGesture:(BOOL)hasUserGesture { - WKNavigation* navigation = [_webView goToBackForwardListItem:wk_item]; - - GURL URL = net::GURLWithNSURL(wk_item.URL); - if (IsPlaceholderUrl(URL)) { - // No need to create navigation context for placeholder back forward - // navigations. Future callbacks do not expect that context will exist. - return; - } - - // This navigation can be an iframe navigation, but it's not possible to - // distinguish it from the main frame navigation, so context still has to be - // created. - std::unique_ptr<web::NavigationContextImpl> context = - web::NavigationContextImpl::CreateNavigationContext( - _webStateImpl, URL, hasUserGesture, - static_cast<ui::PageTransition>( - item->GetTransitionType() | - ui::PageTransition::PAGE_TRANSITION_FORWARD_BACK), - type == web::NavigationInitiationType::RENDERER_INITIATED); - context->SetNavigationItemUniqueID(item->GetUniqueID()); - if (!navigation) { - // goToBackForwardListItem: returns nil for same-document back forward - // navigations. - context->SetIsSameDocument(true); - } else { - _webStateImpl->SetIsLoading(true); - _loadPhase = web::LOAD_REQUESTED; - } - - web::WKBackForwardListItemHolder* holder = - web::WKBackForwardListItemHolder::FromNavigationItem(item); - holder->set_navigation_type(WKNavigationTypeBackForward); - context->SetIsPost((holder && [holder->http_method() isEqual:@"POST"]) || - item->HasPostData()); - - if (holder) { - context->SetMimeType(holder->mime_type()); - } - - [_navigationStates setContext:std::move(context) forNavigation:navigation]; - [_navigationStates setState:web::WKNavigationState::REQUESTED - forNavigation:navigation]; -} - - (void)webView:(WKWebView*)webView didFinishNavigation:(WKNavigation*)navigation { [self didReceiveWebViewNavigationDelegateCallback]; @@ -5476,8 +5656,20 @@ [self webViewWebProcessDidCrash]; } -#pragma mark - -#pragma mark CRWSSLStatusUpdater DataSource/Delegate Methods +#pragma mark - WKNavigationDelegate helper method + +// WKNavigation objects are used as a weak key to store web::NavigationContext. +// WKWebView manages WKNavigation lifetime and destroys them after the +// navigation is finished. However for window opening navigations WKWebView +// passes null WKNavigation to WKNavigationDelegate callbacks and strong key is +// used to store web::NavigationContext. Those "null" navigations have to be +// cleaned up manually by calling this method. +- (void)forgetNullWKNavigation:(WKNavigation*)navigation { + if (!navigation) + [_navigationStates removeNavigation:navigation]; +} + +#pragma mark - CRWSSLStatusUpdaterDataSource - (void)SSLStatusUpdater:(CRWSSLStatusUpdater*)SSLStatusUpdater querySSLStatusForTrust:(base::ScopedCFTypeRef<SecTrustRef>)trust @@ -5488,28 +5680,32 @@ completionHandler:completionHandler]; } +#pragma mark - CRWSSLStatusUpdaterDelegate + - (void)SSLStatusUpdater:(CRWSSLStatusUpdater*)SSLStatusUpdater didChangeSSLStatusForNavigationItem:(web::NavigationItem*)navigationItem { web::NavigationItem* visibleItem = - _webStateImpl->GetNavigationManager()->GetVisibleItem(); + self.webStateImpl->GetNavigationManager()->GetVisibleItem(); if (navigationItem == visibleItem) - _webStateImpl->DidChangeVisibleSecurityState(); + self.webStateImpl->DidChangeVisibleSecurityState(); } -#pragma mark - -#pragma mark CRWWebContextMenuControllerDelegate methods +#pragma mark - CRWContextMenuDelegate methods - (void)webView:(WKWebView*)webView handleContextMenu:(const web::ContextMenuParams&)params { - DCHECK(webView == _webView); + DCHECK(webView == self.webView); if (_isBeingDestroyed) { return; } self.webStateImpl->HandleContextMenu(params); } -#pragma mark - -#pragma mark CRWNativeContentDelegate methods +#pragma mark - CRWNativeContentDelegate methods + +- (void)nativeContent:(id)content titleDidChange:(NSString*)title { + [self setNavigationItemTitle:title]; +} - (void)nativeContent:(id)content handleContextMenu:(const web::ContextMenuParams&)params { @@ -5519,20 +5715,7 @@ self.webStateImpl->HandleContextMenu(params); } -#pragma mark - -#pragma mark CRWSessionControllerDelegate methods - -- (web::NavigationItemImpl*)pendingItemForSessionController: - (CRWSessionController*)sessionController { - WKNavigation* navigation = - [_navigationStates lastNavigationWithPendingItemInNavigationContext]; - if (!navigation) - return nullptr; - return [_navigationStates contextForNavigation:navigation] -> GetItem(); -} - -#pragma mark - -#pragma mark KVO Observation +#pragma mark - KVO Observation - (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object @@ -5557,12 +5740,15 @@ } } +// Called when WKWebView estimatedProgress has been changed. - (void)webViewEstimatedProgressDidChange { if (!_isBeingDestroyed) { - self.webStateImpl->SendChangeLoadProgress([_webView estimatedProgress]); + self.webStateImpl->SendChangeLoadProgress(self.webView.estimatedProgress); } } +// Called when WKWebView certificateChain or hasOnlySecureContent property has +// changed. - (void)webViewSecurityFeaturesDidChange { if (self.loadPhase == web::LOAD_REQUESTED) { // Do not update SSL Status for pending load. It will be updated in @@ -5572,11 +5758,12 @@ [self updateSSLStatusForCurrentNavigationItem]; } +// Called when WKWebView loading state has been changed. - (void)webViewLoadingStateDidChange { - if (_webView.loading) + if (self.webView.loading) return; - GURL webViewURL = net::GURLWithNSURL([_webView URL]); + GURL webViewURL = net::GURLWithNSURL(self.webView.URL); if (![self isCurrentNavigationBackForward]) return; @@ -5601,7 +5788,7 @@ if (web::GetWebClient()->IsSlimNavigationManagerEnabled() && IsRestoreSessionUrl(webViewURL)) { if (previousURLHasAboutScheme || is_back_forward_navigation) { - [_webView reload]; + [self.webView reload]; _loadPhase = web::LOAD_REQUESTED; return; } @@ -5635,7 +5822,7 @@ placeholderNavigation:IsPlaceholderUrl(webViewURL)]; [self webPageChangedWithContext:newContext.get()]; newContext->SetHasCommitted(!isSameDocumentNavigation); - _webStateImpl->OnNavigationFinished(newContext.get()); + self.webStateImpl->OnNavigationFinished(newContext.get()); // TODO(crbug.com/792515): It is OK, but very brittle, to call // |didFinishNavigation:| here because the gating condition is mutually // exclusive with the condition below. Refactor this method after @@ -5646,14 +5833,15 @@ } else { // Same document navigation does not contain response headers. net::HttpResponseHeaders* headers = - isSameDocumentNavigation ? nullptr - : _webStateImpl->GetHttpResponseHeaders(); + isSameDocumentNavigation + ? nullptr + : self.webStateImpl->GetHttpResponseHeaders(); existingContext->SetResponseHeaders(headers); existingContext->SetIsSameDocument(isSameDocumentNavigation); existingContext->SetHasCommitted(!isSameDocumentNavigation); - _webStateImpl->OnNavigationStarted(existingContext); + self.webStateImpl->OnNavigationStarted(existingContext); [self webPageChangedWithContext:existingContext]; - _webStateImpl->OnNavigationFinished(existingContext); + self.webStateImpl->OnNavigationFinished(existingContext); } } @@ -5661,11 +5849,12 @@ [self didFinishNavigation:existingContext]; } +// Called when WKWebView title has been changed. - (void)webViewTitleDidChange { // WKWebView's title becomes empty when the web process dies; ignore that // update. if (_webProcessCrashed) { - DCHECK_EQ([_webView title].length, 0U); + DCHECK_EQ(self.webView.title.length, 0U); return; } @@ -5677,28 +5866,30 @@ lastNavigationState == web::WKNavigationState::REDIRECTED; if (!hasPendingNavigation && - !IsPlaceholderUrl(net::GURLWithNSURL(_webView.URL))) { + !IsPlaceholderUrl(net::GURLWithNSURL(self.webView.URL))) { // Do not update the title if there is a navigation in progress because // there is no way to tell if KVO change fired for new or previous page. - [self setNavigationItemTitle:[_webView title]]; + [self setNavigationItemTitle:self.webView.title]; } } +// Called when WKWebView canGoForward/canGoBack state has been changed. - (void)webViewBackForwardStateDidChange { // Don't trigger for LegacyNavigationManager because its back/foward state // doesn't always match that of WKWebView. if (web::GetWebClient()->IsSlimNavigationManagerEnabled()) - _webStateImpl->OnBackForwardStateChanged(); + self.webStateImpl->OnBackForwardStateChanged(); } +// Called when WKWebView URL has been changed. - (void)webViewURLDidChange { // TODO(stuartmorgan): Determine if there are any cases where this still // happens, and if so whether anything should be done when it does. - if (![_webView URL]) { + if (!self.webView.URL) { DVLOG(1) << "Received nil URL callback"; return; } - GURL URL(net::GURLWithNSURL([_webView URL])); + GURL URL(net::GURLWithNSURL(self.webView.URL)); // URL changes happen at four points: // 1) When a load starts; at this point, the load is provisional, and // it should be ignored until it's committed, since the document/window @@ -5729,13 +5920,13 @@ // spoof the origin. On a document-changing URL change, the // window.location.href will match the previous URL at this stage, not the web // view's current URL. - if (![_webView isLoading]) { + if (!self.webView.loading) { if (_documentURL == URL) { if (![self isSafeBrowsingWarningDisplayedInWebView]) return; self.navigationManagerImpl->DiscardNonCommittedItems(); - _webStateImpl->SetIsLoading(false); + self.webStateImpl->SetIsLoading(false); _pendingNavigationInfo = nil; if (web::GetWebClient()->IsSlimNavigationManagerEnabled()) { // Right after a history navigation that gets cancelled by a tap on @@ -5746,35 +5937,37 @@ // WKBasedNavigationManagerImpl::WKWebViewCache::GetCurrentItemIndex() // will be the index of the unsafe page's item. To get back into a // consistent state, force a reload. - [_webView reload]; + [self.webView reload]; } else { // Tapping "Go Back" on a SafeBrowsing interstitial can change whether // there are any forward or back items, e.g., by returning to or // moving away from the forward-most or back-most item. - _webStateImpl->OnBackForwardStateChanged(); + self.webStateImpl->OnBackForwardStateChanged(); } return; } - // At this point, _webView, _webView.backForwardList.currentItem and its - // associated NavigationItem should all have the same URL, except in two + // At this point, self.webView, self.webView.backForwardList.currentItem and + // its associated NavigationItem should all have the same URL, except in two // edge cases: - // 1. location.replace that only changes hash: WebKit updates _webView.URL + // 1. location.replace that only changes hash: WebKit updates + // self.webView.URL // and currentItem.URL, and NavigationItem URL must be synced. - // 2. location.replace to about: URL: a WebKit bug causes only _webView.URL, + // 2. location.replace to about: URL: a WebKit bug causes only + // self.webView.URL, // but not currentItem.URL to be updated. NavigationItem URL should be - // synced to _webView.URL. + // synced to self.webView.URL. // This needs to be done before |URLDidChangeWithoutDocumentChange| so any // WebStateObserver callbacks will see the updated URL. - // TODO(crbug.com/809287) use currentItem.URL instead of _webView.URL to + // TODO(crbug.com/809287) use currentItem.URL instead of self.webView.URL to // update NavigationItem URL. if (web::GetWebClient()->IsSlimNavigationManagerEnabled()) { - const GURL webViewURL = net::GURLWithNSURL(_webView.URL); + const GURL webViewURL = net::GURLWithNSURL(self.webView.URL); web::NavigationItem* currentItem = nullptr; - if (_webView.backForwardList.currentItem) { + if (self.webView.backForwardList.currentItem) { currentItem = [[CRWNavigationItemHolder - holderForBackForwardListItem:_webView.backForwardList.currentItem] - navigationItem]; + holderForBackForwardListItem:self.webView.backForwardList + .currentItem] navigationItem]; } else { // WKBackForwardList.currentItem may be nil in a corner case when // location.replace is called with about:blank#hash in an empty window @@ -5791,12 +5984,12 @@ [self URLDidChangeWithoutDocumentChange:URL]; } else if ([self isKVOChangePotentialSameDocumentNavigationToURL:URL]) { WKNavigation* navigation = [_navigationStates lastAddedNavigation]; - [_webView + [self.webView evaluateJavaScript:@"window.location.href" completionHandler:^(id result, NSError* error) { // If the web view has gone away, or the location // couldn't be retrieved, abort. - if (!_webView || ![result isKindOfClass:[NSString class]]) { + if (!self.webView || ![result isKindOfClass:[NSString class]]) { return; } GURL JSURL(base::SysNSStringToUTF8(result)); @@ -5815,7 +6008,7 @@ // change occurs immediately after. Revisit heuristics to // prevent this. BOOL webViewURLMatchesNewURL = - net::GURLWithNSURL([_webView URL]) == URL; + net::GURLWithNSURL(self.webView.URL) == URL; // Check that the new URL is different from the current // document URL. If not, URL change should not be reported. BOOL URLDidChangeFromDocumentURL = URL != _documentURL; @@ -5841,6 +6034,12 @@ } } +#pragma mark - KVO helper methods + +// Returns YES if a KVO change to |newURL| could be a 'navigation' within the +// document (hash change, pushState/replaceState, etc.). This should only be +// used in the context of a URL KVO callback firing, and only if |isLoading| is +// YES for the web view (since if it's not, no guesswork is needed). - (BOOL)isKVOChangePotentialSameDocumentNavigationToURL:(const GURL&)newURL { // If the origin changes, it can't be same-document. if (_documentURL.GetOrigin().is_empty() || @@ -5859,8 +6058,10 @@ return YES; } +// Called when a non-document-changing URL change occurs. Updates the +// _documentURL, and informs the superclass of the change. - (void)URLDidChangeWithoutDocumentChange:(const GURL&)newURL { - DCHECK(newURL == net::GURLWithNSURL([_webView URL])); + DCHECK(newURL == net::GURLWithNSURL(self.webView.URL)); if (base::FeatureList::IsEnabled( web::features::kCrashOnUnexpectedURLChange)) { @@ -5922,7 +6123,7 @@ ? newNavigationContext->GetItem() : self.navigationManagerImpl->GetPendingItem(); if (pendingItem) - pendingItem->SetTitle(_webStateImpl->GetTitle()); + pendingItem->SetTitle(self.webStateImpl->GetTitle()); } } } @@ -5938,272 +6139,19 @@ [self contextForPendingMainFrameNavigationWithURL:newURL]; } navigationContext->SetIsSameDocument(true); - _webStateImpl->OnNavigationStarted(navigationContext); + self.webStateImpl->OnNavigationStarted(navigationContext); [self didStartLoading]; self.navigationManagerImpl->CommitPendingItem( navigationContext->ReleaseItem()); navigationContext->SetHasCommitted(true); - _webStateImpl->OnNavigationFinished(navigationContext); + self.webStateImpl->OnNavigationFinished(navigationContext); [self updateSSLStatusForCurrentNavigationItem]; [self didFinishNavigation:navigationContext]; } } -- (web::NavigationContextImpl*)contextForPendingMainFrameNavigationWithURL: - (const GURL&)URL { - // Here the enumeration variable |navigation| is __strong to allow setting it - // to nil. - for (__strong id navigation in [_navigationStates pendingNavigations]) { - if (navigation == [NSNull null]) { - // null is a valid navigation object passed to WKNavigationDelegate - // callbacks and represents window opening action. - navigation = nil; - } - - web::NavigationContextImpl* context = - [_navigationStates contextForNavigation:navigation]; - if (context && context->GetUrl() == URL) { - return context; - } - } - return nullptr; -} - -- (void)loadRequestForCurrentNavigationItem { - DCHECK(_webView); - DCHECK(self.currentNavItem); - // If a load is kicked off on a WKWebView with a frame whose size is {0, 0} or - // that has a negative dimension for a size, rendering issues occur that - // manifest in erroneous scrolling and tap handling (crbug.com/574996, - // crbug.com/577793). - DCHECK_GT(CGRectGetWidth([_webView frame]), 0.0); - DCHECK_GT(CGRectGetHeight([_webView frame]), 0.0); - - // If the current item uses a different user agent from that is currently used - // in the web view, update |customUserAgent| property, which will be used by - // the next request sent by this web view. - web::UserAgentType itemUserAgentType = - self.currentNavItem->GetUserAgentType(); - if (itemUserAgentType != web::UserAgentType::NONE) { - NSString* userAgentString = base::SysUTF8ToNSString( - web::GetWebClient()->GetUserAgent(itemUserAgentType)); - if (![_webView.customUserAgent isEqualToString:userAgentString]) { - _webView.customUserAgent = userAgentString; - } - } - - web::WKBackForwardListItemHolder* holder = - [self currentBackForwardListItemHolder]; - BOOL repostedForm = - [holder->http_method() isEqual:@"POST"] && - (holder->navigation_type() == WKNavigationTypeFormResubmitted || - holder->navigation_type() == WKNavigationTypeFormSubmitted); - web::NavigationItemImpl* currentItem = self.currentNavItem; - NSData* POSTData = currentItem->GetPostData(); - NSMutableURLRequest* request = [self requestForCurrentNavigationItem]; - - BOOL sameDocumentNavigation = currentItem->IsCreatedFromPushState() || - currentItem->IsCreatedFromHashChange(); - - if (holder->back_forward_list_item()) { - // Check if holder's WKBackForwardListItem still correctly represents - // navigation item. With LegacyNavigationManager, replaceState operation - // creates a new navigation item, leaving the old item committed. That - // old committed item will be associated with WKBackForwardListItem whose - // state was replaced. So old item won't have correct WKBackForwardListItem. - if (net::GURLWithNSURL(holder->back_forward_list_item().URL) != - currentItem->GetURL()) { - // The state was replaced for this item. The item should not be a part of - // committed items, but it's too late to remove the item. Cleaup - // WKBackForwardListItem and mark item with "state replaced" flag. - currentItem->SetHasStateBeenReplaced(true); - holder->set_back_forward_list_item(nil); - } - } - - // If the request has POST data and is not a repost form, configure and - // run the POST request. - if (POSTData.length && !repostedForm) { - [request setHTTPMethod:@"POST"]; - [request setHTTPBody:POSTData]; - [request setAllHTTPHeaderFields:self.currentHTTPHeaders]; - // As of iOS 11, WKWebView supports requests with POST data, so the - // Javascript POST workaround only needs to be used if the OS version is - // less than iOS 11. - // TODO(crbug.com/740987): Remove POST workaround once iOS 10 is dropped. - if (!base::ios::IsRunningOnIOS11OrLater()) { - GURL navigationURL = - currentItem ? currentItem->GetURL() : GURL::EmptyGURL(); - std::unique_ptr<web::NavigationContextImpl> navigationContext = - [self registerLoadRequestForURL:navigationURL - referrer:self.currentNavItemReferrer - transition:self.currentTransition - sameDocumentNavigation:sameDocumentNavigation - hasUserGesture:YES - rendererInitiated:NO - placeholderNavigation:NO]; - WKNavigation* navigation = [self loadPOSTRequest:request]; - [_navigationStates setContext:std::move(navigationContext) - forNavigation:navigation]; - [_navigationStates setState:web::WKNavigationState::REQUESTED - forNavigation:navigation]; - return; - } - } - - ProceduralBlock defaultNavigationBlock = ^{ - web::NavigationItem* item = self.currentNavItem; - GURL navigationURL = item ? item->GetURL() : GURL::EmptyGURL(); - GURL contextURL = IsPlaceholderUrl(navigationURL) - ? ExtractUrlFromPlaceholderUrl(navigationURL) - : navigationURL; - std::unique_ptr<web::NavigationContextImpl> navigationContext = - [self registerLoadRequestForURL:contextURL - referrer:self.currentNavItemReferrer - transition:self.currentTransition - sameDocumentNavigation:sameDocumentNavigation - hasUserGesture:YES - rendererInitiated:NO - placeholderNavigation:IsPlaceholderUrl(navigationURL)]; - - WKNavigation* navigation = nil; - GURL virtualURL = item ? item->GetVirtualURL() : GURL::EmptyGURL(); - if (navigationURL.SchemeIsFile() && - web::GetWebClient()->IsAppSpecificURL(virtualURL)) { - // file:// URL navigations are allowed for app-specific URLs, which - // already have elevated privileges. - NSURL* navigationNSURL = net::NSURLWithGURL(navigationURL); - navigation = [_webView loadFileURL:navigationNSURL - allowingReadAccessToURL:navigationNSURL]; - } else { - navigation = [_webView loadRequest:request]; - } - [_navigationStates setState:web::WKNavigationState::REQUESTED - forNavigation:navigation]; - [_navigationStates setContext:std::move(navigationContext) - forNavigation:navigation]; - [self reportBackForwardNavigationTypeForFastNavigation:NO]; - }; - - // When navigating via WKBackForwardListItem to pages created or updated by - // calls to pushState() and replaceState(), sometimes web_bundle.js is not - // injected correctly. This means that calling window.history navigation - // functions will invoke WKWebView's non-overridden implementations, causing a - // mismatch between the WKBackForwardList and NavigationManager. - // TODO(crbug.com/659816): Figure out how to prevent web_bundle.js injection - // flake. - if (currentItem->HasStateBeenReplaced() || - currentItem->IsCreatedFromPushState()) { - defaultNavigationBlock(); - return; - } - - // If there is no corresponding WKBackForwardListItem, or the item is not in - // the current WKWebView's back-forward list, navigating using WKWebView API - // is not possible. In this case, fall back to the default navigation - // mechanism. - if (!holder->back_forward_list_item() || - ![self isBackForwardListItemValid:holder->back_forward_list_item()]) { - defaultNavigationBlock(); - return; - } - - ProceduralBlock webViewNavigationBlock = ^{ - // If the current navigation URL is the same as the URL of the visible - // page, that means the user requested a reload. |goToBackForwardListItem| - // will be a no-op when it is passed the current back forward list item, - // so |reload| must be explicitly called. - web::NavigationItem* item = self.currentNavItem; - GURL navigationURL = item ? item->GetURL() : GURL::EmptyGURL(); - std::unique_ptr<web::NavigationContextImpl> navigationContext = - [self registerLoadRequestForURL:navigationURL - referrer:self.currentNavItemReferrer - transition:self.currentTransition - sameDocumentNavigation:sameDocumentNavigation - hasUserGesture:YES - rendererInitiated:NO - placeholderNavigation:NO]; - WKNavigation* navigation = nil; - if (navigationURL == net::GURLWithNSURL([_webView URL])) { - navigation = [_webView reload]; - } else { - // |didCommitNavigation:| may not be called for fast navigation, so update - // the navigation type now as it is already known. - navigationContext->SetWKNavigationType(WKNavigationTypeBackForward); - navigationContext->SetMimeType(holder->mime_type()); - holder->set_navigation_type(WKNavigationTypeBackForward); - navigation = - [_webView goToBackForwardListItem:holder->back_forward_list_item()]; - [self reportBackForwardNavigationTypeForFastNavigation:YES]; - } - [_navigationStates setState:web::WKNavigationState::REQUESTED - forNavigation:navigation]; - [_navigationStates setContext:std::move(navigationContext) - forNavigation:navigation]; - }; - - // If the request is not a form submission or resubmission, or the user - // doesn't need to confirm the load, then continue right away. - - if (!repostedForm || currentItem->ShouldSkipRepostFormConfirmation()) { - webViewNavigationBlock(); - return; - } - - // If the request is form submission or resubmission, then prompt the - // user before proceeding. - DCHECK(repostedForm); - DCHECK(!web::GetWebClient()->IsSlimNavigationManagerEnabled()); - _webStateImpl->ShowRepostFormWarningDialog( - base::BindOnce(^(bool shouldContinue) { - if (_isBeingDestroyed) - return; - - if (shouldContinue) - webViewNavigationBlock(); - else - [self stopLoading]; - })); -} - -- (void)reportBackForwardNavigationTypeForFastNavigation:(BOOL)isFast { - // TODO(crbug.com/665189): Use NavigationManager::GetPendingItemIndex() once - // it returns correct result. - int pendingIndex = self.sessionController.pendingItemIndex; - if (pendingIndex == -1) { - // Pending navigation is not a back forward navigation. - return; - } - - BOOL isBack = - pendingIndex < self.navigationManagerImpl->GetLastCommittedItemIndex(); - BackForwardNavigationType type = BackForwardNavigationType::FAST_BACK; - if (isBack) { - type = isFast ? BackForwardNavigationType::FAST_BACK - : BackForwardNavigationType::SLOW_BACK; - } else { - type = isFast ? BackForwardNavigationType::FAST_FORWARD - : BackForwardNavigationType::SLOW_FORWARD; - } - - UMA_HISTOGRAM_ENUMERATION( - "Navigation.IOSWKWebViewSlowFastBackForward", type, - BackForwardNavigationType::BACK_FORWARD_NAVIGATION_TYPE_COUNT); -} - -- (void)setAllowsBackForwardNavigationGestures: - (BOOL)allowsBackForwardNavigationGestures { - // Store it to an instance variable as well as - // _webView.allowsBackForwardNavigationGestures because _webView may be nil. - // When _webView is nil, it will be set later in -setWebView:. - _allowsBackForwardNavigationGestures = allowsBackForwardNavigationGestures; - _webView.allowsBackForwardNavigationGestures = - allowsBackForwardNavigationGestures; -} - -#pragma mark - -#pragma mark Testing-Only Methods +#pragma mark - Testing-Only Methods - (void)injectWebViewContentView:(CRWWebViewContentView*)webViewContentView { _currentURLLoadWasTrigerred = NO;
diff --git a/ios/web/web_state/web_state_observer_inttest.mm b/ios/web/web_state/web_state_observer_inttest.mm index 349d5b40..434fc67 100644 --- a/ios/web/web_state/web_state_observer_inttest.mm +++ b/ios/web/web_state/web_state_observer_inttest.mm
@@ -1895,7 +1895,12 @@ // Tests server redirect navigation. TEST_P(WebStateObserverTest, RedirectNavigation) { - const GURL url = test_server_->GetURL("/server-redirect?echoall"); + const GURL url = test_server_->GetURL("/server-redirect-301?" + "server-redirect-302?" + "server-redirect-303?" + "server-redirect-307?" + "server-redirect-308?" + "echoall"); const GURL redirect_url = test_server_->GetURL("/echoall"); // Load url which replies with redirect. @@ -1912,14 +1917,17 @@ .WillOnce(VerifyPageStartedContext( web_state(), url, ui::PageTransition::PAGE_TRANSITION_TYPED, &context, &nav_id)); - // Second ShouldAllowRequest call is for redirect_url. + + // 5 calls on ShouldAllowRequest for redirections. WebStatePolicyDecider::RequestInfo expected_redirect_request_info( ui::PageTransition::PAGE_TRANSITION_CLIENT_REDIRECT, /*target_main_frame=*/true, /*has_user_gesture=*/false); EXPECT_CALL( *decider_, ShouldAllowRequest(_, RequestInfoMatch(expected_redirect_request_info))) - .WillOnce(Return(true)); + .Times(5) + .WillRepeatedly(Return(true)); + EXPECT_CALL(*decider_, ShouldAllowResponse(_, /*for_main_frame=*/true)) .WillOnce(Return(true)); EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _))
diff --git a/ios/web_view/internal/web_view_web_main_parts.mm b/ios/web_view/internal/web_view_web_main_parts.mm index a5a901a1..06b549af 100644 --- a/ios/web_view/internal/web_view_web_main_parts.mm +++ b/ios/web_view/internal/web_view_web_main_parts.mm
@@ -53,7 +53,6 @@ std::string enable_features = base::JoinString( {autofill::features::kAutofillEnableAccountWalletStorage.name, autofill::features::kAutofillAlwaysShowServerCardsInSyncTransport.name, - switches::kSyncStandaloneTransport.name, switches::kSyncSupportSecondaryAccount.name, switches::kSyncUSSAutofillWalletData.name}, ",");
diff --git a/net/BUILD.gn b/net/BUILD.gn index 96c801b..6838a451 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -6402,9 +6402,7 @@ sources = [ "reporting/reporting_policy.proto", ] - deps = [ - "//testing/libfuzzer/proto:json_proto", - ] + link_deps = [ "//testing/libfuzzer/proto:json_proto" ] } fuzzer_test("net_reporting_header_parser_fuzzer") {
diff --git a/net/cert/internal/cert_error_params.cc b/net/cert/internal/cert_error_params.cc index 851f8e3..f454572 100644 --- a/net/cert/internal/cert_error_params.cc +++ b/net/cert/internal/cert_error_params.cc
@@ -4,6 +4,8 @@ #include "net/cert/internal/cert_error_params.h" +#include <memory> + #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "net/der/input.h"
diff --git a/net/cert/internal/path_builder.cc b/net/cert/internal/path_builder.cc index 4c0f933a..fcc73fc 100644 --- a/net/cert/internal/path_builder.cc +++ b/net/cert/internal/path_builder.cc
@@ -4,6 +4,7 @@ #include "net/cert/internal/path_builder.h" +#include <memory> #include <set> #include <unordered_set>
diff --git a/net/dns/dns_test_util.cc b/net/dns/dns_test_util.cc index 701d8d5..b02fa0876 100644 --- a/net/dns/dns_test_util.cc +++ b/net/dns/dns_test_util.cc
@@ -127,7 +127,7 @@ for (std::string text_string : text_strings) { DCHECK(!text_string.empty()); - rdata += base::checked_cast<char>(text_string.size()); + rdata += base::checked_cast<unsigned char>(text_string.size()); rdata += std::move(text_string); } record.SetOwnedRdata(std::move(rdata)); @@ -186,6 +186,7 @@ MockTransaction(const MockDnsClientRuleList& rules, const std::string& hostname, uint16_t qtype, + SecureDnsMode secure_dns_mode, DnsTransactionFactory::CallbackType callback) : result_(MockDnsClientRule::FAIL), hostname_(hostname), @@ -194,10 +195,13 @@ secure_(false), started_(false), delayed_(false) { - // Find the relevant rule which matches |qtype| and prefix of |hostname|. + // Find the relevant rule which matches |qtype|, |secure_dns_mode|, and + // prefix of |hostname|. for (size_t i = 0; i < rules.size(); ++i) { const std::string& prefix = rules[i].prefix; - if ((rules[i].qtype == qtype) && (hostname.size() >= prefix.size()) && + if ((rules[i].qtype == qtype) && + rules[i].secure_dns_mode == secure_dns_mode && + (hostname.size() >= prefix.size()) && (hostname.compare(0, prefix.size(), prefix) == 0)) { const MockDnsClientRule::Result* result = &rules[i].result; result_ = MockDnsClientRule::Result(result->type); @@ -432,6 +436,14 @@ MockDnsClientRule::Result& MockDnsClientRule::Result::operator=( Result&& result) = default; +// static +MockDnsClientRule::Result MockDnsClientRule::CreateSecureResult( + std::unique_ptr<DnsResponse> response) { + auto result = Result(std::move(response)); + result.secure = true; + return result; +} + // A DnsTransactionFactory which creates MockTransaction. class MockDnsClient::MockTransactionFactory : public DnsTransactionFactory { public: @@ -445,18 +457,16 @@ uint16_t qtype, DnsTransactionFactory::CallbackType callback, const NetLogWithSource&, - SecureDnsMode) override { + SecureDnsMode secure_dns_mode) override { std::unique_ptr<MockTransaction> transaction = std::make_unique<MockTransaction>(rules_, hostname, qtype, - std::move(callback)); + secure_dns_mode, std::move(callback)); if (transaction->delayed()) delayed_transactions_.push_back(transaction->AsWeakPtr()); return transaction; } - void AddEDNSOption(const OptRecordRdata::Opt& opt) override { - NOTREACHED() << "Not implemented"; - } + void AddEDNSOption(const OptRecordRdata::Opt& opt) override {} void CompleteDelayedTransactions() { DelayedTransactionList old_delayed_transactions;
diff --git a/net/dns/dns_test_util.h b/net/dns/dns_test_util.h index a72cbfae..f8a990b 100644 --- a/net/dns/dns_test_util.h +++ b/net/dns/dns_test_util.h
@@ -17,6 +17,7 @@ #include "net/dns/dns_client.h" #include "net/dns/dns_config.h" #include "net/dns/dns_response.h" +#include "net/dns/dns_util.h" #include "net/dns/public/dns_protocol.h" namespace net { @@ -215,20 +216,25 @@ bool secure = false; }; + static Result CreateSecureResult(std::unique_ptr<DnsResponse> response); + // If |delay| is true, matching transactions will be delayed until triggered // by the consumer. MockDnsClientRule(const std::string& prefix_arg, uint16_t qtype_arg, + SecureDnsMode secure_dns_mode, Result result_arg, bool delay) : result(std::move(result_arg)), prefix(prefix_arg), qtype(qtype_arg), + secure_dns_mode(secure_dns_mode), delay(delay) {} Result result; std::string prefix; uint16_t qtype; + SecureDnsMode secure_dns_mode; bool delay; };
diff --git a/net/dns/host_resolver.h b/net/dns/host_resolver.h index 040bcb4..72a1f8a 100644 --- a/net/dns/host_resolver.h +++ b/net/dns/host_resolver.h
@@ -261,14 +261,15 @@ // Checks whether this HostResolver has cached a resolution for the given // hostname (or IP address literal). If so, returns true and writes the source - // of the resolution (e.g. DNS, HOSTS file, etc.) to |source_out| and the - // staleness of the resolution to |stale_out| (if they are not null). - // It tries using two common address_family and host_resolver_flag - // combinations when checking the cache; this means false negatives are - // possible, but unlikely. + // of the resolution (e.g. DNS, HOSTS file, etc.) to |source_out|, the + // staleness of the resolution to |stale_out|, and whether the result was + // retrieved securely or not to |secure_out| (if they are not null). It tries + // using two common address_family and host_resolver_flag combinations when + // checking the cache; this means false negatives are possible, but unlikely. virtual bool HasCached(base::StringPiece hostname, HostCache::Entry::Source* source_out, - HostCache::EntryStaleness* stale_out) const = 0; + HostCache::EntryStaleness* stale_out, + bool* secure_out) const = 0; // Returns the current DNS configuration |this| is using, as a Value, or // nullptr if it's configured to always use the system host resolver.
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc index 6e38743..d0c75fa 100644 --- a/net/dns/host_resolver_impl.cc +++ b/net/dns/host_resolver_impl.cc
@@ -2273,11 +2273,16 @@ bool HostResolverImpl::HasCached(base::StringPiece hostname, HostCache::Entry::Source* source_out, - HostCache::EntryStaleness* stale_out) const { + HostCache::EntryStaleness* stale_out, + bool* secure_out) const { if (!cache_) return false; - return !!cache_->GetMatchingKey(hostname, source_out, stale_out); + const HostCache::Key* key = + cache_->GetMatchingKey(hostname, source_out, stale_out); + if (key && secure_out != nullptr) + *secure_out = key->secure; + return !!key; } std::unique_ptr<base::Value> HostResolverImpl::GetDnsConfigAsValue() const {
diff --git a/net/dns/host_resolver_impl.h b/net/dns/host_resolver_impl.h index 149f9b9..893aeceb 100644 --- a/net/dns/host_resolver_impl.h +++ b/net/dns/host_resolver_impl.h
@@ -153,7 +153,8 @@ HostCache* GetHostCache() override; bool HasCached(base::StringPiece hostname, HostCache::Entry::Source* source_out, - HostCache::EntryStaleness* stale_out) const override; + HostCache::EntryStaleness* stale_out, + bool* secure_out) const override; std::unique_ptr<base::Value> GetDnsConfigAsValue() const override;
diff --git a/net/dns/host_resolver_impl_unittest.cc b/net/dns/host_resolver_impl_unittest.cc index 2bfba68..1238156 100644 --- a/net/dns/host_resolver_impl_unittest.cc +++ b/net/dns/host_resolver_impl_unittest.cc
@@ -2918,8 +2918,8 @@ uint16_t qtype, MockDnsClientRule::ResultType result_type, bool delay) { - rules->emplace_back(prefix, qtype, MockDnsClientRule::Result(result_type), - delay); + rules->emplace_back(prefix, qtype, SecureDnsMode::AUTOMATIC, + MockDnsClientRule::Result(result_type), delay); } static void AddDnsRule(MockDnsClientRuleList* rules, @@ -2927,7 +2927,7 @@ uint16_t qtype, const IPAddress& result_ip, bool delay) { - rules->emplace_back(prefix, qtype, + rules->emplace_back(prefix, qtype, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result( BuildTestDnsResponse(prefix, std::move(result_ip))), delay); @@ -2940,7 +2940,7 @@ std::string cannonname, bool delay) { rules->emplace_back( - prefix, qtype, + prefix, qtype, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(BuildTestDnsResponse( prefix, std::move(result_ip), std::move(cannonname))), delay); @@ -2953,7 +2953,8 @@ bool delay) { MockDnsClientRule::Result result(result_type); result.secure = true; - rules->emplace_back(prefix, qtype, std::move(result), delay); + rules->emplace_back(prefix, qtype, SecureDnsMode::AUTOMATIC, + std::move(result), delay); } void ChangeDnsConfig(const DnsConfig& config) { @@ -3470,9 +3471,9 @@ TEST_F(HostResolverImplDnsTest, BypassDnsToMdnsWithNonAddress) { // Ensure DNS task and system (proc) requests will fail. MockDnsClientRuleList rules; - rules.emplace_back("myhello.local", dns_protocol::kTypeTXT, - MockDnsClientRule::Result(MockDnsClientRule::FAIL), - false /* delay */); + rules.emplace_back( + "myhello.local", dns_protocol::kTypeTXT, SecureDnsMode::AUTOMATIC, + MockDnsClientRule::Result(MockDnsClientRule::FAIL), false /* delay */); CreateResolver(); UseMockDnsClient(CreateValidDnsConfig(), std::move(rules)); proc_->AddRuleForAllFamilies(std::string(), std::string()); @@ -5004,7 +5005,7 @@ bar_records}; MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeTXT, + rules.emplace_back("host", dns_protocol::kTypeTXT, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result( BuildTestDnsResponse("host", std::move(text_records))), false /* delay */); @@ -5041,7 +5042,7 @@ proc_->SignalMultiple(1u); MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeTXT, + rules.emplace_back("host", dns_protocol::kTypeTXT, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(MockDnsClientRule::NODOMAIN), false /* delay */); @@ -5066,7 +5067,7 @@ proc_->SignalMultiple(1u); MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeTXT, + rules.emplace_back("host", dns_protocol::kTypeTXT, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(MockDnsClientRule::FAIL), false /* delay */); @@ -5091,7 +5092,7 @@ proc_->SignalMultiple(1u); MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeTXT, + rules.emplace_back("host", dns_protocol::kTypeTXT, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(MockDnsClientRule::TIMEOUT), false /* delay */); @@ -5116,7 +5117,7 @@ proc_->SignalMultiple(1u); MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeTXT, + rules.emplace_back("host", dns_protocol::kTypeTXT, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(MockDnsClientRule::EMPTY), false /* delay */); @@ -5141,7 +5142,7 @@ proc_->SignalMultiple(1u); MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeTXT, + rules.emplace_back("host", dns_protocol::kTypeTXT, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(MockDnsClientRule::MALFORMED), false /* delay */); @@ -5162,7 +5163,7 @@ TEST_F(HostResolverImplDnsTest, TxtQuery_MismatchedName) { std::vector<std::vector<std::string>> text_records = {{"text"}}; MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeTXT, + rules.emplace_back("host", dns_protocol::kTypeTXT, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(BuildTestDnsResponse( "host", std::move(text_records), "not.host")), false /* delay */); @@ -5184,7 +5185,7 @@ TEST_F(HostResolverImplDnsTest, TxtQuery_WrongType) { // Respond to a TXT query with an A response. MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeTXT, + rules.emplace_back("host", dns_protocol::kTypeTXT, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result( BuildTestDnsResponse("host", IPAddress(1, 2, 3, 4))), false /* delay */); @@ -5216,7 +5217,7 @@ bar_records}; MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeTXT, + rules.emplace_back("host", dns_protocol::kTypeTXT, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result( BuildTestDnsResponse("host", std::move(text_records))), false /* delay */); @@ -5249,7 +5250,7 @@ TEST_F(HostResolverImplDnsTest, PtrQuery) { MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypePTR, + rules.emplace_back("host", dns_protocol::kTypePTR, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(BuildTestDnsPointerResponse( "host", {"foo.com", "bar.com"})), false /* delay */); @@ -5275,6 +5276,7 @@ TEST_F(HostResolverImplDnsTest, PtrQuery_Ip) { MockDnsClientRuleList rules; rules.emplace_back("8.8.8.8", dns_protocol::kTypePTR, + SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(BuildTestDnsPointerResponse( "8.8.8.8", {"foo.com", "bar.com"})), false /* delay */); @@ -5304,7 +5306,7 @@ proc_->SignalMultiple(1u); MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypePTR, + rules.emplace_back("host", dns_protocol::kTypePTR, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(MockDnsClientRule::NODOMAIN), false /* delay */); @@ -5329,7 +5331,7 @@ proc_->SignalMultiple(1u); MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypePTR, + rules.emplace_back("host", dns_protocol::kTypePTR, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(MockDnsClientRule::FAIL), false /* delay */); @@ -5354,7 +5356,7 @@ proc_->SignalMultiple(1u); MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypePTR, + rules.emplace_back("host", dns_protocol::kTypePTR, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(MockDnsClientRule::TIMEOUT), false /* delay */); @@ -5379,7 +5381,7 @@ proc_->SignalMultiple(1u); MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypePTR, + rules.emplace_back("host", dns_protocol::kTypePTR, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(MockDnsClientRule::EMPTY), false /* delay */); @@ -5404,7 +5406,7 @@ proc_->SignalMultiple(1u); MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypePTR, + rules.emplace_back("host", dns_protocol::kTypePTR, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(MockDnsClientRule::MALFORMED), false /* delay */); @@ -5425,7 +5427,7 @@ TEST_F(HostResolverImplDnsTest, PtrQuery_MismatchedName) { std::vector<std::string> ptr_records = {{"foo.com"}}; MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypePTR, + rules.emplace_back("host", dns_protocol::kTypePTR, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(BuildTestDnsPointerResponse( "host", std::move(ptr_records), "not.host")), false /* delay */); @@ -5447,7 +5449,7 @@ TEST_F(HostResolverImplDnsTest, PtrQuery_WrongType) { // Respond to a TXT query with an A response. MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypePTR, + rules.emplace_back("host", dns_protocol::kTypePTR, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result( BuildTestDnsResponse("host", IPAddress(1, 2, 3, 4))), false /* delay */); @@ -5473,7 +5475,7 @@ // involved. TEST_F(HostResolverImplDnsTest, PtrDnsQuery) { MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypePTR, + rules.emplace_back("host", dns_protocol::kTypePTR, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(BuildTestDnsPointerResponse( "host", {"foo.com", "bar.com"})), false /* delay */); @@ -5503,7 +5505,7 @@ const TestServiceRecord kRecord3 = {5, 1, 5, "google.com"}; const TestServiceRecord kRecord4 = {2, 100, 12345, "chromium.org"}; MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeSRV, + rules.emplace_back("host", dns_protocol::kTypeSRV, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(BuildTestDnsResponse( "host", {kRecord1, kRecord2, kRecord3, kRecord4})), false /* delay */); @@ -5546,7 +5548,7 @@ const TestServiceRecord kRecord1 = {5, 0, 80, "bar.com"}; const TestServiceRecord kRecord2 = {5, 0, 5, "google.com"}; MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeSRV, + rules.emplace_back("host", dns_protocol::kTypeSRV, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result( BuildTestDnsResponse("host", {kRecord1, kRecord2})), false /* delay */); @@ -5576,7 +5578,7 @@ proc_->SignalMultiple(1u); MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeSRV, + rules.emplace_back("host", dns_protocol::kTypeSRV, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(MockDnsClientRule::NODOMAIN), false /* delay */); @@ -5601,7 +5603,7 @@ proc_->SignalMultiple(1u); MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeSRV, + rules.emplace_back("host", dns_protocol::kTypeSRV, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(MockDnsClientRule::FAIL), false /* delay */); @@ -5626,7 +5628,7 @@ proc_->SignalMultiple(1u); MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeSRV, + rules.emplace_back("host", dns_protocol::kTypeSRV, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(MockDnsClientRule::TIMEOUT), false /* delay */); @@ -5651,7 +5653,7 @@ proc_->SignalMultiple(1u); MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeSRV, + rules.emplace_back("host", dns_protocol::kTypeSRV, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(MockDnsClientRule::EMPTY), false /* delay */); @@ -5676,7 +5678,7 @@ proc_->SignalMultiple(1u); MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeSRV, + rules.emplace_back("host", dns_protocol::kTypeSRV, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(MockDnsClientRule::MALFORMED), false /* delay */); @@ -5697,7 +5699,7 @@ TEST_F(HostResolverImplDnsTest, SrvQuery_MismatchedName) { std::vector<TestServiceRecord> srv_records = {{1, 2, 3, "foo.com"}}; MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeSRV, + rules.emplace_back("host", dns_protocol::kTypeSRV, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(BuildTestDnsResponse( "host", std::move(srv_records), "not.host")), false /* delay */); @@ -5719,7 +5721,7 @@ TEST_F(HostResolverImplDnsTest, SrvQuery_WrongType) { // Respond to a SRV query with an A response. MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeSRV, + rules.emplace_back("host", dns_protocol::kTypeSRV, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result( BuildTestDnsResponse("host", IPAddress(1, 2, 3, 4))), false /* delay */); @@ -5749,7 +5751,7 @@ const TestServiceRecord kRecord3 = {5, 1, 5, "google.com"}; const TestServiceRecord kRecord4 = {2, 100, 12345, "chromium.org"}; MockDnsClientRuleList rules; - rules.emplace_back("host", dns_protocol::kTypeSRV, + rules.emplace_back("host", dns_protocol::kTypeSRV, SecureDnsMode::AUTOMATIC, MockDnsClientRule::Result(BuildTestDnsResponse( "host", {kRecord1, kRecord2, kRecord3, kRecord4})), false /* delay */);
diff --git a/net/dns/mapped_host_resolver.cc b/net/dns/mapped_host_resolver.cc index a0f1339..04667430 100644 --- a/net/dns/mapped_host_resolver.cc +++ b/net/dns/mapped_host_resolver.cc
@@ -80,8 +80,9 @@ bool MappedHostResolver::HasCached(base::StringPiece hostname, HostCache::Entry::Source* source_out, - HostCache::EntryStaleness* stale_out) const { - return impl_->HasCached(hostname, source_out, stale_out); + HostCache::EntryStaleness* stale_out, + bool* secure_out) const { + return impl_->HasCached(hostname, source_out, stale_out, secure_out); } std::unique_ptr<base::Value> MappedHostResolver::GetDnsConfigAsValue() const {
diff --git a/net/dns/mapped_host_resolver.h b/net/dns/mapped_host_resolver.h index f3968c65..a3b5872 100644 --- a/net/dns/mapped_host_resolver.h +++ b/net/dns/mapped_host_resolver.h
@@ -57,7 +57,8 @@ HostCache* GetHostCache() override; bool HasCached(base::StringPiece hostname, HostCache::Entry::Source* source_out, - HostCache::EntryStaleness* stale_out) const override; + HostCache::EntryStaleness* stale_out, + bool* secure_out) const override; std::unique_ptr<base::Value> GetDnsConfigAsValue() const override; void SetNoIPv6OnWifi(bool no_ipv6_on_wifi) override; bool GetNoIPv6OnWifi() override;
diff --git a/net/dns/mock_host_resolver.cc b/net/dns/mock_host_resolver.cc index 160f82e..0b61518c 100644 --- a/net/dns/mock_host_resolver.cc +++ b/net/dns/mock_host_resolver.cc
@@ -288,14 +288,18 @@ return cache_.get(); } -bool MockHostResolverBase::HasCached( - base::StringPiece hostname, - HostCache::Entry::Source* source_out, - HostCache::EntryStaleness* stale_out) const { +bool MockHostResolverBase::HasCached(base::StringPiece hostname, + HostCache::Entry::Source* source_out, + HostCache::EntryStaleness* stale_out, + bool* secure_out) const { if (!cache_) return false; - return !!cache_->GetMatchingKey(hostname, source_out, stale_out); + const HostCache::Key* key = + cache_->GetMatchingKey(hostname, source_out, stale_out); + if (key && secure_out != nullptr) + *secure_out = key->secure; + return !!key; } int MockHostResolverBase::LoadIntoCache( @@ -918,10 +922,10 @@ is_local_only); } -bool HangingHostResolver::HasCached( - base::StringPiece hostname, - HostCache::Entry::Source* source_out, - HostCache::EntryStaleness* stale_out) const { +bool HangingHostResolver::HasCached(base::StringPiece hostname, + HostCache::Entry::Source* source_out, + HostCache::EntryStaleness* stale_out, + bool* secure_out) const { return false; }
diff --git a/net/dns/mock_host_resolver.h b/net/dns/mock_host_resolver.h index 3b60b19..798a7e5 100644 --- a/net/dns/mock_host_resolver.h +++ b/net/dns/mock_host_resolver.h
@@ -122,7 +122,8 @@ HostCache* GetHostCache() override; bool HasCached(base::StringPiece hostname, HostCache::Entry::Source* source_out, - HostCache::EntryStaleness* stale_out) const override; + HostCache::EntryStaleness* stale_out, + bool* secure_out) const override; void SetDnsConfigOverrides(const DnsConfigOverrides& overrides) override {} // Preloads the cache with what would currently be the result of a request @@ -414,7 +415,8 @@ override; bool HasCached(base::StringPiece hostname, HostCache::Entry::Source* source_out, - HostCache::EntryStaleness* stale_out) const override; + HostCache::EntryStaleness* stale_out, + bool* secure_out) const override; // Use to detect cancellations since there's otherwise no externally-visible // differentiation between a cancelled and a hung task.
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc index 786ff57..19eaa7e 100644 --- a/net/http/http_stream_parser.cc +++ b/net/http/http_stream_parser.cc
@@ -199,7 +199,7 @@ http_09_on_non_default_ports_enabled_(false), read_buf_(read_buffer), read_buf_unused_offset_(0), - response_header_start_offset_(-1), + response_header_start_offset_(std::string::npos), received_bytes_(0), sent_bytes_(0), response_(nullptr), @@ -820,7 +820,7 @@ // Accepting truncated headers over HTTPS is a potential security // vulnerability, so just return an error in that case. // - // If response_header_start_offset_ is -1, this may be a < 8 + // If response_header_start_offset_ is std::string::npos, this may be a < 8 // byte HTTP/0.9 response. However, accepting such a response over HTTPS // would allow a MITM to truncate an HTTP/1.x status line to look like a // short HTTP/0.9 response if the peer put a record boundary at the first 8 @@ -838,7 +838,7 @@ // Parse things as well as we can and let the caller decide what to do. int end_offset; - if (response_header_start_offset_ >= 0) { + if (response_header_start_offset_ != std::string::npos) { // The response looks to be a truncated set of HTTP headers. io_state_ = STATE_READ_BODY_COMPLETE; end_offset = read_buf_->offset(); @@ -910,7 +910,7 @@ // request so we return OK here, which lets the caller inspect the // response and reject it in the event that we're setting up a CONNECT // tunnel. - response_header_start_offset_ = -1; + response_header_start_offset_ = std::string::npos; response_body_length_ = -1; // Now waiting for the second set of headers to be read. } else { @@ -935,23 +935,25 @@ int HttpStreamParser::FindAndParseResponseHeaders(int new_bytes) { DCHECK_GT(new_bytes, 0); DCHECK_EQ(0, read_buf_unused_offset_); - int end_offset = -1; + size_t end_offset = std::string::npos; // Look for the start of the status line, if it hasn't been found yet. - if (response_header_start_offset_ < 0) { + if (response_header_start_offset_ == std::string::npos) { response_header_start_offset_ = HttpUtil::LocateStartOfStatusLine( read_buf_->StartOfBuffer(), read_buf_->offset()); } - if (response_header_start_offset_ >= 0) { + if (response_header_start_offset_ != std::string::npos) { // LocateEndOfHeaders looks for two line breaks in a row (With or without // carriage returns). So the end of the headers includes at most the last 3 // bytes of the buffer from the past read. This optimization avoids O(n^2) // performance in the case each read only returns a couple bytes. It's not // too important in production, but for fuzzers with memory instrumentation, // it's needed to avoid timing out. - int search_start = std::max(response_header_start_offset_, - read_buf_->offset() - new_bytes - 3); + size_t lower_bound = + (base::ClampedNumeric<size_t>(read_buf_->offset()) - new_bytes - 3) + .RawValue(); + size_t search_start = std::max(response_header_start_offset_, lower_bound); end_offset = HttpUtil::LocateEndOfHeaders( read_buf_->StartOfBuffer(), read_buf_->offset(), search_start); } else if (read_buf_->offset() >= 8) { @@ -960,7 +962,7 @@ end_offset = 0; } - if (end_offset == -1) + if (end_offset == std::string::npos) return -1; int rv = ParseResponseHeaders(end_offset); @@ -973,7 +975,7 @@ scoped_refptr<HttpResponseHeaders> headers; DCHECK_EQ(0, read_buf_unused_offset_); - if (response_header_start_offset_ >= 0) { + if (response_header_start_offset_ != std::string::npos) { received_bytes_ += end_offset; headers = HttpResponseHeaders::TryToCreate( base::StringPiece(read_buf_->StartOfBuffer(), end_offset));
diff --git a/net/http/http_stream_parser.h b/net/http/http_stream_parser.h index 6ca4b5b5..c09a709 100644 --- a/net/http/http_stream_parser.h +++ b/net/http/http_stream_parser.h
@@ -228,8 +228,8 @@ int read_buf_unused_offset_; // The amount beyond |read_buf_unused_offset_| where the status line starts; - // -1 if not found yet. - int response_header_start_offset_; + // std::string::npos if not found yet. + size_t response_header_start_offset_; // The amount of received data. If connection is reused then intermediate // value may be bigger than final.
diff --git a/net/http/http_util.cc b/net/http/http_util.cc index 2baf637..6d9c6e63 100644 --- a/net/http/http_util.cc +++ b/net/http/http_util.cc
@@ -641,27 +641,27 @@ // Find the "http" substring in a status line. This allows for // some slop at the start. If the "http" string could not be found -// then returns -1. +// then returns std::string::npos. // static -int HttpUtil::LocateStartOfStatusLine(const char* buf, int buf_len) { - const int slop = 4; - const int http_len = 4; +size_t HttpUtil::LocateStartOfStatusLine(const char* buf, size_t buf_len) { + const size_t slop = 4; + const size_t http_len = 4; if (buf_len >= http_len) { - int i_max = std::min(buf_len - http_len, slop); - for (int i = 0; i <= i_max; ++i) { + size_t i_max = std::min(buf_len - http_len, slop); + for (size_t i = 0; i <= i_max; ++i) { if (base::LowerCaseEqualsASCII(base::StringPiece(buf + i, http_len), "http")) return i; } } - return -1; // Not found + return std::string::npos; // Not found } -static int LocateEndOfHeadersHelper(const char* buf, - int buf_len, - int i, - bool accept_empty_header_list) { +static size_t LocateEndOfHeadersHelper(const char* buf, + size_t buf_len, + size_t i, + bool accept_empty_header_list) { char last_c = '\0'; bool was_lf = false; if (accept_empty_header_list) { @@ -682,16 +682,16 @@ } last_c = c; } - return -1; + return std::string::npos; } -int HttpUtil::LocateEndOfAdditionalHeaders(const char* buf, - int buf_len, - int i) { +size_t HttpUtil::LocateEndOfAdditionalHeaders(const char* buf, + size_t buf_len, + size_t i) { return LocateEndOfHeadersHelper(buf, buf_len, i, true); } -int HttpUtil::LocateEndOfHeaders(const char* buf, int buf_len, int i) { +size_t HttpUtil::LocateEndOfHeaders(const char* buf, size_t buf_len, size_t i) { return LocateEndOfHeadersHelper(buf, buf_len, i, false); } @@ -738,7 +738,7 @@ } std::string HttpUtil::AssembleRawHeaders(const char* input_begin, - int input_len) { + size_t input_len) { std::string raw_headers; raw_headers.reserve(input_len); @@ -746,8 +746,8 @@ // Skip any leading slop, since the consumers of this output // (HttpResponseHeaders) don't deal with it. - int status_begin_offset = LocateStartOfStatusLine(input_begin, input_len); - if (status_begin_offset != -1) + size_t status_begin_offset = LocateStartOfStatusLine(input_begin, input_len); + if (status_begin_offset != std::string::npos) input_begin += status_begin_offset; // Copy the status line.
diff --git a/net/http/http_util.h b/net/http/http_util.h index bb34abc6..c757bf18 100644 --- a/net/http/http_util.h +++ b/net/http/http_util.h
@@ -161,30 +161,29 @@ // The reverse of Unquote() -- escapes and surrounds with " static std::string Quote(const std::string& str); - // Returns the start of the status line, or -1 if no status line was found. - // This allows for 4 bytes of junk to precede the status line (which is what - // mozilla does too). - // TODO(921389): Convert this to return size_t. - static int LocateStartOfStatusLine(const char* buf, int buf_len); + // Returns the start of the status line, or std::string::npos if no status + // line was found. This allows for 4 bytes of junk to precede the status line + // (which is what Mozilla does too). + static size_t LocateStartOfStatusLine(const char* buf, size_t buf_len); - // Returns index beyond the end-of-headers marker or -1 if not found. RFC - // 2616 defines the end-of-headers marker as a double CRLF; however, some - // servers only send back LFs (e.g., Unix-based CGI scripts written using the - // ASIS Apache module). This function therefore accepts the pattern LF[CR]LF - // as end-of-headers (just like Mozilla). The first line of |buf| is - // considered the status line, even if empty. - // The parameter |i| is the offset within |buf| to begin searching from. - // TODO(921389): Convert this to return size_t. - static int LocateEndOfHeaders(const char* buf, int buf_len, int i = 0); + // Returns index beyond the end-of-headers marker or std::string::npos if not + // found. RFC 2616 defines the end-of-headers marker as a double CRLF; + // however, some servers only send back LFs (e.g., Unix-based CGI scripts + // written using the ASIS Apache module). This function therefore accepts the + // pattern LF[CR]LF as end-of-headers (just like Mozilla). The first line of + // |buf| is considered the status line, even if empty. The parameter |i| is + // the offset within |buf| to begin searching from. + static size_t LocateEndOfHeaders(const char* buf, + size_t buf_len, + size_t i = 0); // Same as |LocateEndOfHeaders|, but does not expect a status line, so can be // used on multi-part responses or HTTP/1.x trailers. As a result, if |buf| // starts with a single [CR]LF, it is considered an empty header list, as // opposed to an empty status line above a header list. - // TODO(921389): Convert this to return size_t. - static int LocateEndOfAdditionalHeaders(const char* buf, - int buf_len, - int i = 0); + static size_t LocateEndOfAdditionalHeaders(const char* buf, + size_t buf_len, + size_t i = 0); // Assemble "raw headers" in the format required by HttpResponseHeaders. // This involves normalizing line terminators, converting [CR]LF to \0 and @@ -197,7 +196,7 @@ // // TODO(crbug.com/671799): Should remove or internalize this to // HttpResponseHeaders. - static std::string AssembleRawHeaders(const char* buf, int buf_len); + static std::string AssembleRawHeaders(const char* buf, size_t buf_len); // Converts assembled "raw headers" back to the HTTP response format. That is // convert each \0 occurence to CRLF. This is used by DevTools.
diff --git a/net/http/http_util_unittest.cc b/net/http/http_util_unittest.cc index 53eefb4..0ddf34d 100644 --- a/net/http/http_util_unittest.cc +++ b/net/http/http_util_unittest.cc
@@ -327,12 +327,12 @@ TEST(HttpUtilTest, LocateEndOfHeaders) { struct { const char* const input; - int expected_result; + size_t expected_result; } tests[] = { - {"\r\n", -1}, - {"\n", -1}, - {"\r", -1}, - {"foo", -1}, + {"\r\n", std::string::npos}, + {"\n", std::string::npos}, + {"\r", std::string::npos}, + {"foo", std::string::npos}, {"\r\n\r\n", 4}, {"foo\r\nbar\r\n\r\n", 12}, {"foo\nbar\n\n", 9}, @@ -343,7 +343,7 @@ }; for (size_t i = 0; i < base::size(tests); ++i) { size_t input_len = strlen(tests[i].input); - int eoh = HttpUtil::LocateEndOfHeaders(tests[i].input, input_len); + size_t eoh = HttpUtil::LocateEndOfHeaders(tests[i].input, input_len); EXPECT_EQ(tests[i].expected_result, eoh); } } @@ -351,12 +351,12 @@ TEST(HttpUtilTest, LocateEndOfAdditionalHeaders) { struct { const char* const input; - int expected_result; + size_t expected_result; } tests[] = { {"\r\n", 2}, {"\n", 1}, - {"\r", -1}, - {"foo", -1}, + {"\r", std::string::npos}, + {"foo", std::string::npos}, {"\r\n\r\n", 2}, {"foo\r\nbar\r\n\r\n", 12}, {"foo\nbar\n\n", 9}, @@ -367,7 +367,8 @@ }; for (size_t i = 0; i < base::size(tests); ++i) { size_t input_len = strlen(tests[i].input); - int eoh = HttpUtil::LocateEndOfAdditionalHeaders(tests[i].input, input_len); + size_t eoh = + HttpUtil::LocateEndOfAdditionalHeaders(tests[i].input, input_len); EXPECT_EQ(tests[i].expected_result, eoh); } }
diff --git a/net/server/http_server_unittest.cc b/net/server/http_server_unittest.cc index 1b63016..19faad0 100644 --- a/net/server/http_server_unittest.cc +++ b/net/server/http_server_unittest.cc
@@ -149,9 +149,9 @@ bool IsCompleteResponse(const std::string& response) { // Check end of headers first. - int end_of_headers = HttpUtil::LocateEndOfHeaders(response.data(), - response.size()); - if (end_of_headers < 0) + size_t end_of_headers = + HttpUtil::LocateEndOfHeaders(response.data(), response.size()); + if (end_of_headers == std::string::npos) return false; // Return true if response has data equal to or more than content length.
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc index 54792fb..28d0e68 100644 --- a/net/url_request/url_request_context_builder.cc +++ b/net/url_request/url_request_context_builder.cc
@@ -196,32 +196,7 @@ max_size(0) {} URLRequestContextBuilder::HttpCacheParams::~HttpCacheParams() = default; -URLRequestContextBuilder::URLRequestContextBuilder() - : enable_brotli_(false), - network_quality_estimator_(nullptr), - data_enabled_(false), -#if !BUILDFLAG(DISABLE_FILE_SUPPORT) - file_enabled_(false), -#endif -#if !BUILDFLAG(DISABLE_FTP_SUPPORT) - ftp_enabled_(false), -#endif - http_cache_enabled_(true), - throttling_enabled_(false), - cookie_store_set_by_client_(false), - net_log_(nullptr), - shared_host_resolver_(nullptr), - pac_quick_check_enabled_(true), - pac_sanitize_url_policy_(ProxyResolutionService::SanitizeUrlPolicy::SAFE), - shared_proxy_delegate_(nullptr), - shared_http_auth_handler_factory_(nullptr), -#if BUILDFLAG(ENABLE_REPORTING) - shared_cert_verifier_(nullptr), - network_error_logging_enabled_(false) { -#else // !BUILDFLAG(ENABLE_REPORTING) - shared_cert_verifier_(nullptr){ -#endif // !BUILDFLAG(ENABLE_REPORTING) -} +URLRequestContextBuilder::URLRequestContextBuilder() = default; URLRequestContextBuilder::~URLRequestContextBuilder() = default; @@ -536,8 +511,10 @@ std::move(proxy_config_service_), context.get(), context->host_resolver(), context->network_delegate(), context->net_log()); - proxy_resolution_service_->set_quick_check_enabled(pac_quick_check_enabled_); - proxy_resolution_service_->set_sanitize_url_policy(pac_sanitize_url_policy_); + proxy_resolution_service_->set_quick_check_enabled( + pac_quick_check_enabled_); + proxy_resolution_service_->set_sanitize_url_policy( + pac_sanitize_url_policy_); } ProxyResolutionService* proxy_resolution_service = proxy_resolution_service_.get();
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h index f68548feb..70c424b 100644 --- a/net/url_request/url_request_context_builder.h +++ b/net/url_request/url_request_context_builder.h
@@ -372,53 +372,54 @@ private: std::string name_; - bool enable_brotli_; - NetworkQualityEstimator* network_quality_estimator_; + bool enable_brotli_ = false; + NetworkQualityEstimator* network_quality_estimator_ = nullptr; std::string accept_language_; std::string user_agent_; std::unique_ptr<HttpUserAgentSettings> http_user_agent_settings_; // Include support for data:// requests. - bool data_enabled_; + bool data_enabled_ = false; #if !BUILDFLAG(DISABLE_FILE_SUPPORT) // Include support for file:// requests. - bool file_enabled_; + bool file_enabled_ = false; #endif #if !BUILDFLAG(DISABLE_FTP_SUPPORT) // Include support for ftp:// requests. - bool ftp_enabled_; + bool ftp_enabled_ = false; #endif - bool http_cache_enabled_; - bool throttling_enabled_; - bool cookie_store_set_by_client_; + bool http_cache_enabled_ = true; + bool throttling_enabled_ = false; + bool cookie_store_set_by_client_ = false; HttpCacheParams http_cache_params_; HttpNetworkSession::Params http_network_session_params_; CreateHttpTransactionFactoryCallback create_http_network_transaction_factory_; base::FilePath transport_security_persister_path_; - NetLog* net_log_; + NetLog* net_log_ = nullptr; std::unique_ptr<HostResolver> host_resolver_; - HostResolver* shared_host_resolver_; + HostResolver* shared_host_resolver_ = nullptr; std::unique_ptr<ProxyConfigService> proxy_config_service_; - bool pac_quick_check_enabled_; - ProxyResolutionService::SanitizeUrlPolicy pac_sanitize_url_policy_; + bool pac_quick_check_enabled_ = true; + ProxyResolutionService::SanitizeUrlPolicy pac_sanitize_url_policy_ = + ProxyResolutionService::SanitizeUrlPolicy::SAFE; std::unique_ptr<ProxyResolutionService> proxy_resolution_service_; std::unique_ptr<SSLConfigService> ssl_config_service_; std::unique_ptr<NetworkDelegate> network_delegate_; CreateLayeredNetworkDelegate create_layered_network_delegate_callback_; std::unique_ptr<ProxyDelegate> proxy_delegate_; - ProxyDelegate* shared_proxy_delegate_; + ProxyDelegate* shared_proxy_delegate_ = nullptr; std::unique_ptr<CookieStore> cookie_store_; std::unique_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_; - HttpAuthHandlerFactory* shared_http_auth_handler_factory_; + HttpAuthHandlerFactory* shared_http_auth_handler_factory_ = nullptr; std::unique_ptr<CertVerifier> cert_verifier_; - CertVerifier* shared_cert_verifier_; + CertVerifier* shared_cert_verifier_ = nullptr; std::unique_ptr<CTVerifier> ct_verifier_; std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer_; #if BUILDFLAG(ENABLE_REPORTING) std::unique_ptr<ReportingPolicy> reporting_policy_; - bool network_error_logging_enabled_; + bool network_error_logging_enabled_ = false; #endif // BUILDFLAG(ENABLE_REPORTING) std::vector<std::unique_ptr<URLRequestInterceptor>> url_request_interceptors_; CreateInterceptingJobFactory create_intercepting_job_factory_;
diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc index 4db5cd4..f7242db5 100644 --- a/pdf/out_of_process_instance.cc +++ b/pdf/out_of_process_instance.cc
@@ -91,6 +91,7 @@ constexpr char kJSMetadataType[] = "metadata"; constexpr char kJSBookmarks[] = "bookmarks"; constexpr char kJSTitle[] = "title"; +constexpr char kJSCanSerializeDocument[] = "canSerializeDocument"; // Get password (Plugin -> Page) constexpr char kJSGetPasswordType[] = "getPassword"; // Get password complete arguments (Page -> Plugin) @@ -1654,6 +1655,9 @@ metadata_message.Set(pp::Var(kJSTitle), pp::Var(title)); HistogramEnumeration("PDF.DocumentFeature", HAS_TITLE, FEATURES_COUNT); } + metadata_message.Set( + pp::Var(kJSCanSerializeDocument), + pp::Var(engine_->GetLoadedByteSize() <= kMaximumSavedFileSize)); pp::VarArray bookmarks = engine_->GetBookmarks(); metadata_message.Set(pp::Var(kJSBookmarks), bookmarks);
diff --git a/services/identity/identity_accessor_impl.cc b/services/identity/identity_accessor_impl.cc index d4b28708..d6faa858 100644 --- a/services/identity/identity_accessor_impl.cc +++ b/services/identity/identity_accessor_impl.cc
@@ -19,34 +19,30 @@ const ScopeSet& scopes, const std::string& consumer_id, GetAccessTokenCallback consumer_callback, - ProfileOAuth2TokenService* token_service, IdentityAccessorImpl* manager) - : OAuth2TokenService::Consumer(consumer_id), - token_service_(token_service), - consumer_callback_(std::move(consumer_callback)), - manager_(manager) { - token_service_request_ = - token_service_->StartRequest(account_id, scopes, this); + : consumer_callback_(std::move(consumer_callback)), manager_(manager) { + access_token_fetcher_ = + manager->identity_manager_->CreateAccessTokenFetcherForAccount( + account_id, consumer_id, scopes, + base::BindOnce(&AccessTokenRequest::OnTokenRequestCompleted, + base::Unretained(this)), + identity::AccessTokenFetcher::Mode::kImmediate); } IdentityAccessorImpl::AccessTokenRequest::~AccessTokenRequest() = default; -void IdentityAccessorImpl::AccessTokenRequest::OnGetTokenSuccess( - const OAuth2TokenService::Request* request, - const OAuth2AccessTokenConsumer::TokenResponse& token_response) { - OnRequestCompleted(request, token_response.access_token, - token_response.expiration_time, - GoogleServiceAuthError::AuthErrorNone()); -} - -void IdentityAccessorImpl::AccessTokenRequest::OnGetTokenFailure( - const OAuth2TokenService::Request* request, - const GoogleServiceAuthError& error) { - OnRequestCompleted(request, base::nullopt, base::Time(), error); +void IdentityAccessorImpl::AccessTokenRequest::OnTokenRequestCompleted( + GoogleServiceAuthError error, + AccessTokenInfo access_token_info) { + if (error.state() == GoogleServiceAuthError::NONE) { + OnRequestCompleted(access_token_info.token, + access_token_info.expiration_time, error); + } else { + OnRequestCompleted(base::nullopt, base::Time(), error); + } } void IdentityAccessorImpl::AccessTokenRequest::OnRequestCompleted( - const OAuth2TokenService::Request* request, const base::Optional<std::string>& access_token, base::Time expiration_time, const GoogleServiceAuthError& error) { @@ -59,21 +55,18 @@ // static void IdentityAccessorImpl::Create(mojom::IdentityAccessorRequest request, IdentityManager* identity_manager, - AccountTrackerService* account_tracker, - ProfileOAuth2TokenService* token_service) { + AccountTrackerService* account_tracker) { new IdentityAccessorImpl(std::move(request), identity_manager, - account_tracker, token_service); + account_tracker); } IdentityAccessorImpl::IdentityAccessorImpl( mojom::IdentityAccessorRequest request, IdentityManager* identity_manager, - AccountTrackerService* account_tracker, - ProfileOAuth2TokenService* token_service) + AccountTrackerService* account_tracker) : binding_(this, std::move(request)), identity_manager_(identity_manager), - account_tracker_(account_tracker), - token_service_(token_service) { + account_tracker_(account_tracker) { binding_.set_connection_error_handler(base::BindRepeating( &IdentityAccessorImpl::OnConnectionError, base::Unretained(this))); @@ -98,7 +91,8 @@ AccountState account_state = GetStateOfAccount(account_info); if (!account_state.has_refresh_token || - token_service_->RefreshTokenHasError(account_info.account_id)) { + identity_manager_->GetErrorStateOfRefreshTokenForAccount( + account_info.account_id) != GoogleServiceAuthError::AuthErrorNone()) { primary_account_available_callbacks_.push_back(std::move(callback)); return; } @@ -123,8 +117,7 @@ GetAccessTokenCallback callback) { std::unique_ptr<AccessTokenRequest> access_token_request = std::make_unique<AccessTokenRequest>(account_id, scopes, consumer_id, - std::move(callback), token_service_, - this); + std::move(callback), this); access_token_requests_[access_token_request.get()] = std::move(access_token_request); @@ -147,7 +140,8 @@ // Check whether the primary account is available and notify any waiting // consumers if so. if (account_state.is_primary_account && account_state.has_refresh_token && - !token_service_->RefreshTokenHasError(account_info.account_id)) { + identity_manager_->GetErrorStateOfRefreshTokenForAccount( + account_info.account_id) == GoogleServiceAuthError::AuthErrorNone()) { DCHECK(!account_info.account_id.empty()); DCHECK(!account_info.email.empty()); DCHECK(!account_info.gaia.empty()); @@ -168,7 +162,7 @@ const AccountInfo& account_info) { AccountState account_state; account_state.has_refresh_token = - token_service_->RefreshTokenIsAvailable(account_info.account_id); + identity_manager_->HasAccountWithRefreshToken(account_info.account_id); account_state.is_primary_account = (account_info.account_id == identity_manager_->GetPrimaryAccountId()); return account_state;
diff --git a/services/identity/identity_accessor_impl.h b/services/identity/identity_accessor_impl.h index 5200da7..b5ca967 100644 --- a/services/identity/identity_accessor_impl.h +++ b/services/identity/identity_accessor_impl.h
@@ -25,44 +25,36 @@ public: static void Create(mojom::IdentityAccessorRequest request, IdentityManager* identity_manager, - AccountTrackerService* account_tracker, - ProfileOAuth2TokenService* token_service); + AccountTrackerService* account_tracker); IdentityAccessorImpl(mojom::IdentityAccessorRequest request, IdentityManager* identity_manager, - AccountTrackerService* account_tracker, - ProfileOAuth2TokenService* token_service); + AccountTrackerService* account_tracker); ~IdentityAccessorImpl() override; private: - // Makes an access token request to the OAuth2TokenService on behalf of a + // Makes an access token request to the IdentityManager on behalf of a // given consumer that has made the request to the Identity Service. - class AccessTokenRequest : public OAuth2TokenService::Consumer { + class AccessTokenRequest { public: AccessTokenRequest(const std::string& account_id, const ScopeSet& scopes, const std::string& consumer_id, GetAccessTokenCallback consumer_callback, - ProfileOAuth2TokenService* token_service, IdentityAccessorImpl* manager); - ~AccessTokenRequest() override; + ~AccessTokenRequest(); private: - // OAuth2TokenService::Consumer: - void OnGetTokenSuccess(const OAuth2TokenService::Request* request, - const OAuth2AccessTokenConsumer::TokenResponse& - token_response) override; - void OnGetTokenFailure(const OAuth2TokenService::Request* request, - const GoogleServiceAuthError& error) override; + // Invoked after access token request completes (successful or not). + void OnTokenRequestCompleted(GoogleServiceAuthError error, + AccessTokenInfo access_token_info); // Completes the pending access token request by calling back the consumer. - void OnRequestCompleted(const OAuth2TokenService::Request* request, - const base::Optional<std::string>& access_token, + void OnRequestCompleted(const base::Optional<std::string>& access_token, base::Time expiration_time, const GoogleServiceAuthError& error); - ProfileOAuth2TokenService* token_service_; - std::unique_ptr<OAuth2TokenService::Request> token_service_request_; + std::unique_ptr<AccessTokenFetcher> access_token_fetcher_; GetAccessTokenCallback consumer_callback_; IdentityAccessorImpl* manager_; }; @@ -103,7 +95,6 @@ mojo::Binding<mojom::IdentityAccessor> binding_; IdentityManager* identity_manager_; AccountTrackerService* account_tracker_; - ProfileOAuth2TokenService* token_service_; // The set of pending requests for access tokens. AccessTokenRequests access_token_requests_;
diff --git a/services/identity/identity_accessor_impl_unittest.cc b/services/identity/identity_accessor_impl_unittest.cc index cdea6e5f..0a70b55 100644 --- a/services/identity/identity_accessor_impl_unittest.cc +++ b/services/identity/identity_accessor_impl_unittest.cc
@@ -64,7 +64,6 @@ service_( identity_test_environment_.identity_manager(), &account_tracker_, - &token_service_, test_connector_factory_.RegisterInstance(mojom::kServiceName)) { AccountTrackerService::RegisterPrefs(pref_service_.registry()); AccountFetcherService::RegisterPrefs(pref_service_.registry());
diff --git a/services/identity/identity_service.cc b/services/identity/identity_service.cc index b9d85bc..41fff98 100644 --- a/services/identity/identity_service.cc +++ b/services/identity/identity_service.cc
@@ -14,12 +14,10 @@ IdentityService::IdentityService(IdentityManager* identity_manager, AccountTrackerService* account_tracker, - ProfileOAuth2TokenService* token_service, service_manager::mojom::ServiceRequest request) : service_binding_(this, std::move(request)), identity_manager_(identity_manager), - account_tracker_(account_tracker), - token_service_(token_service) { + account_tracker_(account_tracker) { registry_.AddInterface<mojom::IdentityAccessor>( base::Bind(&IdentityService::Create, base::Unretained(this))); } @@ -40,7 +38,6 @@ return; identity_manager_ = nullptr; - token_service_ = nullptr; account_tracker_ = nullptr; } @@ -54,7 +51,7 @@ return; IdentityAccessorImpl::Create(std::move(request), identity_manager_, - account_tracker_, token_service_); + account_tracker_); } } // namespace identity
diff --git a/services/identity/identity_service.h b/services/identity/identity_service.h index 3211bf4..c599fef 100644 --- a/services/identity/identity_service.h +++ b/services/identity/identity_service.h
@@ -14,7 +14,6 @@ #include "services/service_manager/public/mojom/service.mojom.h" class AccountTrackerService; -class ProfileOAuth2TokenService; namespace identity { @@ -22,7 +21,6 @@ public: IdentityService(IdentityManager* identity_manager, AccountTrackerService* account_tracker, - ProfileOAuth2TokenService* token_service, service_manager::mojom::ServiceRequest request); ~IdentityService() override; @@ -44,7 +42,6 @@ IdentityManager* identity_manager_; AccountTrackerService* account_tracker_; - ProfileOAuth2TokenService* token_service_; service_manager::BinderRegistry registry_;
diff --git a/services/identity/public/cpp/identity_manager.cc b/services/identity/public/cpp/identity_manager.cc index 03afde7..7403d91 100644 --- a/services/identity/public/cpp/identity_manager.cc +++ b/services/identity/public/cpp/identity_manager.cc
@@ -353,6 +353,12 @@ token_service_->GetDelegate()); return delegate->GetJavaObject(); } + +void IdentityManager::ForceRefreshOfExtendedAccountInfo( + const std::string& account_id) { + DCHECK(HasAccountWithRefreshToken(account_id)); + account_fetcher_service_->ForceRefreshOfAccountInfo(account_id); +} #endif void IdentityManager::AddObserver(Observer* observer) {
diff --git a/services/identity/public/cpp/identity_manager.h b/services/identity/public/cpp/identity_manager.h index 5965392..4e905ed 100644 --- a/services/identity/public/cpp/identity_manager.h +++ b/services/identity/public/cpp/identity_manager.h
@@ -451,6 +451,12 @@ // OAuth2TokenService.java has no more client usage. base::android::ScopedJavaLocalRef<jobject> LegacyGetOAuth2TokenServiceJavaObject(); + + // This method has the contractual assumption that the account is a known + // account and has as its semantics that it fetches the account info for the + // account, triggering an OnExtendedAccountInfoUpdated() callback if the info + // was successfully fetched. + void ForceRefreshOfExtendedAccountInfo(const std::string& refresh_token); #endif // Methods to register or remove observers.
diff --git a/services/identity/public/cpp/identity_manager_unittest.cc b/services/identity/public/cpp/identity_manager_unittest.cc index 2daeb37..dda2d92 100644 --- a/services/identity/public/cpp/identity_manager_unittest.cc +++ b/services/identity/public/cpp/identity_manager_unittest.cc
@@ -52,6 +52,14 @@ const char kTestEmail2[] = "me2@gmail.com"; const char kTestEmail3[] = "me3@gmail.com"; +#if defined(OS_ANDROID) +const char kTestHostedDomain[] = "example.com"; +const char kTestFullName[] = "full_name"; +const char kTestGivenName[] = "given_name"; +const char kTestLocale[] = "locale"; +const char kTestPictureUrl[] = "http://picture.example.com/picture.jpg"; +#endif + #if defined(OS_CHROMEOS) const char kTestEmailWithPeriod[] = "m.e@gmail.com"; #endif @@ -2491,4 +2499,37 @@ EXPECT_EQ(account_info.account_id, extended_account_info.value().account_id); } +#if defined(OS_ANDROID) +TEST_F(IdentityManagerTest, ForceRefreshOfExtendedAccountInfo) { + account_fetcher()->OnNetworkInitialized(); + AccountInfo account_info = + MakeAccountAvailable(identity_manager(), kTestEmail2); + + identity_manager()->ForceRefreshOfExtendedAccountInfo( + account_info.account_id); + + base::DictionaryValue user_info; + user_info.SetString("id", account_info.account_id); + user_info.SetString("email", account_info.email); + user_info.SetString("hd", kTestHostedDomain); + user_info.SetString("name", kTestFullName); + user_info.SetString("given_name", kTestGivenName); + user_info.SetString("locale", kTestLocale); + user_info.SetString("picture", kTestPictureUrl); + account_tracker()->SetAccountInfoFromUserInfo(account_info.account_id, + &user_info); + + const AccountInfo& refreshed_account_info = + identity_manager_observer()->AccountFromAccountUpdatedCallback(); + EXPECT_EQ(account_info.account_id, refreshed_account_info.account_id); + EXPECT_EQ(account_info.email, refreshed_account_info.email); + EXPECT_EQ(account_info.gaia, refreshed_account_info.gaia); + EXPECT_EQ(kTestHostedDomain, refreshed_account_info.hosted_domain); + EXPECT_EQ(kTestFullName, refreshed_account_info.full_name); + EXPECT_EQ(kTestGivenName, refreshed_account_info.given_name); + EXPECT_EQ(kTestLocale, refreshed_account_info.locale); + EXPECT_EQ(kTestPictureUrl, refreshed_account_info.picture_url); +} +#endif + } // namespace identity
diff --git a/services/network/cors/preflight_controller.cc b/services/network/cors/preflight_controller.cc index 3baaf03..d7aba44d 100644 --- a/services/network/cors/preflight_controller.cc +++ b/services/network/cors/preflight_controller.cc
@@ -288,7 +288,7 @@ FinalizeLoader(); timing_info_.start_time = head.request_start; - timing_info_.finish_time = base::TimeTicks::Now(); + timing_info_.response_end = base::TimeTicks::Now(); timing_info_.alpn_negotiated_protocol = head.alpn_negotiated_protocol; timing_info_.connection_info = head.connection_info; auto timing_allow_origin =
diff --git a/services/network/host_resolver_unittest.cc b/services/network/host_resolver_unittest.cc index 3980779d..d80a15a 100644 --- a/services/network/host_resolver_unittest.cc +++ b/services/network/host_resolver_unittest.cc
@@ -1136,7 +1136,7 @@ static const char* kTextRecords[] = {"foo", "bar", "more text"}; net::MockDnsClientRuleList rules; rules.emplace_back( - "example.com", net::dns_protocol::kTypeTXT, + "example.com", net::dns_protocol::kTypeTXT, net::SecureDnsMode::AUTOMATIC, net::MockDnsClientRule::Result(net::BuildTestDnsResponse( "example.com", {std::vector<std::string>(std::begin(kTextRecords), std::end(kTextRecords))})), @@ -1175,7 +1175,7 @@ TEST_F(HostResolverTest, HostResults) { net::MockDnsClientRuleList rules; rules.emplace_back( - "example.com", net::dns_protocol::kTypePTR, + "example.com", net::dns_protocol::kTypePTR, net::SecureDnsMode::AUTOMATIC, net::MockDnsClientRule::Result(net::BuildTestDnsPointerResponse( "example.com", {"google.com", "chromium.org"})), false /* delay */);
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc index ede6e0cc..5eaceb3 100644 --- a/services/network/network_context_unittest.cc +++ b/services/network/network_context_unittest.cc
@@ -3103,11 +3103,13 @@ CHECK(result.AssignFromIPLiteral(kResult)); net::MockDnsClientRuleList rules; rules.emplace_back(kQueryHostname, net::dns_protocol::kTypeA, + net::SecureDnsMode::AUTOMATIC, net::MockDnsClientRule::Result( net::BuildTestDnsResponse(kQueryHostname, result)), false /* delay */); rules.emplace_back( kQueryHostname, net::dns_protocol::kTypeAAAA, + net::SecureDnsMode::AUTOMATIC, net::MockDnsClientRule::Result(net::MockDnsClientRule::ResultType::EMPTY), false /* delay */); auto mock_dns_client =
diff --git a/services/network/public/cpp/cors/preflight_timing_info.cc b/services/network/public/cpp/cors/preflight_timing_info.cc index 2691e8c9..c74f32a 100644 --- a/services/network/public/cpp/cors/preflight_timing_info.cc +++ b/services/network/public/cpp/cors/preflight_timing_info.cc
@@ -14,7 +14,7 @@ PreflightTimingInfo::~PreflightTimingInfo() = default; bool PreflightTimingInfo::operator==(const PreflightTimingInfo& rhs) const { - return start_time == rhs.start_time && finish_time == rhs.finish_time && + return start_time == rhs.start_time && response_end == rhs.response_end && alpn_negotiated_protocol == rhs.alpn_negotiated_protocol && connection_info == rhs.connection_info && timing_allow_origin == rhs.timing_allow_origin &&
diff --git a/services/network/public/cpp/cors/preflight_timing_info.h b/services/network/public/cpp/cors/preflight_timing_info.h index a59c56f9..819c5d9f 100644 --- a/services/network/public/cpp/cors/preflight_timing_info.h +++ b/services/network/public/cpp/cors/preflight_timing_info.h
@@ -26,7 +26,7 @@ ~PreflightTimingInfo(); base::TimeTicks start_time; - base::TimeTicks finish_time; + base::TimeTicks response_end; std::string alpn_negotiated_protocol; net::HttpResponseInfo::ConnectionInfo connection_info = net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN;
diff --git a/services/network/public/cpp/network_ipc_param_traits.h b/services/network/public/cpp/network_ipc_param_traits.h index 7089b8b6..431ca3a 100644 --- a/services/network/public/cpp/network_ipc_param_traits.h +++ b/services/network/public/cpp/network_ipc_param_traits.h
@@ -117,7 +117,7 @@ IPC_STRUCT_TRAITS_BEGIN(network::cors::PreflightTimingInfo) IPC_STRUCT_TRAITS_MEMBER(start_time) - IPC_STRUCT_TRAITS_MEMBER(finish_time) + IPC_STRUCT_TRAITS_MEMBER(response_end) IPC_STRUCT_TRAITS_MEMBER(alpn_negotiated_protocol) IPC_STRUCT_TRAITS_MEMBER(connection_info) IPC_STRUCT_TRAITS_MEMBER(timing_allow_origin)
diff --git a/services/network/public/cpp/server/http_server_unittest.cc b/services/network/public/cpp/server/http_server_unittest.cc index 2af5ec40..05facf1e 100644 --- a/services/network/public/cpp/server/http_server_unittest.cc +++ b/services/network/public/cpp/server/http_server_unittest.cc
@@ -130,9 +130,9 @@ private: bool IsCompleteResponse(const std::string& response) { // Check end of headers first. - int end_of_headers = + size_t end_of_headers = net::HttpUtil::LocateEndOfHeaders(response.data(), response.size()); - if (end_of_headers < 0) + if (end_of_headers == std::string::npos) return false; // Return true if response has data equal to or more than content length.
diff --git a/services/tracing/perfetto/json_trace_exporter.cc b/services/tracing/perfetto/json_trace_exporter.cc index 6d664c0..6e6b4af7 100644 --- a/services/tracing/perfetto/json_trace_exporter.cc +++ b/services/tracing/perfetto/json_trace_exporter.cc
@@ -36,6 +36,8 @@ bool has_more) { DCHECK(!packets.empty() || !has_more); + // TODO(eseckler): |label_filter_| seems broken for anything but + // "traceEvents" (e.g. "systemTraceEvents" will output invalid JSON). if (label_filter_.empty() && !has_output_json_preamble_) { out_ += "{\"traceEvents\":["; has_output_json_preamble_ = true; @@ -77,10 +79,10 @@ base::JSONWriter::Write(*metadata_, &json_value); out_ += json_value; } - } - // Finish the json object we started in the preamble. - out_ += "}"; + // Finish the json object we started in the preamble. + out_ += "}"; + } } // Send any remaining data. There is no harm issuing the callback with an
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index 653ca22..ef9b08e 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -585,7 +585,7 @@ "name": "non_network_service_browser_tests", "swarming": { "can_use_on_swarming_builders": true, - "shards": 10 + "shards": 21 }, "test": "browser_tests" },
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 6db509e..6853b698 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -949,6 +949,16 @@ }, }, }, + 'non_network_service_browser_tests': { + 'modifications': { + # chromium.chromiumos + 'linux-chromeos-dbg': { + 'swarming': { + 'shards': 21, + }, + }, + }, + }, 'non_network_service_webkit_layout_tests' : { 'remove_from': [ 'Linux Tests (dbg)(1)(32)', # 32-bit linux is unsupported
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn index c0ed490..71447aef 100644 --- a/testing/libfuzzer/fuzzers/BUILD.gn +++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -400,9 +400,7 @@ sources = [ "$target_gen_dir/javascript_parser.proto", ] - deps = [ - ":gen_javascript_parser_proto", - ] + proto_deps = [ ":gen_javascript_parser_proto" ] proto_out_dir = "" }
diff --git a/testing/libfuzzer/proto/BUILD.gn b/testing/libfuzzer/proto/BUILD.gn index 5e62020..47747e3 100644 --- a/testing/libfuzzer/proto/BUILD.gn +++ b/testing/libfuzzer/proto/BUILD.gn
@@ -4,15 +4,6 @@ import("//third_party/protobuf/proto_library.gni") -copy("json_proto_copy") { - sources = [ - "json.proto", - ] - outputs = [ - "$root_gen_dir" + "/testing/libfuzzer/proto/json.proto", - ] -} - proto_library("json_proto") { sources = [ "json.proto", @@ -21,9 +12,6 @@ # This way json.pb.h header goes into "$root_gen_dir" directory precisely, # otherwise it goes into "$root_gen_dir" + "/testing/libfuzzer/proto/". proto_out_dir = "" - deps = [ - ":json_proto_copy", - ] } source_set("json_proto_converter") {
diff --git a/third_party/blink/public/platform/web_resource_timing_info.h b/third_party/blink/public/platform/web_resource_timing_info.h index 65e7f29..250ae8e 100644 --- a/third_party/blink/public/platform/web_resource_timing_info.h +++ b/third_party/blink/public/platform/web_resource_timing_info.h
@@ -46,7 +46,7 @@ WebURLLoadTiming timing; base::TimeTicks last_redirect_end_time; - base::TimeTicks finish_time; + base::TimeTicks response_end; uint64_t transfer_size; uint64_t encoded_body_size;
diff --git a/third_party/blink/renderer/bindings/core/v8/custom/v8_custom_xpath_ns_resolver.cc b/third_party/blink/renderer/bindings/core/v8/custom/v8_custom_xpath_ns_resolver.cc index dc98870..6d9ada6 100644 --- a/third_party/blink/renderer/bindings/core/v8/custom/v8_custom_xpath_ns_resolver.cc +++ b/third_party/blink/renderer/bindings/core/v8/custom/v8_custom_xpath_ns_resolver.cc
@@ -68,7 +68,7 @@ LocalFrame* frame = ToLocalFrameIfNotDetached(script_state_->GetContext()); if (frame) frame->Console().AddMessage(ConsoleMessage::Create( - kJSMessageSource, kErrorMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kError, "XPathNSResolver does not have a lookupNamespaceURI method.")); return g_null_atom; }
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc b/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc index f48d9bb..2960df8 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc
@@ -11,6 +11,7 @@ #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable_visitor.h" #include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" namespace blink { @@ -129,14 +130,30 @@ return node; } -} // namespace - -class V8EmbedderGraphBuilder +// V8EmbedderGraphBuilder is used to build heap snapshots of Blink's managed +// object graph. On a high level, the following operations are performed: +// - Objects are classified as attached, detached, or unknown. +// - Depending an implicit mode, objects are classified as relevant or internal. +// This classification happens based on NameTrait and the fact that all +// ScriptWrappable objects (those that can have JS properties) are using that +// trait. +// - Not relevant objects are filtered where possible, e.g., sub graphs of +// internals are filtered and not reported. +// +// The algorithm performs a single pass on the graph, starting from V8-to-Blink +// references that identify attached nodes. Each object then starts a recursion +// into its own subgraph to identify and filter subgraphs that only consist of +// internals. Roots, which are potentially Blink only, are transitively +// traversed after handling JavaScript related objects. +class GC_PLUGIN_IGNORE( + "This class is not managed by Oilpan but GC plugin recognizes it as such " + "due to Trace methods.") V8EmbedderGraphBuilder : public Visitor, public v8::PersistentHandleVisitor, public v8::EmbedderHeapTracer::TracedGlobalHandleVisitor { public: V8EmbedderGraphBuilder(v8::Isolate*, Graph*, NodeBuilder*); + ~V8EmbedderGraphBuilder() override; void BuildEmbedderGraph(); @@ -150,15 +167,13 @@ // Visitor overrides. void Visit(const TraceWrapperV8Reference<v8::Value>&) final; - void VisitWithWrappers(void*, TraceDescriptor) final; + void Visit(void*, TraceDescriptor) final; void VisitBackingStoreStrongly(void* object, void** object_slot, TraceDescriptor desc) final; // Unused Visitor overrides. - void Visit(void* object, TraceDescriptor desc) final { - // TODO(mlippautz): Implement for unified heap snapshots. - } + void VisitWithWrappers(void* object, TraceDescriptor desc) final {} void VisitWeak(void* object, void** object_slot, TraceDescriptor desc, @@ -178,10 +193,9 @@ STACK_ALLOCATED(); public: - ParentScope(V8EmbedderGraphBuilder* visitor, EmbedderNode* parent) + ParentScope(V8EmbedderGraphBuilder* visitor, Traceable traceable) : visitor_(visitor) { - DCHECK_EQ(visitor->current_parent_, nullptr); - visitor->current_parent_ = parent; + visitor->current_parent_ = traceable; } ~ParentScope() { visitor_->current_parent_ = nullptr; } @@ -189,38 +203,176 @@ V8EmbedderGraphBuilder* const visitor_; }; - struct WorklistItem { - EmbedderNode* node; - Traceable traceable; - TraceCallback trace_callback; + class State final { + public: + State(Traceable traceable, const char* name, DomTreeState dom_tree_state) + : traceable_(traceable), name_(name), dom_tree_state_(dom_tree_state) {} + explicit State(EmbedderNode* node) + : node_(node), dom_tree_state_(node->GetDomTreeState()) {} + + bool IsVisited() const { return visited_; } + void MarkVisited() { visited_ = true; } + + bool IsPending() const { return pending_; } + void MarkPending() { pending_ = true; } + void UnmarkPending() { pending_ = false; } + + bool HasNode() const { return node_; } + EmbedderNode* GetOrCreateNode(NodeBuilder* builder) { + if (!node_) { + DCHECK(name_); + node_ = builder->GraphNode(traceable_, name_, nullptr, dom_tree_state_); + } + return node_; + } + + DomTreeState GetDomTreeState() const { return dom_tree_state_; } + void UpdateDomTreeState(DomTreeState parent_dom_tree_state) { + // If the child's state is unknown, then take the parent's state. + // If the parent is attached, then the child is also attached. + if (dom_tree_state_ == DomTreeState::kUnknown || + parent_dom_tree_state == DomTreeState::kAttached) { + dom_tree_state_ = parent_dom_tree_state; + } + if (node_) + node_->UpdateDomTreeState(dom_tree_state_); + } + + private: + EmbedderNode* node_ = nullptr; + Traceable traceable_ = nullptr; + const char* name_ = nullptr; + DomTreeState dom_tree_state_; + bool visited_ = false; + bool pending_ = false; }; + // WorklistItemBase is used for different kinds of items that require + // processing the regular worklist. + class WorklistItemBase { + public: + explicit WorklistItemBase(State* parent, State* to_process) + : parent_(parent), to_process_(to_process) {} + virtual ~WorklistItemBase() = default; + virtual void Process(V8EmbedderGraphBuilder*) = 0; + + State* to_process() const { return to_process_; } + State* parent() const { return parent_; } + + private: + State* const parent_; + State* const to_process_; + }; + + // A VisitationItem processes a given object and visits all its children. + class VisitationItem final : public WorklistItemBase { + public: + VisitationItem(State* parent, + State* to_process, + Traceable traceable, + TraceCallback trace_callback) + : WorklistItemBase(parent, to_process), + traceable_(traceable), + trace_callback_(trace_callback) {} + + void Process(V8EmbedderGraphBuilder* builder) final { + // Post-order traversal as parent needs the full information on child. + builder->worklist_.push_back(std::unique_ptr<WorklistItemBase>{ + new VisitationDoneItem(parent(), to_process())}); + to_process()->MarkPending(); + DCHECK(to_process()->IsPending()); + DCHECK(to_process()->IsVisited()); + ParentScope parent_scope(builder, traceable_); + trace_callback_(builder, const_cast<void*>(traceable_)); + } + + private: + Traceable traceable_; + TraceCallback trace_callback_; + }; + + // A VisitationDoneItem unmarks the pending state of an object and creates an + // edge from a parent in case there is one. + class VisitationDoneItem final : public WorklistItemBase { + public: + VisitationDoneItem(State* parent, State* to_process) + : WorklistItemBase(parent, to_process) {} + + void Process(V8EmbedderGraphBuilder* builder) final { + if (parent() && to_process()->HasNode()) { + NodeBuilder* node_builder = builder->node_builder_; + builder->graph_->AddEdge(parent()->GetOrCreateNode(node_builder), + to_process()->GetOrCreateNode(node_builder)); + } + to_process()->UnmarkPending(); + } + }; + + State* GetOrCreateState(Traceable traceable, + const char* name, + DomTreeState dom_tree_state) { + if (!states_.Contains(traceable)) { + states_.insert(traceable, new State(traceable, name, dom_tree_state)); + } + return states_.at(traceable); + } + + State* GetStateNotNull(Traceable traceable) { + CHECK(states_.Contains(traceable)); + return states_.at(traceable); + } + + State* EnsureState(Traceable traceable, EmbedderNode* node) { + if (!states_.Contains(traceable)) { + states_.insert(traceable, new State(node)); + } + return states_.at(traceable); + } + + void EnsureRootState(EmbedderNode* node) { + CHECK(!states_.Contains(node)); + states_.insert(node, new State(node)); + } + void VisitPersistentHandleInternal(v8::Local<v8::Object>, uint16_t); - WorklistItem ToWorklistItem(EmbedderNode*, const TraceDescriptor&) const; - void VisitPendingActivities(); + void VisitBlinkRoots(); void VisitTransitiveClosure(); - // Push the item to the default worklist if item.traceable was not + // Push a VisitatonItem to the main worklist in case the State has not been // already visited. - void PushToWorklist(WorklistItem); + void CreateAndPushVisitationItem(State* parent, + State* to_process, + Traceable traceable, + TraceCallback trace_callback) { + DCHECK(!to_process->IsVisited()); + to_process->MarkVisited(); + worklist_.push_back(std::unique_ptr<WorklistItemBase>{ + new VisitationItem(parent, to_process, traceable, trace_callback)}); + } + + void PushVisitationItem(std::unique_ptr<VisitationItem> item) { + if (!item->to_process()->IsVisited()) { + item->to_process()->MarkVisited(); + worklist_.push_back(std::move(item)); + } + } v8::Isolate* const isolate_; Graph* const graph_; NodeBuilder* const node_builder_; - EmbedderNode* current_parent_ = nullptr; - - HashSet<Traceable> visited_; + Traceable current_parent_ = nullptr; + HashMap<Traceable, State*> states_; // The default worklist that is used to visit transitive closure. - Deque<WorklistItem> worklist_; + Deque<std::unique_ptr<WorklistItemBase>> worklist_; // The worklist that collects detached Nodes during persistent handle // iteration. - Deque<WorklistItem> detached_worklist_; + Deque<std::unique_ptr<VisitationItem>> detached_worklist_; // The worklist that collects ScriptWrappables with unknown information // about attached/detached state during persistent handle iteration. - Deque<WorklistItem> unknown_worklist_; + Deque<std::unique_ptr<VisitationItem>> unknown_worklist_; }; V8EmbedderGraphBuilder::V8EmbedderGraphBuilder(v8::Isolate* isolate, @@ -235,6 +387,12 @@ CHECK_EQ(isolate, ThreadState::Current()->GetIsolate()); } +V8EmbedderGraphBuilder::~V8EmbedderGraphBuilder() { + for (const auto& kvp : states_) { + delete kvp.value; + } +} + void V8EmbedderGraphBuilder::BuildEmbedderGraph() { isolate_->VisitHandlesWithClassIds(this); v8::EmbedderHeapTracer* tracer = @@ -244,14 +402,14 @@ // At this point we collected ScriptWrappables in three groups: // attached, detached, and unknown. #if DCHECK_IS_ON() - for (const WorklistItem& item : worklist_) { - DCHECK_EQ(DomTreeState::kAttached, item.node->GetDomTreeState()); + for (auto const& item : worklist_) { + DCHECK_EQ(DomTreeState::kAttached, item->to_process()->GetDomTreeState()); } - for (const WorklistItem& item : detached_worklist_) { - DCHECK_EQ(DomTreeState::kDetached, item.node->GetDomTreeState()); + for (auto const& item : detached_worklist_) { + DCHECK_EQ(DomTreeState::kDetached, item->to_process()->GetDomTreeState()); } - for (const WorklistItem& item : unknown_worklist_) { - DCHECK_EQ(DomTreeState::kUnknown, item.node->GetDomTreeState()); + for (auto const& item : unknown_worklist_) { + DCHECK_EQ(DomTreeState::kUnknown, item->to_process()->GetDomTreeState()); } #endif // We need to propagate attached/detached information to ScriptWrappables @@ -273,18 +431,20 @@ VisitTransitiveClosure(); // Stage 2: find transitive closure of the detached nodes. while (!detached_worklist_.empty()) { - auto item = detached_worklist_.back(); + auto item = std::move(detached_worklist_.back()); detached_worklist_.pop_back(); - PushToWorklist(item); + PushVisitationItem(std::move(item)); } VisitTransitiveClosure(); // Stage 3: find transitive closure of the unknown nodes. // Nodes reachable only via pending activities are treated as unknown. VisitPendingActivities(); + if (RuntimeEnabledFeatures::HeapUnifiedGarbageCollectionEnabled()) + VisitBlinkRoots(); while (!unknown_worklist_.empty()) { - auto item = unknown_worklist_.back(); + auto item = std::move(unknown_worklist_.back()); unknown_worklist_.pop_back(); - PushToWorklist(item); + PushVisitationItem(std::move(item)); } VisitTransitiveClosure(); DCHECK(worklist_.empty()); @@ -303,18 +463,23 @@ DomTreeStateFromWrapper(isolate_, class_id, v8_value); EmbedderNode* graph_node = node_builder_->GraphNode( traceable, traceable->NameInHeapSnapshot(), wrapper, dom_tree_state); + State* const to_process_state = EnsureState(traceable, graph_node); const TraceDescriptor& descriptor = TraceDescriptorFor<ScriptWrappable>(traceable); - WorklistItem item = ToWorklistItem(graph_node, descriptor); switch (graph_node->GetDomTreeState()) { case DomTreeState::kAttached: - PushToWorklist(item); + CreateAndPushVisitationItem(nullptr, to_process_state, traceable, + descriptor.callback); break; case DomTreeState::kDetached: - detached_worklist_.push_back(item); + detached_worklist_.push_back( + std::unique_ptr<VisitationItem>{new VisitationItem( + nullptr, to_process_state, traceable, descriptor.callback)}); break; case DomTreeState::kUnknown: - unknown_worklist_.push_back(item); + unknown_worklist_.push_back( + std::unique_ptr<VisitationItem>{new VisitationItem( + nullptr, to_process_state, traceable, descriptor.callback)}); break; } } @@ -344,26 +509,49 @@ // Add an edge from the current parent to the V8 object. v8::Local<v8::Value> v8_value = traced_wrapper.NewLocal(isolate_); if (!v8_value.IsEmpty()) { - graph_->AddEdge(current_parent_, node_builder_->GraphNode(v8_value)); + State* parent = GetStateNotNull(current_parent_); + graph_->AddEdge(parent->GetOrCreateNode(node_builder_), + node_builder_->GraphNode(v8_value)); } } -void V8EmbedderGraphBuilder::VisitWithWrappers( - void* object, - TraceDescriptor wrapper_descriptor) { - // Add an edge from the current parent to this object. - // Also push the object to the worklist in order to process its members. +void V8EmbedderGraphBuilder::Visit(void* object, + TraceDescriptor wrapper_descriptor) { const void* traceable = wrapper_descriptor.base_object_payload; - const char* name = - GCInfoTable::Get() - .GCInfoFromIndex( - HeapObjectHeader::FromPayload(traceable)->GcInfoIndex()) - ->name(traceable) - .value; - EmbedderNode* graph_node = node_builder_->GraphNode( - traceable, name, nullptr, current_parent_->GetDomTreeState()); - graph_->AddEdge(current_parent_, graph_node); - PushToWorklist(ToWorklistItem(graph_node, wrapper_descriptor)); + const GCInfo* info = GCInfoTable::Get().GCInfoFromIndex( + HeapObjectHeader::FromPayload(traceable)->GcInfoIndex()); + HeapObjectName name = info->name(traceable); + + State* const parent = GetStateNotNull(current_parent_); + State* const current = + GetOrCreateState(traceable, name.value, parent->GetDomTreeState()); + if (current->IsPending()) { + if (parent->HasNode()) { + // Backedge in currently processed graph. + graph_->AddEdge(parent->GetOrCreateNode(node_builder_), + current->GetOrCreateNode(node_builder_)); + } + return; + } + + // Immediately materialize the node if it is not hidden. + if (!name.name_is_hidden) { + current->GetOrCreateNode(node_builder_); + } + + // Propagate the parent's DomTreeState down to the current state. + current->UpdateDomTreeState(parent->GetDomTreeState()); + + if (!current->IsVisited()) { + CreateAndPushVisitationItem(parent, current, traceable, info->trace); + } else { + // Edge into an already processed subgraph. + if (current->HasNode()) { + // Create an edge in case the current node has already been visited. + graph_->AddEdge(parent->GetOrCreateNode(node_builder_), + current->GetOrCreateNode(node_builder_)); + } + } } void V8EmbedderGraphBuilder::VisitBackingStoreStrongly(void* object, @@ -379,33 +567,41 @@ EmbedderNode* root = static_cast<EmbedderNode*>(graph_->AddNode(std::unique_ptr<Graph::Node>( new EmbedderRootNode("Pending activities")))); + EnsureRootState(root); ParentScope parent(this, root); ActiveScriptWrappableBase::TraceActiveScriptWrappables(isolate_, this); } -V8EmbedderGraphBuilder::WorklistItem V8EmbedderGraphBuilder::ToWorklistItem( - EmbedderNode* node, - const TraceDescriptor& descriptor) const { - return {node, descriptor.base_object_payload, descriptor.callback}; -} - -void V8EmbedderGraphBuilder::PushToWorklist(WorklistItem item) { - if (!visited_.Contains(item.traceable)) { - visited_.insert(item.traceable); - worklist_.push_back(item); +void V8EmbedderGraphBuilder::VisitBlinkRoots() { + { + EmbedderNode* root = static_cast<EmbedderNode*>(graph_->AddNode( + std::unique_ptr<Graph::Node>(new EmbedderRootNode("Blink roots")))); + EnsureRootState(root); + ParentScope parent(this, root); + ThreadState::Current()->GetPersistentRegion()->TracePersistentNodes(this); + } + { + EmbedderNode* root = + static_cast<EmbedderNode*>(graph_->AddNode(std::unique_ptr<Graph::Node>( + new EmbedderRootNode("Blink cross-thread roots")))); + EnsureRootState(root); + ParentScope parent(this, root); + MutexLocker persistent_lock(ProcessHeap::CrossThreadPersistentMutex()); + ProcessHeap::GetCrossThreadPersistentRegion().TracePersistentNodes(this); } } void V8EmbedderGraphBuilder::VisitTransitiveClosure() { // Depth-first search. while (!worklist_.empty()) { - auto item = worklist_.back(); + std::unique_ptr<WorklistItemBase> item = std::move(worklist_.back()); worklist_.pop_back(); - ParentScope parent(this, item.node); - item.trace_callback(this, const_cast<void*>(item.traceable)); + item->Process(this); } } +} // namespace + void EmbedderGraphBuilder::BuildEmbedderGraphCallback(v8::Isolate* isolate, v8::EmbedderGraph* graph, void*) {
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc index 2aabade3..06154336 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
@@ -196,21 +196,21 @@ } namespace { -MessageLevel MessageLevelFromNonFatalErrorLevel(int error_level) { - MessageLevel level = kErrorMessageLevel; +mojom::ConsoleMessageLevel MessageLevelFromNonFatalErrorLevel(int error_level) { + mojom::ConsoleMessageLevel level = mojom::ConsoleMessageLevel::kError; switch (error_level) { case v8::Isolate::kMessageDebug: - level = kVerboseMessageLevel; + level = mojom::ConsoleMessageLevel::kVerbose; break; case v8::Isolate::kMessageLog: case v8::Isolate::kMessageInfo: - level = kInfoMessageLevel; + level = mojom::ConsoleMessageLevel::kInfo; break; case v8::Isolate::kMessageWarning: - level = kWarningMessageLevel; + level = mojom::ConsoleMessageLevel::kWarning; break; case v8::Isolate::kMessageError: - level = kInfoMessageLevel; + level = mojom::ConsoleMessageLevel::kInfo; break; default: NOTREACHED();
diff --git a/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl b/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl index 2b30deb..bbfe849 100644 --- a/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl +++ b/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl
@@ -427,7 +427,7 @@ if (!IsValidEnum(cpp_value, kValidValues, base::size(kValidValues), "{{attribute.enum_type}}", dummy_exception_state)) { ExecutionContext::ForCurrentRealm(info)->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, + ConsoleMessage::Create(kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, dummy_exception_state.Message())); return; }
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.cc index c0ffad6..9cb8629 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.cc
@@ -272,7 +272,7 @@ if (!IsValidEnum(cpp_value, kValidValues, base::size(kValidValues), "TestEnum", dummy_exception_state)) { ExecutionContext::ForCurrentRealm(info)->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, + ConsoleMessage::Create(kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, dummy_exception_state.Message())); return; } @@ -320,7 +320,7 @@ if (!IsValidEnum(cpp_value, kValidValues, base::size(kValidValues), "TestEnum", dummy_exception_state)) { ExecutionContext::ForCurrentRealm(info)->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, + ConsoleMessage::Create(kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, dummy_exception_state.Message())); return; } @@ -1292,7 +1292,7 @@ if (!IsValidEnum(cpp_value, kValidValues, base::size(kValidValues), "PartialEnumType", dummy_exception_state)) { ExecutionContext::ForCurrentRealm(info)->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, + ConsoleMessage::Create(kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, dummy_exception_state.Message())); return; }
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc index 3725cbd..a413aca 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc
@@ -1553,7 +1553,7 @@ if (!IsValidEnum(cpp_value, kValidValues, base::size(kValidValues), "TestEnum", dummy_exception_state)) { ExecutionContext::ForCurrentRealm(info)->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, + ConsoleMessage::Create(kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, dummy_exception_state.Message())); return; } @@ -1601,7 +1601,7 @@ if (!IsValidEnum(cpp_value, kValidValues, base::size(kValidValues), "TestEnum", dummy_exception_state)) { ExecutionContext::ForCurrentRealm(info)->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, + ConsoleMessage::Create(kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, dummy_exception_state.Message())); return; }
diff --git a/third_party/blink/renderer/core/animation/effect_input.cc b/third_party/blink/renderer/core/animation/effect_input.cc index 89950ab..67af486 100644 --- a/third_party/blink/renderer/core/animation/effect_input.cc +++ b/third_party/blink/renderer/core/animation/effect_input.cc
@@ -102,7 +102,7 @@ if (!set_result.did_parse && execution_context) { if (document.GetFrame()) { document.GetFrame()->Console().AddMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "Invalid keyframe value for property " + property + ": " + value)); } }
diff --git a/third_party/blink/renderer/core/css/cssom/cross_thread_keyword_value.cc b/third_party/blink/renderer/core/css/cssom/cross_thread_keyword_value.cc index 17085a5..4aabd90 100644 --- a/third_party/blink/renderer/core/css/cssom/cross_thread_keyword_value.cc +++ b/third_party/blink/renderer/core/css/cssom/cross_thread_keyword_value.cc
@@ -12,4 +12,11 @@ return CSSKeywordValue::Create(keyword_value_); } +bool CrossThreadKeywordValue::operator==( + const CrossThreadStyleValue& other) const { + if (auto* o = DynamicTo<CrossThreadKeywordValue>(other)) + return keyword_value_ == o->keyword_value_; + return false; +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/css/cssom/cross_thread_keyword_value.h b/third_party/blink/renderer/core/css/cssom/cross_thread_keyword_value.h index 4d821cd..a235477 100644 --- a/third_party/blink/renderer/core/css/cssom/cross_thread_keyword_value.h +++ b/third_party/blink/renderer/core/css/cssom/cross_thread_keyword_value.h
@@ -8,6 +8,7 @@ #include "base/macros.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/css/cssom/cross_thread_style_value.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace blink { @@ -20,8 +21,13 @@ : keyword_value_(keyword) {} ~CrossThreadKeywordValue() override = default; + StyleValueType GetType() const override { + return StyleValueType::kKeywordType; + } CSSStyleValue* ToCSSStyleValue() override; + bool operator==(const CrossThreadStyleValue&) const override; + private: friend class CrossThreadStyleValueTest; @@ -29,6 +35,14 @@ DISALLOW_COPY_AND_ASSIGN(CrossThreadKeywordValue); }; +template <> +struct DowncastTraits<CrossThreadKeywordValue> { + static bool AllowFrom(const CrossThreadStyleValue& keyword_value) { + return keyword_value.GetType() == + CrossThreadStyleValue::StyleValueType::kKeywordType; + } +}; + } // namespace blink #endif
diff --git a/third_party/blink/renderer/core/css/cssom/cross_thread_style_value.h b/third_party/blink/renderer/core/css/cssom/cross_thread_style_value.h index 080a584..bd9fd5a 100644 --- a/third_party/blink/renderer/core/css/cssom/cross_thread_style_value.h +++ b/third_party/blink/renderer/core/css/cssom/cross_thread_style_value.h
@@ -16,10 +16,19 @@ // passed cross threads. class CORE_EXPORT CrossThreadStyleValue { public: + enum class StyleValueType { + kUnknownType, + kKeywordType, + kUnitType, + }; + virtual ~CrossThreadStyleValue() = default; + virtual StyleValueType GetType() const = 0; virtual CSSStyleValue* ToCSSStyleValue() = 0; + virtual bool operator==(const CrossThreadStyleValue&) const = 0; + protected: CrossThreadStyleValue() = default;
diff --git a/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc b/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc index 95bd0b92..e4a6458 100644 --- a/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc +++ b/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc
@@ -165,4 +165,93 @@ EXPECT_EQ(static_cast<CSSUnitValue*>(style_value)->unit(), "deg"); } +TEST_F(CrossThreadStyleValueTest, ComparingNullValues) { + // Two null values are equal to each other. + std::unique_ptr<CrossThreadStyleValue> null_value1(nullptr); + std::unique_ptr<CrossThreadStyleValue> null_value2(nullptr); + EXPECT_TRUE(DataEquivalent(null_value1, null_value2)); + + // If one argument is null and the other isn't they are never equal. + std::unique_ptr<CrossThreadStyleValue> keyword_value( + new CrossThreadKeywordValue("keyword")); + std::unique_ptr<CrossThreadStyleValue> unit_value( + new CrossThreadUnitValue(1, CSSPrimitiveValue::UnitType::kDegrees)); + std::unique_ptr<CrossThreadStyleValue> unsupported_value( + new CrossThreadUnsupportedValue("unsupported")); + + EXPECT_FALSE(DataEquivalent(null_value1, keyword_value)); + EXPECT_FALSE(DataEquivalent(null_value1, unit_value)); + EXPECT_FALSE(DataEquivalent(null_value1, unsupported_value)); + EXPECT_FALSE(DataEquivalent(keyword_value, null_value1)); + EXPECT_FALSE(DataEquivalent(unit_value, null_value1)); + EXPECT_FALSE(DataEquivalent(unsupported_value, null_value1)); +} + +TEST_F(CrossThreadStyleValueTest, ComparingDifferentTypes) { + // Mismatching types are never equal. + std::unique_ptr<CrossThreadStyleValue> keyword_value( + new CrossThreadKeywordValue("keyword")); + std::unique_ptr<CrossThreadStyleValue> unit_value( + new CrossThreadUnitValue(1, CSSPrimitiveValue::UnitType::kDegrees)); + std::unique_ptr<CrossThreadStyleValue> unsupported_value( + new CrossThreadUnsupportedValue("unsupported")); + + EXPECT_FALSE(DataEquivalent(keyword_value, unit_value)); + EXPECT_FALSE(DataEquivalent(keyword_value, unsupported_value)); + EXPECT_FALSE(DataEquivalent(unit_value, unsupported_value)); + EXPECT_FALSE(DataEquivalent(unit_value, keyword_value)); + EXPECT_FALSE(DataEquivalent(unsupported_value, keyword_value)); + EXPECT_FALSE(DataEquivalent(unsupported_value, unit_value)); +} + +TEST_F(CrossThreadStyleValueTest, ComparingCrossThreadKeywordValue) { + // CrossThreadKeywordValues are compared on their keyword; if it is equal then + // so are they. + std::unique_ptr<CrossThreadStyleValue> keyword_value_1( + new CrossThreadKeywordValue("keyword")); + std::unique_ptr<CrossThreadStyleValue> keyword_value_2( + new CrossThreadKeywordValue("keyword")); + std::unique_ptr<CrossThreadStyleValue> keyword_value_3( + new CrossThreadKeywordValue("different")); + + EXPECT_TRUE(DataEquivalent(keyword_value_1, keyword_value_2)); + EXPECT_FALSE(DataEquivalent(keyword_value_1, keyword_value_3)); +} + +TEST_F(CrossThreadStyleValueTest, ComparingCrossThreadUnitValue) { + // CrossThreadUnitValues are compared based on their value and unit type; both + // have to match. There are a lot of unit types; we just test a single sample. + std::unique_ptr<CrossThreadStyleValue> unit_value_1( + new CrossThreadUnitValue(1, CSSPrimitiveValue::UnitType::kDegrees)); + + // Same value, same unit. + std::unique_ptr<CrossThreadStyleValue> unit_value_2( + new CrossThreadUnitValue(1, CSSPrimitiveValue::UnitType::kDegrees)); + EXPECT_TRUE(DataEquivalent(unit_value_1, unit_value_2)); + + // Same value, different unit. + std::unique_ptr<CrossThreadStyleValue> unit_value_3( + new CrossThreadUnitValue(1, CSSPrimitiveValue::UnitType::kPoints)); + EXPECT_FALSE(DataEquivalent(unit_value_1, unit_value_3)); + + // Different value, same unit. + std::unique_ptr<CrossThreadStyleValue> unit_value_4( + new CrossThreadUnitValue(2, CSSPrimitiveValue::UnitType::kDegrees)); + EXPECT_FALSE(DataEquivalent(unit_value_1, unit_value_4)); +} + +TEST_F(CrossThreadStyleValueTest, ComparingCrossThreadUnsupportedValue) { + // CrossThreadUnsupportedValues are compared on their value; if it is equal + // then so are they. + std::unique_ptr<CrossThreadStyleValue> unsupported_value_1( + new CrossThreadUnsupportedValue("value")); + std::unique_ptr<CrossThreadStyleValue> unsupported_value_2( + new CrossThreadUnsupportedValue("value")); + std::unique_ptr<CrossThreadStyleValue> unsupported_value_3( + new CrossThreadUnsupportedValue("different")); + + EXPECT_TRUE(DataEquivalent(unsupported_value_1, unsupported_value_2)); + EXPECT_FALSE(DataEquivalent(unsupported_value_1, unsupported_value_3)); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/css/cssom/cross_thread_unit_value.cc b/third_party/blink/renderer/core/css/cssom/cross_thread_unit_value.cc index fa4af69f..227161d7 100644 --- a/third_party/blink/renderer/core/css/cssom/cross_thread_unit_value.cc +++ b/third_party/blink/renderer/core/css/cssom/cross_thread_unit_value.cc
@@ -12,4 +12,11 @@ return CSSUnitValue::Create(value_, unit_); } +bool CrossThreadUnitValue::operator==( + const CrossThreadStyleValue& other) const { + if (auto* o = DynamicTo<CrossThreadUnitValue>(other)) + return value_ == o->value_ && unit_ == o->unit_; + return false; +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/css/cssom/cross_thread_unit_value.h b/third_party/blink/renderer/core/css/cssom/cross_thread_unit_value.h index d9ff1ae..0bfb8c49 100644 --- a/third_party/blink/renderer/core/css/cssom/cross_thread_unit_value.h +++ b/third_party/blink/renderer/core/css/cssom/cross_thread_unit_value.h
@@ -9,6 +9,7 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/css/css_primitive_value.h" #include "third_party/blink/renderer/core/css/cssom/cross_thread_style_value.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" namespace blink { @@ -20,8 +21,11 @@ : value_(value), unit_(unit) {} ~CrossThreadUnitValue() override = default; + StyleValueType GetType() const override { return StyleValueType::kUnitType; } CSSStyleValue* ToCSSStyleValue() override; + bool operator==(const CrossThreadStyleValue&) const override; + private: friend class CrossThreadStyleValueTest; @@ -30,6 +34,14 @@ DISALLOW_COPY_AND_ASSIGN(CrossThreadUnitValue); }; +template <> +struct DowncastTraits<CrossThreadUnitValue> { + static bool AllowFrom(const CrossThreadStyleValue& unit_value) { + return unit_value.GetType() == + CrossThreadStyleValue::StyleValueType::kUnitType; + } +}; + } // namespace blink #endif
diff --git a/third_party/blink/renderer/core/css/cssom/cross_thread_unsupported_value.cc b/third_party/blink/renderer/core/css/cssom/cross_thread_unsupported_value.cc index 020bafb1..bf8ee3d 100644 --- a/third_party/blink/renderer/core/css/cssom/cross_thread_unsupported_value.cc +++ b/third_party/blink/renderer/core/css/cssom/cross_thread_unsupported_value.cc
@@ -12,4 +12,11 @@ return CSSUnsupportedStyleValue::Create(value_); } +bool CrossThreadUnsupportedValue::operator==( + const CrossThreadStyleValue& other) const { + if (auto* o = DynamicTo<CrossThreadUnsupportedValue>(other)) + return value_ == o->value_; + return false; +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/css/cssom/cross_thread_unsupported_value.h b/third_party/blink/renderer/core/css/cssom/cross_thread_unsupported_value.h index 20e085a..db24ac6 100644 --- a/third_party/blink/renderer/core/css/cssom/cross_thread_unsupported_value.h +++ b/third_party/blink/renderer/core/css/cssom/cross_thread_unsupported_value.h
@@ -8,6 +8,7 @@ #include "base/macros.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/css/cssom/cross_thread_style_value.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace blink { @@ -20,8 +21,13 @@ explicit CrossThreadUnsupportedValue(const String& value) : value_(value) {} ~CrossThreadUnsupportedValue() override = default; + StyleValueType GetType() const override { + return StyleValueType::kUnknownType; + } CSSStyleValue* ToCSSStyleValue() override; + bool operator==(const CrossThreadStyleValue&) const override; + private: friend class CrossThreadStyleValueTest; @@ -29,6 +35,14 @@ DISALLOW_COPY_AND_ASSIGN(CrossThreadUnsupportedValue); }; +template <> +struct DowncastTraits<CrossThreadUnsupportedValue> { + static bool AllowFrom(const CrossThreadStyleValue& unsupported_value) { + return unsupported_value.GetType() == + CrossThreadStyleValue::StyleValueType::kUnknownType; + } +}; + } // namespace blink #endif
diff --git a/third_party/blink/renderer/core/css/remote_font_face_source.cc b/third_party/blink/renderer/core/css/remote_font_face_source.cc index fbe64fc..ff93779 100644 --- a/third_party/blink/renderer/core/css/remote_font_face_source.cc +++ b/third_party/blink/renderer/core/css/remote_font_face_source.cc
@@ -124,12 +124,12 @@ if (font->GetStatus() == ResourceStatus::kDecodeError) { font_selector_->GetExecutionContext()->AddConsoleMessage( ConsoleMessage::Create( - kOtherMessageSource, kWarningMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, "Failed to decode downloaded font: " + font->Url().ElidedString())); if (font->OtsParsingMessage().length() > 1) { font_selector_->GetExecutionContext()->AddConsoleMessage( ConsoleMessage::Create( - kOtherMessageSource, kWarningMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, "OTS parsing error: " + font->OtsParsingMessage())); } } @@ -279,7 +279,7 @@ if (font->IsLowPriorityLoadingAllowedForRemoteFont()) { font_selector_->GetExecutionContext()->AddConsoleMessage( ConsoleMessage::Create( - kInterventionMessageSource, kInfoMessageLevel, + kInterventionMessageSource, mojom::ConsoleMessageLevel::kInfo, "Slow network is detected. See " "https://www.chromestatus.com/feature/5636954674692096 for more " "details. Fallback font will be used while loading: " +
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc index 4124e3adc..66579d86 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc +++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -4,6 +4,8 @@ #include "third_party/blink/renderer/core/display_lock/display_lock_context.h" +#include <string> + #include "base/memory/ptr_util.h" #include "third_party/blink/renderer/core/display_lock/display_lock_options.h" #include "third_party/blink/renderer/core/display_lock/strict_yielding_display_lock_budget.h" @@ -37,6 +39,24 @@ const char* kLockCommitted = "Lock commit was requested."; } // namespace rejection_names +// Helper function to convert a display locking state to a string. Used in +// traces. +std::string StateToString(DisplayLockContext::State state) { + switch (state) { + case DisplayLockContext::kLocked: + return "kLocked"; + case DisplayLockContext::kUpdating: + return "kUpdating"; + case DisplayLockContext::kCommitting: + return "kCommitting"; + case DisplayLockContext::kUnlocked: + return "kUnlocked"; + case DisplayLockContext::kPendingAcquire: + return "kPendingAcquire"; + } + return ""; +} + // Helper function that returns an immediately rejected promise. ScriptPromise GetRejectedPromise(ScriptState* script_state, const char* rejection_reason) { @@ -120,6 +140,7 @@ ScriptPromise DisplayLockContext::acquire(ScriptState* script_state, DisplayLockOptions* options) { + TRACE_EVENT0("blink", "DisplayLockContext::acquire()"); double timeout_ms = (options && options->hasTimeout()) ? options->timeout() : kDefaultLockTimeoutMs; @@ -167,6 +188,7 @@ } ScriptPromise DisplayLockContext::update(ScriptState* script_state) { + TRACE_EVENT0("blink", "DisplayLockContext::update()"); // Reject if we're unlocked or disconnected. if (state_ == kUnlocked || state_ == kPendingAcquire || !element_->isConnected()) { @@ -187,6 +209,7 @@ } ScriptPromise DisplayLockContext::commit(ScriptState* script_state) { + TRACE_EVENT0("blink", "DisplayLockContext::commit()"); // Resolve if we're already unlocked. if (state_ == kUnlocked) return GetResolvedPromise(script_state); @@ -214,6 +237,8 @@ } ScriptPromise DisplayLockContext::updateAndCommit(ScriptState* script_state) { + TRACE_EVENT0("blink", "DisplayLockContext::updateAndCommit()"); + // Resolve if we're already unlocked. if (state_ == kUnlocked) return GetResolvedPromise(script_state); @@ -802,10 +827,20 @@ if (new_state == state_) return *this; + if (state_ == kUnlocked) { + TRACE_EVENT_ASYNC_BEGIN0("blink", "LockedDisplayLock", this); + } else if (new_state == kUnlocked) { + TRACE_EVENT_ASYNC_END0("blink", "LockedDisplayLock", this); + } + bool was_activatable = context_->IsActivatable(); bool was_locked = context_->IsLocked(); state_ = new_state; + if (state_ != kUnlocked) { + TRACE_EVENT_ASYNC_STEP_INTO0("blink", "LockedDisplayLock", this, + StateToString(state_)); + } if (!context_->document_) return *this;
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.h b/third_party/blink/renderer/core/display_lock/display_lock_context.h index 40077f2..e965a536 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_context.h +++ b/third_party/blink/renderer/core/display_lock/display_lock_context.h
@@ -50,6 +50,15 @@ kDefault = kYieldBetweenLifecyclePhases }; + // The current state of the lock. Note that the order of these matters. + enum State { + kLocked, + kUpdating, + kCommitting, + kUnlocked, + kPendingAcquire, + }; + // See GetScopedPendingFrameRect() for description. class ScopedPendingFrameRect { STACK_ALLOCATED(); @@ -162,15 +171,6 @@ friend class DisplayLockSuspendedHandle; friend class DisplayLockBudget; - // The current state of the lock. Note that the order of these matters. - enum State { - kLocked, - kUpdating, - kCommitting, - kUnlocked, - kPendingAcquire, - }; - class StateChangeHelper { DISALLOW_NEW();
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index e7debdfc..a60ac38 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -1383,7 +1383,7 @@ // The above removeChild() can execute arbitrary JavaScript code. if (source->parentNode()) { AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, ExceptionMessages::FailedToExecute("adoptNode", "Document", "Unable to remove the " "specified node from the " @@ -3947,7 +3947,7 @@ if (!has_insertion_point) { if (ignore_destructive_write_count_) { AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, ExceptionMessages::FailedToExecute( "write", "Document", "It isn't possible to write into a document " @@ -4187,7 +4187,7 @@ base_element_url.ProtocolIsJavaScript()) { UseCounter::Count(*this, WebFeature::kBaseWithDataHref); AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "'" + base_element_url.Protocol() + "' URLs may not be used as base URLs for a document.")); } @@ -4304,8 +4304,8 @@ if (refresh_url.ProtocolIsJavaScript()) { String message = "Refused to refresh " + url_.ElidedString() + " to a javascript: URL"; - AddConsoleMessage(ConsoleMessage::Create(kSecurityMessageSource, - kErrorMessageLevel, message)); + AddConsoleMessage(ConsoleMessage::Create( + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, message)); return; } @@ -4315,8 +4315,8 @@ "Refused to execute the redirect specified via '<meta " "http-equiv='refresh' content='...'>'. The document is sandboxed, and " "the 'allow-scripts' keyword is not set."; - AddConsoleMessage(ConsoleMessage::Create(kSecurityMessageSource, - kErrorMessageLevel, message)); + AddConsoleMessage(ConsoleMessage::Create( + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, message)); return; } frame_->GetNavigationScheduler().ScheduleRedirect(delay, refresh_url, @@ -6341,9 +6341,9 @@ auto declared_policy = ParseFeaturePolicyHeader( feature_policy_header, GetSecurityOrigin(), &messages, this); for (auto& message : messages) { - AddConsoleMessage( - ConsoleMessage::Create(kSecurityMessageSource, kErrorMessageLevel, - "Error with Feature-Policy header: " + message)); + AddConsoleMessage(ConsoleMessage::Create( + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, + "Error with Feature-Policy header: " + message)); } if (GetSandboxFlags() != kSandboxNone && RuntimeEnabledFeatures::FeaturePolicyForSandboxEnabled()) { @@ -6409,7 +6409,7 @@ // later. In that case, any subsequent violations will be correctly reported. if (!origin_trials::FeaturePolicyReportingEnabled(this)) { AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kWarningMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kWarning, "Feature-Policy-Report-Only header will have no effect unless Feature " "Policy reporting is enabled with an Origin Trial. Sign up at " "https://developers.chrome.com/origintrials/")); @@ -6421,7 +6421,7 @@ feature_policy_report_only_header, GetSecurityOrigin(), &messages, this); for (auto& message : messages) { AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "Error with Feature-Policy-Report-Only header: " + message)); } @@ -6716,7 +6716,7 @@ // https://bugs.webkit.org/show_bug.cgi?id=103274 exists. if (reason == kAboutToExecuteScript) { AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "Blocked script execution in '" + Url().ElidedString() + "' because the document's frame is sandboxed and the " "'allow-scripts' permission is not set.")); @@ -6874,7 +6874,7 @@ } static void RunAddConsoleMessageTask(MessageSource source, - MessageLevel level, + mojom::ConsoleMessageLevel level, const String& message, ExecutionContext* context) { ConsoleMessage* console_message = @@ -7901,7 +7901,7 @@ // TODO(iclelland): Report something different in report-only mode if (disposition == mojom::FeaturePolicyDisposition::kEnforce) { frame->Console().AddMessage(ConsoleMessage::Create( - kViolationMessageSource, kErrorMessageLevel, + kViolationMessageSource, mojom::ConsoleMessageLevel::kError, (message.IsEmpty() ? ("Feature policy violation: " + feature_name + " is not allowed in this document.") : message))); @@ -8002,7 +8002,7 @@ report_endpoints.push_back(end_point); AddConsoleMessage(ConsoleMessage::Create(kSecurityMessageSource, - kErrorMessageLevel, + mojom::ConsoleMessageLevel::kError, violation_params->console_message)); GetContentSecurityPolicy()->ReportViolation( violation_params->directive,
diff --git a/third_party/blink/renderer/core/dom/events/event_target.cc b/third_party/blink/renderer/core/dom/events/event_target.cc index 599872c..4848d06 100644 --- a/third_party/blink/renderer/core/dom/events/event_target.cc +++ b/third_party/blink/renderer/core/dom/events/event_target.cc
@@ -309,7 +309,8 @@ executing_window->GetFrame()->Console().AddMessage( ConsoleMessage::Create( - kInterventionMessageSource, kWarningMessageLevel, + kInterventionMessageSource, + mojom::ConsoleMessageLevel::kWarning, "Registering mousewheel event as passive due to " "smoothscroll.js usage. The smoothscroll.js library is " "buggy, no longer necessary and degrades performance. See "
diff --git a/third_party/blink/renderer/core/editing/commands/document_exec_command.cc b/third_party/blink/renderer/core/editing/commands/document_exec_command.cc index fcae634b..64cfbf6 100644 --- a/third_party/blink/renderer/core/editing/commands/document_exec_command.cc +++ b/third_party/blink/renderer/core/editing/commands/document_exec_command.cc
@@ -80,8 +80,8 @@ String message = "We don't execute document.execCommand() this time, because it is " "called recursively."; - AddConsoleMessage(ConsoleMessage::Create(kJSMessageSource, - kWarningMessageLevel, message)); + AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); return false; } base::AutoReset<bool> execute_scope(&is_running_exec_command_, true);
diff --git a/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc b/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc index d866658d..899b1c8 100644 --- a/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc +++ b/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc
@@ -532,7 +532,7 @@ // non-<html> root elements under <body>, and the <body> works as // rootEditableElement. document.AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "document.execCommand() doesn't work with an invalid HTML structure. It " "is corrected automatically.")); UseCounter::Count(document, WebFeature::kExecCommandAltersHTMLStructure);
diff --git a/third_party/blink/renderer/core/editing/dom_selection.cc b/third_party/blink/renderer/core/editing/dom_selection.cc index 45ed2e1..4a3011a 100644 --- a/third_party/blink/renderer/core/editing/dom_selection.cc +++ b/third_party/blink/renderer/core/editing/dom_selection.cc
@@ -842,7 +842,7 @@ void DOMSelection::AddConsoleWarning(const String& message) { if (tree_scope_) { tree_scope_->GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, message)); + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); } }
diff --git a/third_party/blink/renderer/core/editing/serializers/serialization.cc b/third_party/blink/renderer/core/editing/serializers/serialization.cc index 541be41..06c8e61 100644 --- a/third_party/blink/renderer/core/editing/serializers/serialization.cc +++ b/third_party/blink/renderer/core/editing/serializers/serialization.cc
@@ -737,22 +737,6 @@ ChildListMutationScope mutation(*container_node); - // FIXME: This is wrong if containerNode->firstChild() has more than one ref! - // Example: - // <div>foo</div> - // <script> - // var oldText = div.firstChild; - // console.log(oldText.data); // foo - // div.innerText = "bar"; - // console.log(oldText.data); // bar!?! - // </script> - // I believe this is an intentional benchmark cheat from years ago. - // We should re-visit if we actually want this still. - if (container_node->HasOneTextChild()) { - ToText(container_node->firstChild())->setData(text); - return; - } - // NOTE: This method currently always creates a text node, even if that text // node will be empty. Text* text_node = Text::Create(container_node->GetDocument(), text);
diff --git a/third_party/blink/renderer/core/events/touch_event_test.cc b/third_party/blink/renderer/core/events/touch_event_test.cc index b987a51..cab98c7 100644 --- a/third_party/blink/renderer/core/events/touch_event_test.cc +++ b/third_party/blink/renderer/core/events/touch_event_test.cc
@@ -24,7 +24,7 @@ // ChromeClient methods: void AddMessageToConsole(LocalFrame*, MessageSource message_source, - MessageLevel, + mojom::ConsoleMessageLevel, const String& message, unsigned line_number, const String& source_id,
diff --git a/third_party/blink/renderer/core/execution_context/execution_context.cc b/third_party/blink/renderer/core/execution_context/execution_context.cc index 4cc9282..5af50879 100644 --- a/third_party/blink/renderer/core/execution_context/execution_context.cc +++ b/third_party/blink/renderer/core/execution_context/execution_context.cc
@@ -211,7 +211,7 @@ : kDoNotSupportReferrerPolicyLegacyKeywords, &referrer_policy)) { AddConsoleMessage(ConsoleMessage::Create( - kRenderingMessageSource, kErrorMessageLevel, + kRenderingMessageSource, mojom::ConsoleMessageLevel::kError, "Failed to set referrer policy: The value '" + policies + "' is not one of " + (support_legacy_keywords
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc index f5fc44b..85d653bd 100644 --- a/third_party/blink/renderer/core/exported/web_frame_test.cc +++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -10547,7 +10547,7 @@ web_view_impl->MainFrameImpl()->CollectGarbageForTesting(); } -TEST_F(WebFrameTest, ImageDocumentLoadFinishTime) { +TEST_F(WebFrameTest, ImageDocumentLoadResponseEnd) { // Loading an image resource directly generates an ImageDocument with // the document loader feeding image data into the resource of a generated // img tag. We expect the load finish time to be the same for the document @@ -10566,12 +10566,12 @@ ImageResource* resource = img_document->CachedImageResourceDeprecated(); EXPECT_TRUE(resource); - EXPECT_NE(TimeTicks(), resource->LoadFinishTime()); + EXPECT_NE(TimeTicks(), resource->LoadResponseEnd()); DocumentLoader* loader = document->Loader(); EXPECT_TRUE(loader); - EXPECT_EQ(loader->GetTiming().ResponseEnd(), resource->LoadFinishTime()); + EXPECT_EQ(loader->GetTiming().ResponseEnd(), resource->LoadResponseEnd()); } TEST_F(WebFrameTest, CopyImageDocument) {
diff --git a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc index a324ea3..97b1979 100644 --- a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc +++ b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
@@ -116,7 +116,7 @@ void AddMessageToConsole(LocalFrame*, MessageSource, - MessageLevel, + mojom::ConsoleMessageLevel, const String& message, unsigned line_number, const String&,
diff --git a/third_party/blink/renderer/core/feature_policy/dom_feature_policy.cc b/third_party/blink/renderer/core/feature_policy/dom_feature_policy.cc index 60e36eb..b8da5b0 100644 --- a/third_party/blink/renderer/core/feature_policy/dom_feature_policy.cc +++ b/third_party/blink/renderer/core/feature_policy/dom_feature_policy.cc
@@ -31,7 +31,7 @@ SecurityOrigin::CreateFromString(url); if (!origin || origin->IsOpaque()) { GetDocument()->AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kWarningMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, "Invalid origin url for feature '" + feature + "': " + url + ".")); return false; } @@ -98,9 +98,9 @@ void DOMFeaturePolicy::AddWarningForUnrecognizedFeature( const String& feature) const { - GetDocument()->AddConsoleMessage( - ConsoleMessage::Create(kOtherMessageSource, kWarningMessageLevel, - "Unrecognized feature: '" + feature + "'.")); + GetDocument()->AddConsoleMessage(ConsoleMessage::Create( + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, + "Unrecognized feature: '" + feature + "'.")); } void DOMFeaturePolicy::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/fetch/fetch_manager.cc b/third_party/blink/renderer/core/fetch/fetch_manager.cc index 30897ef..8b1e9d5 100644 --- a/third_party/blink/renderer/core/fetch/fetch_manager.cc +++ b/third_party/blink/renderer/core/fetch/fetch_manager.cc
@@ -818,8 +818,8 @@ if (execution_context_->IsContextDestroyed()) return; if (!message.IsEmpty()) { - execution_context_->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kErrorMessageLevel, message)); + execution_context_->AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kError, message)); } if (resolver_) { ScriptState* state = resolver_->GetScriptState();
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc index 0399b9ea..e4112a6 100644 --- a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc +++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
@@ -1198,7 +1198,7 @@ String message = "Unrecognized Content-Security-Policy directive '" + name + "'.\n"; - MessageLevel level = kErrorMessageLevel; + mojom::ConsoleMessageLevel level = mojom::ConsoleMessageLevel::kError; if (EqualIgnoringASCIICase(name, kAllow)) { message = kAllowMessage; } else if (EqualIgnoringASCIICase(name, kOptions)) { @@ -1208,7 +1208,7 @@ } else if (GetDirectiveType(name) != DirectiveType::kUndefined) { message = "The Content-Security-Policy directive '" + name + "' is implemented behind a flag which is currently disabled.\n"; - level = kInfoMessageLevel; + level = mojom::ConsoleMessageLevel::kInfo; } LogToConsole(message, level); @@ -1317,7 +1317,7 @@ } void ContentSecurityPolicy::LogToConsole(const String& message, - MessageLevel level) { + mojom::ConsoleMessageLevel level) { LogToConsole(ConsoleMessage::Create(kSecurityMessageSource, level, message)); }
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.h b/third_party/blink/renderer/core/frame/csp/content_security_policy.h index 0a1f91d..3866754d 100644 --- a/third_party/blink/renderer/core/frame/csp/content_security_policy.h +++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.h
@@ -29,13 +29,13 @@ #include <memory> #include <utility> +#include "third_party/blink/public/mojom/devtools/console_message.mojom-shared.h" #include "third_party/blink/public/platform/web_content_security_policy_struct.h" #include "third_party/blink/public/platform/web_insecure_request_policy.h" #include "third_party/blink/renderer/bindings/core/v8/source_location.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/execution_context/security_context.h" #include "third_party/blink/renderer/core/frame/web_feature.h" -#include "third_party/blink/renderer/core/inspector/console_types.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.h" @@ -507,7 +507,9 @@ void ApplyPolicySideEffectsToDelegate(); - void LogToConsole(const String& message, MessageLevel = kErrorMessageLevel); + void LogToConsole( + const String& message, + mojom::ConsoleMessageLevel = mojom::ConsoleMessageLevel::kError); void AddAndReportPolicyFromHeaderValue(const String&, ContentSecurityPolicyHeaderType,
diff --git a/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc b/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc index 22c42b5..e0d298e 100644 --- a/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc +++ b/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc
@@ -172,8 +172,8 @@ ContentSecurityPolicy::ViolationType violation_type) const { String message = IsReportOnly() ? "[Report Only] " + console_message : console_message; - policy_->LogToConsole(ConsoleMessage::Create(kSecurityMessageSource, - kErrorMessageLevel, message)); + policy_->LogToConsole(ConsoleMessage::Create( + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, message)); policy_->ReportViolation(directive_text, effective_type, message, blocked_url, report_endpoints_, use_reporting_api_, header_, header_type_, violation_type, @@ -190,9 +190,10 @@ LocalFrame* frame) const { String message = IsReportOnly() ? "[Report Only] " + console_message : console_message; - policy_->LogToConsole(ConsoleMessage::Create(kSecurityMessageSource, - kErrorMessageLevel, message), - frame); + policy_->LogToConsole( + ConsoleMessage::Create(kSecurityMessageSource, + mojom::ConsoleMessageLevel::kError, message), + frame); policy_->ReportViolation(directive_text, effective_type, message, blocked_url, report_endpoints_, use_reporting_api_, header_, header_type_, ContentSecurityPolicy::kURLViolation, @@ -212,9 +213,9 @@ IsReportOnly() ? "[Report Only] " + console_message : console_message; std::unique_ptr<SourceLocation> source_location = SourceLocation::Capture(context_url, context_line.OneBasedInt(), 0); - policy_->LogToConsole(ConsoleMessage::Create(kSecurityMessageSource, - kErrorMessageLevel, message, - source_location->Clone())); + policy_->LogToConsole(ConsoleMessage::Create( + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, message, + source_location->Clone())); policy_->ReportViolation(directive_text, effective_type, message, blocked_url, report_endpoints_, use_reporting_api_, header_, header_type_, @@ -239,7 +240,8 @@ if (IsReportOnly() || exception_status == ContentSecurityPolicy::kWillNotThrowException) { ConsoleMessage* console_message = ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, report_message); + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, + report_message); policy_->LogToConsole(console_message); } policy_->ReportViolation(directive_text, effective_type, message, blocked_url,
diff --git a/third_party/blink/renderer/core/frame/deprecation.cc b/third_party/blink/renderer/core/frame/deprecation.cc index 1e34763..ec51f32 100644 --- a/third_party/blink/renderer/core/frame/deprecation.cc +++ b/third_party/blink/renderer/core/frame/deprecation.cc
@@ -711,8 +711,9 @@ String message = DeprecationMessage(unresolved_property); if (!message.IsEmpty()) { page->GetDeprecation().Suppress(unresolved_property); - ConsoleMessage* console_message = ConsoleMessage::Create( - kDeprecationMessageSource, kWarningMessageLevel, message); + ConsoleMessage* console_message = + ConsoleMessage::Create(kDeprecationMessageSource, + mojom::ConsoleMessageLevel::kWarning, message); frame->Console().AddMessage(console_message); } } @@ -795,7 +796,8 @@ // Send the deprecation message to the console as a warning. DCHECK(!info.message.IsEmpty()); ConsoleMessage* console_message = ConsoleMessage::Create( - kDeprecationMessageSource, kWarningMessageLevel, info.message); + kDeprecationMessageSource, mojom::ConsoleMessageLevel::kWarning, + info.message); frame->Console().AddMessage(console_message); if (!frame || !frame->Client())
diff --git a/third_party/blink/renderer/core/frame/dom_window.cc b/third_party/blink/renderer/core/frame/dom_window.cc index e59311c..a911157 100644 --- a/third_party/blink/renderer/core/frame/dom_window.cc +++ b/third_party/blink/renderer/core/frame/dom_window.cc
@@ -333,7 +333,7 @@ !allow_scripts_to_close_windows) { active_document->domWindow()->GetFrameConsole()->AddMessage( ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "Scripts may close only the windows that were opened by it.")); return; }
diff --git a/third_party/blink/renderer/core/frame/frame_console.cc b/third_party/blink/renderer/core/frame/frame_console.cc index 607e38de..5e8cf02 100644 --- a/third_party/blink/renderer/core/frame/frame_console.cc +++ b/third_party/blink/renderer/core/frame/frame_console.cc
@@ -61,7 +61,7 @@ } void FrameConsole::ReportMessageToClient(MessageSource source, - MessageLevel level, + mojom::ConsoleMessageLevel level, const String& message, SourceLocation* location) { if (source == kNetworkMessageSource) @@ -105,7 +105,7 @@ String::Number(response.HttpStatusCode()) + " (" + response.HttpStatusText() + ')'; ConsoleMessage* console_message = ConsoleMessage::CreateForRequest( - kNetworkMessageSource, kErrorMessageLevel, message, + kNetworkMessageSource, mojom::ConsoleMessageLevel::kError, message, response.CurrentRequestUrl().GetString(), loader, request_identifier); AddMessage(console_message); } @@ -122,8 +122,8 @@ message.Append(error.LocalizedDescription()); } AddMessageToStorage(ConsoleMessage::CreateForRequest( - kNetworkMessageSource, kErrorMessageLevel, message.ToString(), - error.FailingURL(), loader, request_identifier)); + kNetworkMessageSource, mojom::ConsoleMessageLevel::kError, + message.ToString(), error.FailingURL(), loader, request_identifier)); } void FrameConsole::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/frame/frame_console.h b/third_party/blink/renderer/core/frame/frame_console.h index 71722a5..192da82 100644 --- a/third_party/blink/renderer/core/frame/frame_console.h +++ b/third_party/blink/renderer/core/frame/frame_console.h
@@ -29,8 +29,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_CONSOLE_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_CONSOLE_H_ +#include "third_party/blink/public/mojom/devtools/console_message.mojom-shared.h" #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/inspector/console_types.h" #include "third_party/blink/renderer/core/loader/console_logger_impl_base.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/wtf/forward.h" @@ -69,7 +69,7 @@ bool AddMessageToStorage(ConsoleMessage*); void ReportMessageToClient(MessageSource, - MessageLevel, + mojom::ConsoleMessageLevel, const String& message, SourceLocation*);
diff --git a/third_party/blink/renderer/core/frame/intervention.cc b/third_party/blink/renderer/core/frame/intervention.cc index 10b9e7ee..f3f654e 100644 --- a/third_party/blink/renderer/core/frame/intervention.cc +++ b/third_party/blink/renderer/core/frame/intervention.cc
@@ -27,7 +27,7 @@ // Send the message to the console. Document* document = frame->GetDocument(); document->AddConsoleMessage(ConsoleMessage::Create( - kInterventionMessageSource, kErrorMessageLevel, message)); + kInterventionMessageSource, mojom::ConsoleMessageLevel::kError, message)); if (!frame->Client()) return;
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc index 275ea60..ede46e4 100644 --- a/third_party/blink/renderer/core/frame/local_dom_window.cc +++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -587,9 +587,9 @@ "The target origin provided ('" + intended_target_origin->ToString() + "') does not match the recipient window's origin ('" + document()->GetSecurityOrigin()->ToString() + "')."); - ConsoleMessage* console_message = - ConsoleMessage::Create(kSecurityMessageSource, kErrorMessageLevel, - message, std::move(location)); + ConsoleMessage* console_message = ConsoleMessage::Create( + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, message, + std::move(location)); GetFrameConsole()->AddMessage(console_message); return; } @@ -660,7 +660,7 @@ if (document()->IsSandboxed(kSandboxModals)) { UseCounter::Count(document(), WebFeature::kDialogInSandboxedContext); GetFrameConsole()->AddMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "Ignored call to 'alert()'. The document is sandboxed, and the " "'allow-modals' keyword is not set.")); return; @@ -689,7 +689,7 @@ if (document()->IsSandboxed(kSandboxModals)) { UseCounter::Count(document(), WebFeature::kDialogInSandboxedContext); GetFrameConsole()->AddMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "Ignored call to 'confirm()'. The document is sandboxed, and the " "'allow-modals' keyword is not set.")); return false; @@ -720,7 +720,7 @@ if (document()->IsSandboxed(kSandboxModals)) { UseCounter::Count(document(), WebFeature::kDialogInSandboxedContext); GetFrameConsole()->AddMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "Ignored call to 'prompt()'. The document is sandboxed, and the " "'allow-modals' keyword is not set.")); return String(); @@ -1316,7 +1316,7 @@ "event. Please make sure it has an appropriate `as` value and it is " + "preloaded intentionally."; GetFrameConsole()->AddMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, message)); + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); } } @@ -1405,8 +1405,8 @@ if (message.IsEmpty()) return; - GetFrameConsole()->AddMessage( - ConsoleMessage::Create(kJSMessageSource, kErrorMessageLevel, message)); + GetFrameConsole()->AddMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kError, message)); } DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate,
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index d10a4d9..487d19c 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -481,8 +481,8 @@ } void LocalFrame::PrintNavigationWarning(const String& message) { - console_->AddMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, message)); + console_->AddMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); } bool LocalFrame::ShouldClose() {
diff --git a/third_party/blink/renderer/core/frame/navigation_rate_limiter.cc b/third_party/blink/renderer/core/frame/navigation_rate_limiter.cc index 0a2757e6..84b2de1 100644 --- a/third_party/blink/renderer/core/frame/navigation_rate_limiter.cc +++ b/third_party/blink/renderer/core/frame/navigation_rate_limiter.cc
@@ -49,7 +49,7 @@ error_message_sent_ = true; if (auto* local_frame = DynamicTo<LocalFrame>(frame_.Get())) { local_frame->Console().AddMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "Throttling navigation to prevent the browser from hanging. See " "https://crbug.com/882238. Command line switch " "--disable-ipc-flooding-protection can be used to bypass the "
diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc index d948617..b6e0e2c9 100644 --- a/third_party/blink/renderer/core/frame/remote_frame.cc +++ b/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -63,7 +63,7 @@ UserGestureStatus user_gesture_status) { if (!origin_document.GetSecurityOrigin()->CanDisplay(url)) { origin_document.AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "Not allowed to load local resource: " + url.ElidedString())); return; }
diff --git a/third_party/blink/renderer/core/frame/scheduling.cc b/third_party/blink/renderer/core/frame/scheduling.cc index a05ab63..bd915e17 100644 --- a/third_party/blink/renderer/core/frame/scheduling.cc +++ b/third_party/blink/renderer/core/frame/scheduling.cc
@@ -26,7 +26,7 @@ // a process are part of the same site to avoid leaking cross-site inputs. ExecutionContext::From(script_state) ->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "isInputPending requires site-per-process (crbug.com/910421).")); return false; } @@ -50,7 +50,8 @@ message.Append("\". Skipping."); ExecutionContext::From(script_state) ->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, message.ToString())); + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, + message.ToString())); } if (!has_pending_input)
diff --git a/third_party/blink/renderer/core/fullscreen/fullscreen.cc b/third_party/blink/renderer/core/fullscreen/fullscreen.cc index 17c5cf4..567bd87e 100644 --- a/third_party/blink/renderer/core/fullscreen/fullscreen.cc +++ b/third_party/blink/renderer/core/fullscreen/fullscreen.cc
@@ -239,8 +239,8 @@ String message = ExceptionMessages::FailedToExecute( "requestFullscreen", "Element", "API can only be initiated by a user gesture."); - document.AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, message)); + document.AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); return false; }
diff --git a/third_party/blink/renderer/core/html/forms/base_text_input_type.cc b/third_party/blink/renderer/core/html/forms/base_text_input_type.cc index e4189959..fcde627 100644 --- a/third_party/blink/renderer/core/html/forms/base_text_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/base_text_input_type.cc
@@ -88,11 +88,11 @@ new ScriptRegexp(raw_pattern, kTextCaseSensitive, kMultilineDisabled, ScriptRegexp::UTF16)); if (!raw_regexp->IsValid()) { - GetElement().GetDocument().AddConsoleMessage( - ConsoleMessage::Create(kRenderingMessageSource, kErrorMessageLevel, - "Pattern attribute value " + raw_pattern + - " is not a valid regular expression: " + - raw_regexp->ExceptionMessage())); + GetElement().GetDocument().AddConsoleMessage(ConsoleMessage::Create( + kRenderingMessageSource, mojom::ConsoleMessageLevel::kError, + "Pattern attribute value " + raw_pattern + + " is not a valid regular expression: " + + raw_regexp->ExceptionMessage())); regexp_.reset(raw_regexp.release()); pattern_for_regexp_ = raw_pattern; return false;
diff --git a/third_party/blink/renderer/core/html/forms/file_input_type.cc b/third_party/blink/renderer/core/html/forms/file_input_type.cc index 3cfb161..47054c0 100644 --- a/third_party/blink/renderer/core/html/forms/file_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/file_input_type.cc
@@ -165,7 +165,7 @@ String message = "File chooser dialog can only be shown with a user activation."; document.AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, message)); + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); return; }
diff --git a/third_party/blink/renderer/core/html/forms/html_form_control_element.cc b/third_party/blink/renderer/core/html/forms/html_form_control_element.cc index 3a77be8..90b16f9 100644 --- a/third_party/blink/renderer/core/html/forms/html_form_control_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_form_control_element.cc
@@ -220,7 +220,7 @@ // FIXME: This message should be moved off the console once a solution to // https://bugs.webkit.org/show_bug.cgi?id=103274 exists. element->GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "Blocked autofocusing on a form control because the form's frame is " "sandboxed and the 'allow-scripts' permission is not set.")); return false;
diff --git a/third_party/blink/renderer/core/html/forms/html_form_element.cc b/third_party/blink/renderer/core/html/forms/html_form_element.cc index f1443608..913a642 100644 --- a/third_party/blink/renderer/core/html/forms/html_form_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_form_element.cc
@@ -251,8 +251,9 @@ String message( "An invalid form control with name='%name' is not focusable."); message.Replace("%name", unhandled->GetName()); - GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kRenderingMessageSource, kErrorMessageLevel, message)); + GetDocument().AddConsoleMessage( + ConsoleMessage::Create(kRenderingMessageSource, + mojom::ConsoleMessageLevel::kError, message)); } } return false; @@ -267,14 +268,14 @@ if (!isConnected()) { GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "Form submission canceled because the form is not connected")); return; } if (GetDocument().IsSandboxed(kSandboxForms)) { GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "Blocked form submission to '" + attributes_.Action() + "' because the form's frame is sandboxed and the 'allow-forms' " "permission is not set.")); @@ -290,7 +291,7 @@ if (RuntimeEnabledFeatures::UnclosedFormControlIsInvalidEnabled()) { String tag_name = ToHTMLFormControlElement(element)->tagName(); GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "Form submission failed, as the <" + tag_name + "> element named " "'" + @@ -360,17 +361,17 @@ // context flag set, then abort these steps without doing anything. if (!isConnected()) { GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "Form submission canceled because the form is not connected")); return; } if (is_constructing_entry_list_) { DCHECK(RuntimeEnabledFeatures::FormDataEventEnabled()); - GetDocument().AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, - "Form submission canceled because the form is " - "constructing entry list")); + GetDocument().AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, + "Form submission canceled because the form is " + "constructing entry list")); return; } @@ -404,7 +405,7 @@ // 'formdata' event handlers might disconnect the form. if (RuntimeEnabledFeatures::FormDataEventEnabled() && !isConnected()) { GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "Form submission canceled because the form is not connected")); return; } @@ -461,7 +462,7 @@ // FIXME: This message should be moved off the console once a solution to // https://bugs.webkit.org/show_bug.cgi?id=103274 exists. GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "Blocked form submission to '" + submission->Action().ElidedString() + "' because the form's frame is sandboxed and the 'allow-forms' " "permission is not set."));
diff --git a/third_party/blink/renderer/core/html/forms/html_select_element.cc b/third_party/blink/renderer/core/html/forms/html_select_element.cc index d6e5e1f..53de70b 100644 --- a/third_party/blink/renderer/core/html/forms/html_select_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_select_element.cc
@@ -380,7 +380,7 @@ if (index >= kMaxListItems || GetListItems().size() + diff + 1 > kMaxListItems) { GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, String::Format("Blocked to expand the option list and set an option at " "index=%u. The maximum list length is %u.", index, kMaxListItems))); @@ -412,7 +412,7 @@ if (new_len > kMaxListItems || GetListItems().size() + new_len - length() > kMaxListItems) { GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, String::Format("Blocked to expand the option list to %u items. The " "maximum list length is %u.", new_len, kMaxListItems)));
diff --git a/third_party/blink/renderer/core/html/forms/input_type.cc b/third_party/blink/renderer/core/html/forms/input_type.cc index a60dbe4f..33c440ab 100644 --- a/third_party/blink/renderer/core/html/forms/input_type.cc +++ b/third_party/blink/renderer/core/html/forms/input_type.cc
@@ -909,7 +909,7 @@ void InputType::AddWarningToConsole(const char* message_format, const String& value) const { GetElement().GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kRenderingMessageSource, kWarningMessageLevel, + kRenderingMessageSource, mojom::ConsoleMessageLevel::kWarning, String::Format(message_format, JSONValue::QuoteString(value).Utf8().data()))); }
diff --git a/third_party/blink/renderer/core/html/forms/listed_element.cc b/third_party/blink/renderer/core/html/forms/listed_element.cc index 1ba4f3e..0de55bc 100644 --- a/third_party/blink/renderer/core/html/forms/listed_element.cc +++ b/third_party/blink/renderer/core/html/forms/listed_element.cc
@@ -490,7 +490,7 @@ "An invalid form control with name='%name' is not focusable."); message.Replace("%name", GetName()); element.GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kRenderingMessageSource, kErrorMessageLevel, message)); + kRenderingMessageSource, mojom::ConsoleMessageLevel::kError, message)); } return false; }
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc index e19dcef..8d2b3ff8 100644 --- a/third_party/blink/renderer/core/html/html_iframe_element.cc +++ b/third_party/blink/renderer/core/html/html_iframe_element.cc
@@ -148,7 +148,7 @@ invalid_tokens)); if (!invalid_tokens.IsNull()) { GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kErrorMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kError, "Error while parsing the 'sandbox' attribute: " + invalid_tokens)); } if (RuntimeEnabledFeatures::FeaturePolicyForSandboxEnabled()) { @@ -157,7 +157,8 @@ if (!messages.IsEmpty()) { for (const String& message : messages) { GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kWarningMessageLevel, message)); + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, + message)); } } } @@ -197,7 +198,7 @@ value.GetString(), GetDocument().RequiredCSP().GetString())) { required_csp_ = g_null_atom; GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kErrorMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kError, "'csp' attribute is not a valid policy: " + value)); return; } @@ -213,7 +214,8 @@ if (!messages.IsEmpty()) { for (const String& message : messages) { GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kWarningMessageLevel, message)); + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, + message)); } } if (!value.IsEmpty()) { @@ -233,11 +235,11 @@ WebFeature::kHTMLIFrameElementGestureMedia)) { UseCounter::Count(GetDocument(), WebFeature::kHTMLIFrameElementGestureMedia); - GetDocument().AddConsoleMessage( - ConsoleMessage::Create(kOtherMessageSource, kWarningMessageLevel, - "<iframe gesture=\"media\"> is not supported. " - "Use <iframe allow=\"autoplay\">, " - "https://goo.gl/ximf56")); + GetDocument().AddConsoleMessage(ConsoleMessage::Create( + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, + "<iframe gesture=\"media\"> is not supported. " + "Use <iframe allow=\"autoplay\">, " + "https://goo.gl/ximf56")); } if (name == kSrcAttr) @@ -329,7 +331,7 @@ required_csp_, GetDocument().RequiredCSP().GetString())) { if (!required_csp_.IsEmpty()) { GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kErrorMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kError, "'csp' attribute is not a valid policy: " + required_csp_)); } if (required_csp_ != GetDocument().RequiredCSP()) {
diff --git a/third_party/blink/renderer/core/html/html_image_element.cc b/third_party/blink/renderer/core/html/html_image_element.cc index 48ce62b..4f21bde8 100644 --- a/third_party/blink/renderer/core/html/html_image_element.cc +++ b/third_party/blink/renderer/core/html/html_image_element.cc
@@ -311,7 +311,7 @@ &is_default_overridden_intrinsic_size_, &message); if (!message.IsEmpty()) { GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kWarningMessageLevel, message)); + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); } if (intrinsic_size_changed && GetLayoutObject() &&
diff --git a/third_party/blink/renderer/core/html/html_link_element.cc b/third_party/blink/renderer/core/html/html_link_element.cc index 64a04a6..5ddd770 100644 --- a/third_party/blink/renderer/core/html/html_link_element.cc +++ b/third_party/blink/renderer/core/html/html_link_element.cc
@@ -245,7 +245,7 @@ if (!ShouldLoadLink() && IsInShadowTree()) { String message = "HTML element <link> is ignored in shadow tree."; GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, message)); + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); return kInsertionDone; }
diff --git a/third_party/blink/renderer/core/html/html_meta_element.cc b/third_party/blink/renderer/core/html/html_meta_element.cc index 1d29a4b..c5b25dc 100644 --- a/third_party/blink/renderer/core/html/html_meta_element.cc +++ b/third_party/blink/renderer/core/html/html_meta_element.cc
@@ -129,8 +129,9 @@ String message = "Error parsing a meta element's content: ';' is not a valid key-value " "pair separator. Please use ',' instead."; - document->AddConsoleMessage(ConsoleMessage::Create( - kRenderingMessageSource, kWarningMessageLevel, message)); + document->AddConsoleMessage( + ConsoleMessage::Create(kRenderingMessageSource, + mojom::ConsoleMessageLevel::kWarning, message)); } } @@ -402,7 +403,8 @@ return kErrors[error_code]; } -static MessageLevel ViewportErrorMessageLevel(ViewportErrorCode error_code) { +static mojom::ConsoleMessageLevel ViewportErrorMessageLevel( + ViewportErrorCode error_code) { switch (error_code) { case kTruncatedViewportArgumentValueError: case kTargetDensityDpiUnsupported: @@ -410,11 +412,11 @@ case kUnrecognizedViewportArgumentValueError: case kMaximumScaleTooLargeError: case kViewportFitUnsupported: - return kWarningMessageLevel; + return mojom::ConsoleMessageLevel::kWarning; } NOTREACHED(); - return kErrorMessageLevel; + return mojom::ConsoleMessageLevel::kError; } void HTMLMetaElement::ReportViewportWarning(Document* document,
diff --git a/third_party/blink/renderer/core/html/html_plugin_element.cc b/third_party/blink/renderer/core/html/html_plugin_element.cc index b0d373d..e9312233 100644 --- a/third_party/blink/renderer/core/html/html_plugin_element.cc +++ b/third_party/blink/renderer/core/html/html_plugin_element.cc
@@ -696,12 +696,12 @@ bool HTMLPlugInElement::AllowedToLoadPlugin(const KURL& url, const String& mime_type) { if (GetDocument().IsSandboxed(kSandboxPlugins)) { - GetDocument().AddConsoleMessage( - ConsoleMessage::Create(kSecurityMessageSource, kErrorMessageLevel, - "Failed to load '" + url.ElidedString() + - "' as a plugin, because the " - "frame into which the plugin " - "is loading is sandboxed.")); + GetDocument().AddConsoleMessage(ConsoleMessage::Create( + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, + "Failed to load '" + url.ElidedString() + + "' as a plugin, because the " + "frame into which the plugin " + "is loading is sandboxed.")); return false; } return true;
diff --git a/third_party/blink/renderer/core/html/lazy_load_image_observer.cc b/third_party/blink/renderer/core/html/lazy_load_image_observer.cc index f1cfd96..f07caec 100644 --- a/third_party/blink/renderer/core/html/lazy_load_image_observer.cc +++ b/third_party/blink/renderer/core/html/lazy_load_image_observer.cc
@@ -99,7 +99,7 @@ if (!lazy_load_intersection_observer_) { root_document->AddConsoleMessage(ConsoleMessage::Create( - kInterventionMessageSource, kInfoMessageLevel, + kInterventionMessageSource, mojom::ConsoleMessageLevel::kInfo, "Images loaded lazily and replaced with placeholders. Load events are " "deferred. See https://crbug.com/846170")); lazy_load_intersection_observer_ = IntersectionObserver::Create(
diff --git a/third_party/blink/renderer/core/html/media/autoplay_policy.cc b/third_party/blink/renderer/core/html/media/autoplay_policy.cc index af5cb42..38713aa 100644 --- a/third_party/blink/renderer/core/html/media/autoplay_policy.cc +++ b/third_party/blink/renderer/core/html/media/autoplay_policy.cc
@@ -224,7 +224,8 @@ if (IsGestureNeededForPlayback()) { if (IsUsingDocumentUserActivationRequiredPolicy()) { element_->GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, kWarningUnmuteFailed)); + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, + kWarningUnmuteFailed)); } autoplay_uma_helper_->RecordAutoplayUnmuteStatus(
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc index 4896f2e6..6d78810 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -1463,7 +1463,7 @@ if (!frame || !GetDocument().GetSecurityOrigin()->CanDisplay(url)) { if (action_if_invalid == kComplain) { GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "Not allowed to load local resource: " + url.ElidedString())); } DVLOG(3) << "isSafeToLoadURL(" << (void*)this << ", "
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.cc b/third_party/blink/renderer/core/html/media/html_video_element.cc index d25274e..c39bb4ce 100644 --- a/third_party/blink/renderer/core/html/media/html_video_element.cc +++ b/third_party/blink/renderer/core/html/media/html_video_element.cc
@@ -232,7 +232,7 @@ &is_default_overridden_intrinsic_size_, &message); if (!message.IsEmpty()) { GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kWarningMessageLevel, message)); + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); } if (intrinsic_size_changed && GetLayoutObject() &&
diff --git a/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc b/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc index 637d43e..8a754cba 100644 --- a/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc +++ b/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc
@@ -197,7 +197,8 @@ error_message.Append("Failed parsing 'srcset' attribute value since "); error_message.Append(message); document->GetFrame()->Console().AddMessage(ConsoleMessage::Create( - kOtherMessageSource, kErrorMessageLevel, error_message.ToString())); + kOtherMessageSource, mojom::ConsoleMessageLevel::kError, + error_message.ToString())); } } @@ -327,7 +328,7 @@ UseCounter::Count(document, WebFeature::kSrcsetDroppedCandidate); if (document->GetFrame()) { document->GetFrame()->Console().AddMessage(ConsoleMessage::Create( - kOtherMessageSource, kErrorMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kError, String("Dropped srcset candidate ") + JSONValue::QuoteString( String(image_url_start,
diff --git a/third_party/blink/renderer/core/html/parser/xss_auditor.cc b/third_party/blink/renderer/core/html/parser/xss_auditor.cc index 1f53134..48aa1e2 100644 --- a/third_party/blink/renderer/core/html/parser/xss_auditor.cc +++ b/third_party/blink/renderer/core/html/parser/xss_auditor.cc
@@ -438,7 +438,7 @@ } if (xss_protection_header == kReflectedXSSInvalid) { document->AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "Error parsing header X-XSS-Protection: " + header_value + ": " + error_details + " at character position " + String::Format("%u", error_position) +
diff --git a/third_party/blink/renderer/core/html/parser/xss_auditor_delegate.cc b/third_party/blink/renderer/core/html/parser/xss_auditor_delegate.cc index 240cc29..4cf4f30 100644 --- a/third_party/blink/renderer/core/html/parser/xss_auditor_delegate.cc +++ b/third_party/blink/renderer/core/html/parser/xss_auditor_delegate.cc
@@ -106,7 +106,8 @@ : WebFeature::kXSSAuditorBlockedScript); document_->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kErrorMessageLevel, xss_info.BuildConsoleError())); + kJSMessageSource, mojom::ConsoleMessageLevel::kError, + xss_info.BuildConsoleError())); LocalFrame* local_frame = document_->GetFrame(); FrameLoader& frame_loader = local_frame->Loader();
diff --git a/third_party/blink/renderer/core/inspector/console_message.cc b/third_party/blink/renderer/core/inspector/console_message.cc index 3a790f7..e7843eaf 100644 --- a/third_party/blink/renderer/core/inspector/console_message.cc +++ b/third_party/blink/renderer/core/inspector/console_message.cc
@@ -19,7 +19,7 @@ // static ConsoleMessage* ConsoleMessage::CreateForRequest( MessageSource source, - MessageLevel level, + mojom::ConsoleMessageLevel level, const String& message, const String& url, DocumentLoader* loader, @@ -34,7 +34,7 @@ // static ConsoleMessage* ConsoleMessage::Create( MessageSource source, - MessageLevel level, + mojom::ConsoleMessageLevel level, const String& message, std::unique_ptr<SourceLocation> location) { return MakeGarbageCollected<ConsoleMessage>(source, level, message, @@ -43,7 +43,7 @@ // static ConsoleMessage* ConsoleMessage::Create(MessageSource source, - MessageLevel level, + mojom::ConsoleMessageLevel level, const String& message) { return ConsoleMessage::Create(source, level, message, SourceLocation::Capture()); @@ -51,7 +51,7 @@ // static ConsoleMessage* ConsoleMessage::CreateFromWorker( - MessageLevel level, + mojom::ConsoleMessageLevel level, const String& message, std::unique_ptr<SourceLocation> location, WorkerThread* worker_thread) { @@ -65,28 +65,12 @@ ConsoleMessage* ConsoleMessage::CreateFromWebConsoleMessage( const WebConsoleMessage& message, LocalFrame* local_frame) { - MessageLevel web_core_message_level = kInfoMessageLevel; - switch (message.level) { - case mojom::ConsoleMessageLevel::kVerbose: - web_core_message_level = kVerboseMessageLevel; - break; - case mojom::ConsoleMessageLevel::kInfo: - web_core_message_level = kInfoMessageLevel; - break; - case mojom::ConsoleMessageLevel::kWarning: - web_core_message_level = kWarningMessageLevel; - break; - case mojom::ConsoleMessageLevel::kError: - web_core_message_level = kErrorMessageLevel; - break; - } - MessageSource message_source = message.nodes.empty() ? kOtherMessageSource : kRecommendationMessageSource; ConsoleMessage* console_message = ConsoleMessage::Create( - message_source, web_core_message_level, message.text, + message_source, message.level, message.text, SourceLocation::Create(message.url, message.line_number, message.column_number, nullptr)); @@ -101,7 +85,7 @@ } ConsoleMessage::ConsoleMessage(MessageSource source, - MessageLevel level, + mojom::ConsoleMessageLevel level, const String& message, std::unique_ptr<SourceLocation> location) : source_(source), @@ -129,7 +113,7 @@ return source_; } -MessageLevel ConsoleMessage::Level() const { +mojom::ConsoleMessageLevel ConsoleMessage::Level() const { return level_; } @@ -161,9 +145,4 @@ visitor->Trace(frame_); } -STATIC_ASSERT_ENUM(mojom::ConsoleMessageLevel::kVerbose, kVerboseMessageLevel); -STATIC_ASSERT_ENUM(mojom::ConsoleMessageLevel::kInfo, kInfoMessageLevel); -STATIC_ASSERT_ENUM(mojom::ConsoleMessageLevel::kWarning, kWarningMessageLevel); -STATIC_ASSERT_ENUM(mojom::ConsoleMessageLevel::kError, kErrorMessageLevel); - } // namespace blink
diff --git a/third_party/blink/renderer/core/inspector/console_message.h b/third_party/blink/renderer/core/inspector/console_message.h index 8c46275..99fced4 100644 --- a/third_party/blink/renderer/core/inspector/console_message.h +++ b/third_party/blink/renderer/core/inspector/console_message.h
@@ -5,6 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_CONSOLE_MESSAGE_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_CONSOLE_MESSAGE_H_ +#include "third_party/blink/public/mojom/devtools/console_message.mojom-shared.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/dom_node_ids.h" #include "third_party/blink/renderer/core/inspector/console_types.h" @@ -25,25 +26,25 @@ public: // Location must be non-null. static ConsoleMessage* Create(MessageSource, - MessageLevel, + mojom::ConsoleMessageLevel, const String& message, std::unique_ptr<SourceLocation>); // Shortcut when location is unknown. Captures current location. static ConsoleMessage* Create(MessageSource, - MessageLevel, + mojom::ConsoleMessageLevel, const String& message); // This method captures current location if available. static ConsoleMessage* CreateForRequest(MessageSource, - MessageLevel, + mojom::ConsoleMessageLevel, const String& message, const String& url, DocumentLoader*, unsigned long request_identifier); // This creates message from WorkerMessageSource. - static ConsoleMessage* CreateFromWorker(MessageLevel, + static ConsoleMessage* CreateFromWorker(mojom::ConsoleMessageLevel, const String& message, std::unique_ptr<SourceLocation>, WorkerThread*); @@ -54,7 +55,7 @@ LocalFrame* local_frame); ConsoleMessage(MessageSource, - MessageLevel, + mojom::ConsoleMessageLevel, const String& message, std::unique_ptr<SourceLocation>); ~ConsoleMessage(); @@ -63,7 +64,7 @@ const String& RequestIdentifier() const; double Timestamp() const; MessageSource Source() const; - MessageLevel Level() const; + mojom::ConsoleMessageLevel Level() const; const String& Message() const; const String& WorkerId() const; LocalFrame* Frame() const; @@ -74,7 +75,7 @@ private: MessageSource source_; - MessageLevel level_; + mojom::ConsoleMessageLevel level_; String message_; std::unique_ptr<SourceLocation> location_; String request_identifier_;
diff --git a/third_party/blink/renderer/core/inspector/console_message_storage.cc b/third_party/blink/renderer/core/inspector/console_message_storage.cc index d483ab7..75f14aa 100644 --- a/third_party/blink/renderer/core/inspector/console_message_storage.cc +++ b/third_party/blink/renderer/core/inspector/console_message_storage.cc
@@ -52,7 +52,7 @@ // Change in this function requires adjustment of Catapult/Telemetry metric // tracing/tracing/metrics/console_error_metric.html. // See https://crbug.com/880432 - if (message->Level() == kErrorMessageLevel) { + if (message->Level() == mojom::ConsoleMessageLevel::kError) { TRACE_EVENT_INSTANT1("blink.console", "ConsoleMessage::Error", TRACE_EVENT_SCOPE_THREAD, "source", MessageSourceToString(message->Source()));
diff --git a/third_party/blink/renderer/core/inspector/console_types.h b/third_party/blink/renderer/core/inspector/console_types.h index 8cf77b6..0598949 100644 --- a/third_party/blink/renderer/core/inspector/console_types.h +++ b/third_party/blink/renderer/core/inspector/console_types.h
@@ -23,13 +23,6 @@ kInterventionMessageSource, kRecommendationMessageSource }; - -enum MessageLevel { - kVerboseMessageLevel, - kInfoMessageLevel, - kWarningMessageLevel, - kErrorMessageLevel -}; } #endif // !defined(ConsoleTypes_h)
diff --git a/third_party/blink/renderer/core/inspector/inspector_log_agent.cc b/third_party/blink/renderer/core/inspector/inspector_log_agent.cc index bec90bb..dd50a9c82d 100644 --- a/third_party/blink/renderer/core/inspector/inspector_log_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_log_agent.cc
@@ -52,15 +52,15 @@ } } -String MessageLevelValue(MessageLevel level) { +String MessageLevelValue(mojom::ConsoleMessageLevel level) { switch (level) { - case kVerboseMessageLevel: + case mojom::ConsoleMessageLevel::kVerbose: return protocol::Log::LogEntry::LevelEnum::Verbose; - case kInfoMessageLevel: + case mojom::ConsoleMessageLevel::kInfo: return protocol::Log::LogEntry::LevelEnum::Info; - case kWarningMessageLevel: + case mojom::ConsoleMessageLevel::kWarning: return protocol::Log::LogEntry::LevelEnum::Warning; - case kErrorMessageLevel: + case mojom::ConsoleMessageLevel::kError: return protocol::Log::LogEntry::LevelEnum::Error; } return protocol::Log::LogEntry::LevelEnum::Info; @@ -256,7 +256,8 @@ "Forced reflow while executing JavaScript took %" PRId64 "ms", duration.InMilliseconds()); ConsoleMessage* message = ConsoleMessage::Create( - kViolationMessageSource, kVerboseMessageLevel, message_text); + kViolationMessageSource, mojom::ConsoleMessageLevel::kVerbose, + message_text); ConsoleMessageAdded(message); } @@ -265,7 +266,8 @@ base::TimeDelta time, SourceLocation* location) { ConsoleMessage* message = ConsoleMessage::Create( - kViolationMessageSource, kVerboseMessageLevel, text, location->Clone()); + kViolationMessageSource, mojom::ConsoleMessageLevel::kVerbose, text, + location->Clone()); ConsoleMessageAdded(message); }
diff --git a/third_party/blink/renderer/core/inspector/main_thread_debugger.cc b/third_party/blink/renderer/core/inspector/main_thread_debugger.cc index dccc070..763e05c9 100644 --- a/third_party/blink/renderer/core/inspector/main_thread_debugger.cc +++ b/third_party/blink/renderer/core/inspector/main_thread_debugger.cc
@@ -105,7 +105,7 @@ void MainThreadDebugger::ReportConsoleMessage(ExecutionContext* context, MessageSource source, - MessageLevel level, + mojom::ConsoleMessageLevel level, const String& message, SourceLocation* location) { if (LocalFrame* frame = ToFrame(context)) @@ -188,9 +188,9 @@ NOTREACHED(); } - frame->Console().ReportMessageToClient(kJSMessageSource, kErrorMessageLevel, - event->MessageForConsole(), - event->Location()); + frame->Console().ReportMessageToClient( + kJSMessageSource, mojom::ConsoleMessageLevel::kError, + event->MessageForConsole(), event->Location()); const String default_message = "Uncaught"; if (script_state && script_state->ContextIsValid()) {
diff --git a/third_party/blink/renderer/core/inspector/main_thread_debugger.h b/third_party/blink/renderer/core/inspector/main_thread_debugger.h index 43a8e4b4..4f6ecca 100644 --- a/third_party/blink/renderer/core/inspector/main_thread_debugger.h +++ b/third_party/blink/renderer/core/inspector/main_thread_debugger.h
@@ -81,7 +81,7 @@ private: void ReportConsoleMessage(ExecutionContext*, MessageSource, - MessageLevel, + mojom::ConsoleMessageLevel, const String& message, SourceLocation*) override; int ContextGroupId(ExecutionContext*) override;
diff --git a/third_party/blink/renderer/core/inspector/thread_debugger.cc b/third_party/blink/renderer/core/inspector/thread_debugger.cc index d0db380..bab91993 100644 --- a/third_party/blink/renderer/core/inspector/thread_debugger.cc +++ b/third_party/blink/renderer/core/inspector/thread_debugger.cc
@@ -48,23 +48,23 @@ } // static -MessageLevel ThreadDebugger::V8MessageLevelToMessageLevel( +mojom::ConsoleMessageLevel ThreadDebugger::V8MessageLevelToMessageLevel( v8::Isolate::MessageErrorLevel level) { - MessageLevel result = kInfoMessageLevel; + mojom::ConsoleMessageLevel result = mojom::ConsoleMessageLevel::kInfo; switch (level) { case v8::Isolate::kMessageDebug: - result = kVerboseMessageLevel; + result = mojom::ConsoleMessageLevel::kVerbose; break; case v8::Isolate::kMessageWarning: - result = kWarningMessageLevel; + result = mojom::ConsoleMessageLevel::kWarning; break; case v8::Isolate::kMessageError: - result = kErrorMessageLevel; + result = mojom::ConsoleMessageLevel::kError; break; case v8::Isolate::kMessageLog: case v8::Isolate::kMessageInfo: default: - result = kInfoMessageLevel; + result = mojom::ConsoleMessageLevel::kInfo; break; } return result; @@ -136,7 +136,8 @@ message = message.Substring(0, 8) + " (in promise)" + message.Substring(8); ReportConsoleMessage(ToExecutionContext(context), kJSMessageSource, - kErrorMessageLevel, message, location.get()); + mojom::ConsoleMessageLevel::kError, message, + location.get()); String url = location->Url(); return GetV8Inspector()->exceptionThrown( context, ToV8InspectorStringView(default_message), exception,
diff --git a/third_party/blink/renderer/core/inspector/thread_debugger.h b/third_party/blink/renderer/core/inspector/thread_debugger.h index 6550cee..685a84c3 100644 --- a/third_party/blink/renderer/core/inspector/thread_debugger.h +++ b/third_party/blink/renderer/core/inspector/thread_debugger.h
@@ -7,6 +7,7 @@ #include <memory> #include "base/macros.h" +#include "third_party/blink/public/mojom/devtools/console_message.mojom-shared.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/user_gesture_indicator.h" #include "third_party/blink/renderer/core/inspector/console_types.h" @@ -61,7 +62,7 @@ virtual int ContextGroupId(ExecutionContext*) = 0; virtual void ReportConsoleMessage(ExecutionContext*, MessageSource, - MessageLevel, + mojom::ConsoleMessageLevel, const String& message, SourceLocation*) = 0; void installAdditionalCommandLineAPI(v8::Local<v8::Context>, @@ -76,7 +77,7 @@ v8::Local<v8::Array>, int index, v8::Local<v8::Value>); - static MessageLevel V8MessageLevelToMessageLevel( + static mojom::ConsoleMessageLevel V8MessageLevelToMessageLevel( v8::Isolate::MessageErrorLevel); v8::Isolate* isolate_;
diff --git a/third_party/blink/renderer/core/inspector/worker_thread_debugger.cc b/third_party/blink/renderer/core/inspector/worker_thread_debugger.cc index 01bbf16f..7e362aa 100644 --- a/third_party/blink/renderer/core/inspector/worker_thread_debugger.cc +++ b/third_party/blink/renderer/core/inspector/worker_thread_debugger.cc
@@ -71,11 +71,12 @@ DCHECK(worker_threads_.IsEmpty()); } -void WorkerThreadDebugger::ReportConsoleMessage(ExecutionContext* context, - MessageSource source, - MessageLevel level, - const String& message, - SourceLocation* location) { +void WorkerThreadDebugger::ReportConsoleMessage( + ExecutionContext* context, + MessageSource source, + mojom::ConsoleMessageLevel level, + const String& message, + SourceLocation* location) { if (!context) return; To<WorkerOrWorkletGlobalScope>(context) @@ -132,8 +133,8 @@ void WorkerThreadDebugger::ExceptionThrown(WorkerThread* worker_thread, ErrorEvent* event) { worker_thread->GetWorkerReportingProxy().ReportConsoleMessage( - kJSMessageSource, kErrorMessageLevel, event->MessageForConsole(), - event->Location()); + kJSMessageSource, mojom::ConsoleMessageLevel::kError, + event->MessageForConsole(), event->Location()); const String default_message = "Uncaught"; ScriptState* script_state =
diff --git a/third_party/blink/renderer/core/inspector/worker_thread_debugger.h b/third_party/blink/renderer/core/inspector/worker_thread_debugger.h index 94ea18b..dce0ddd 100644 --- a/third_party/blink/renderer/core/inspector/worker_thread_debugger.h +++ b/third_party/blink/renderer/core/inspector/worker_thread_debugger.h
@@ -64,7 +64,7 @@ int ContextGroupId(ExecutionContext*) override; void ReportConsoleMessage(ExecutionContext*, MessageSource, - MessageLevel, + mojom::ConsoleMessageLevel, const String& message, SourceLocation*) override;
diff --git a/third_party/blink/renderer/core/layout/custom/css_layout_definition.cc b/third_party/blink/renderer/core/layout/custom/css_layout_definition.cc index 9390b052..dd21a6c 100644 --- a/third_party/blink/renderer/core/layout/custom/css_layout_definition.cc +++ b/third_party/blink/renderer/core/layout/custom/css_layout_definition.cc
@@ -159,7 +159,7 @@ CustomLayoutFragment* fragment = fragment_request->PerformLayout(isolate); if (!fragment) { execution_context->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kInfoMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kInfo, "Unable to perform layout request due to an invalid child, " "falling back to block layout.")); return false; @@ -186,7 +186,7 @@ if (!fragment) { execution_context->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kInfoMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kInfo, "Unable to perform layout request due to an invalid child, " "falling back to block layout.")); return false; @@ -208,10 +208,10 @@ // We recieved something that wasn't either a CustomLayoutFragmentRequest, // or a sequence of CustomLayoutFragmentRequests. Fallback to block layout. - execution_context->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kInfoMessageLevel, - "Unable to parse the layout request, " - "falling back to block layout.")); + execution_context->AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kInfo, + "Unable to parse the layout request, " + "falling back to block layout.")); return false; } @@ -231,10 +231,10 @@ if (exception_state.HadException()) { V8ScriptRunner::ReportException(isolate, exception_state.GetException()); exception_state.ClearException(); - execution_context->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kInfoMessageLevel, - "Unable to parse the layout function " - "result, falling back to block layout.")); + execution_context->AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kInfo, + "Unable to parse the layout function " + "result, falling back to block layout.")); return false; } @@ -253,10 +253,10 @@ if (exception_state.HadException()) { V8ScriptRunner::ReportException(isolate, exception_state.GetException()); exception_state.ClearException(); - execution_context->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kInfoMessageLevel, - "Unable to serialize the data provided in the " - "result, falling back to block layout.")); + execution_context->AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kInfo, + "Unable to serialize the data provided in the " + "result, falling back to block layout.")); return false; } @@ -274,7 +274,7 @@ V8ScriptRunner::ReportException(isolate, exception_state->GetException()); exception_state->ClearException(); execution_context->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kInfoMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kInfo, "The layout function failed, falling back to block layout.")); }
diff --git a/third_party/blink/renderer/core/layout/custom/layout_custom.cc b/third_party/blink/renderer/core/layout/custom/layout_custom.cc index 611c30a..bdb310d 100644 --- a/third_party/blink/renderer/core/layout/custom/layout_custom.cc +++ b/third_party/blink/renderer/core/layout/custom/layout_custom.cc
@@ -165,7 +165,7 @@ if (!instance_) { GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kInfoMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kInfo, "Unable to create an instance of layout class '" + name + "', falling back to block layout.")); return false; @@ -194,18 +194,18 @@ } if (index >= child_fragments.size()) { - GetDocument().AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kInfoMessageLevel, - "Chrome currently requires exactly one " - "LayoutFragment per LayoutChild, " - "falling back to block layout.")); + GetDocument().AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kInfo, + "Chrome currently requires exactly one " + "LayoutFragment per LayoutChild, " + "falling back to block layout.")); return false; } CustomLayoutFragment* fragment = child_fragments[index++]; if (!fragment->IsValid()) { GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kInfoMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kInfo, "An invalid LayoutFragment was returned from the " "layout, falling back to block layout.")); return false; @@ -244,11 +244,11 @@ // Currently we only support exactly one LayoutFragment per LayoutChild. if (index != child_fragments.size()) { - GetDocument().AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kInfoMessageLevel, - "Chrome currently requires exactly one " - "LayoutFragment per LayoutChild, " - "falling back to block layout.")); + GetDocument().AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kInfo, + "Chrome currently requires exactly one " + "LayoutFragment per LayoutChild, " + "falling back to block layout.")); return false; }
diff --git a/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc b/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc index a0dbf33..47e6c34 100644 --- a/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc +++ b/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc
@@ -151,9 +151,9 @@ const KURL& url = image_resource.Url(); String url_string = url.IsNull() ? "''" : url.ElidedString(); - document.AddConsoleMessage( - ConsoleMessage::Create(kSecurityMessageSource, kErrorMessageLevel, - "Unsafe attempt to load URL " + url_string + ".")); + document.AddConsoleMessage(ConsoleMessage::Create( + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, + "Unsafe attempt to load URL " + url_string + ".")); return false; }
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.cc b/third_party/blink/renderer/core/loader/base_fetch_context.cc index 4d814a0..ecddbdf 100644 --- a/third_party/blink/renderer/core/loader/base_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/base_fetch_context.cc
@@ -230,8 +230,8 @@ ". Domains, protocols and ports must match.\n"; } - AddConsoleMessage(ConsoleMessage::Create(kSecurityMessageSource, - kErrorMessageLevel, message)); + AddConsoleMessage(ConsoleMessage::Create( + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, message)); } base::Optional<ResourceRequestBlockedReason> @@ -299,7 +299,7 @@ !origin->CanDisplay(url)) { if (reporting_policy == SecurityViolationReportingPolicy::kReport) { AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kErrorMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kError, "Not allowed to load local resource: " + url.GetString())); } RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::requestResource URL was not "
diff --git a/third_party/blink/renderer/core/loader/console_logger_impl_base.cc b/third_party/blink/renderer/core/loader/console_logger_impl_base.cc index decf906..723be39 100644 --- a/third_party/blink/renderer/core/loader/console_logger_impl_base.cc +++ b/third_party/blink/renderer/core/loader/console_logger_impl_base.cc
@@ -15,19 +15,22 @@ void ConsoleLoggerImplBase::AddInfoMessage(Source source, const String& message) { AddConsoleMessage(ConsoleMessage::Create(GetMessageSourceFromSource(source), - kInfoMessageLevel, message)); + mojom::ConsoleMessageLevel::kInfo, + message)); } void ConsoleLoggerImplBase::AddWarningMessage(Source source, const String& message) { AddConsoleMessage(ConsoleMessage::Create(GetMessageSourceFromSource(source), - kWarningMessageLevel, message)); + mojom::ConsoleMessageLevel::kWarning, + message)); } void ConsoleLoggerImplBase::AddErrorMessage(Source source, const String& message) { AddConsoleMessage(ConsoleMessage::Create(GetMessageSourceFromSource(source), - kErrorMessageLevel, message)); + mojom::ConsoleMessageLevel::kError, + message)); } MessageSource ConsoleLoggerImplBase::GetMessageSourceFromSource(Source source) {
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index cc12719..ab0914f 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -540,7 +540,7 @@ navigation_timing_info_->AddFinalTransferSize( total_encoded_data_length == -1 ? 0 : total_encoded_data_length); if (response_.HttpStatusCode() < 400 && report_timing_info_to_parent_) { - navigation_timing_info_->SetLoadFinishTime(completion_time); + navigation_timing_info_->SetLoadResponseEnd(completion_time); if (state_ >= kCommitted) { // Note that we currently lose timing info for empty documents, // which will be fixed with synchronous commit. @@ -777,7 +777,7 @@ "required by its embedder: '" + GetFrameLoader().RequiredCSP() + "'."; ConsoleMessage* console_message = ConsoleMessage::CreateForRequest( - kSecurityMessageSource, kErrorMessageLevel, message, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, message, response.CurrentRequestUrl(), this, MainResourceIdentifier()); frame_->GetDocument()->AddConsoleMessage(console_message); return nullptr;
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h index 2189154..1aa3ce1 100644 --- a/third_party/blink/renderer/core/loader/empty_clients.h +++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -120,7 +120,7 @@ } void AddMessageToConsole(LocalFrame*, MessageSource, - MessageLevel, + mojom::ConsoleMessageLevel, const String&, unsigned, const String&,
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc index d00ee83..3291c84 100644 --- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -1289,7 +1289,7 @@ if (document && document->IsFreezingInProgress() && !resource_request.GetKeepalive()) { AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kErrorMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kError, "Only fetch keepalive is allowed during onfreeze: " + url.GetString())); return ResourceRequestBlockedReason::kOther; }
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc index 6028d4d..300738c 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -714,7 +714,7 @@ if (!request.OriginDocument()->GetSecurityOrigin()->CanDisplay(url)) { request.OriginDocument()->AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "Not allowed to load local resource: " + url.ElidedString())); return false; } @@ -734,7 +734,7 @@ (url.ProtocolIsData() && network_utils::IsDataURLMimeTypeSupported(url)))) { frame_->GetDocument()->AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "Not allowed to navigate top frame to " + url.Protocol() + " URL: " + url.ElidedString())); return false;
diff --git a/third_party/blink/renderer/core/loader/http_equiv.cc b/third_party/blink/renderer/core/loader/http_equiv.cc index 3af0d588..f5e8f4b 100644 --- a/third_party/blink/renderer/core/loader/http_equiv.cc +++ b/third_party/blink/renderer/core/loader/http_equiv.cc
@@ -105,7 +105,7 @@ document.ParseDNSPrefetchControlHeader(content); } else if (EqualIgnoringASCIICase(equiv, "x-frame-options")) { document.AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "X-Frame-Options may only be set via an HTTP header sent along with a " "document. It may not be set inside <meta>.")); } else if (EqualIgnoringASCIICase(equiv, http_names::kAcceptCH)) { @@ -207,7 +207,7 @@ } document.AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, String::Format("Blocked setting the `%s` cookie from a `<meta>` tag.", content.Utf8().data()))); }
diff --git a/third_party/blink/renderer/core/loader/mixed_content_checker.cc b/third_party/blink/renderer/core/loader/mixed_content_checker.cc index 6acbcae..5dea1e6 100644 --- a/third_party/blink/renderer/core/loader/mixed_content_checker.cc +++ b/third_party/blink/renderer/core/loader/mixed_content_checker.cc
@@ -284,8 +284,9 @@ allowed ? "This content should also be served over HTTPS." : "This request has been blocked; the content must be served " "over HTTPS."); - MessageLevel message_level = - allowed ? kWarningMessageLevel : kErrorMessageLevel; + mojom::ConsoleMessageLevel message_level = + allowed ? mojom::ConsoleMessageLevel::kWarning + : mojom::ConsoleMessageLevel::kError; if (source_location) { return ConsoleMessage::Create(kSecurityMessageSource, message_level, message, std::move(source_location)); @@ -547,8 +548,9 @@ "deprecated." : "This request has been blocked; this endpoint must be " "available over WSS."); - MessageLevel message_level = - allowed ? kWarningMessageLevel : kErrorMessageLevel; + mojom::ConsoleMessageLevel message_level = + allowed ? mojom::ConsoleMessageLevel::kWarning + : mojom::ConsoleMessageLevel::kError; return ConsoleMessage::Create(kSecurityMessageSource, message_level, message); } @@ -653,7 +655,7 @@ MainResourceUrlForFrame(mixed_frame).ElidedString().Utf8().data(), url.ElidedString().Utf8().data()); frame->GetDocument()->AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kWarningMessageLevel, message)); + kSecurityMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); } return true; @@ -782,8 +784,8 @@ "autougprade-mixed.md", main_resource_url.ElidedString().Utf8().data(), mixed_content_url.ElidedString().Utf8().data()); - return ConsoleMessage::Create(kSecurityMessageSource, kWarningMessageLevel, - message); + return ConsoleMessage::Create(kSecurityMessageSource, + mojom::ConsoleMessageLevel::kWarning, message); } // static @@ -800,8 +802,8 @@ "autougprade-mixed.md", main_resource_url.ElidedString().Utf8().data(), mixed_content_url.ElidedString().Utf8().data()); - return ConsoleMessage::Create(kSecurityMessageSource, kWarningMessageLevel, - message); + return ConsoleMessage::Create(kSecurityMessageSource, + mojom::ConsoleMessageLevel::kWarning, message); } WebMixedContentContextType MixedContentChecker::ContextTypeForInspector(
diff --git a/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc index 0245b87e..17720e2 100644 --- a/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc +++ b/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc
@@ -66,8 +66,8 @@ if (source_text.IsNull()) { HeapVector<Member<ConsoleMessage>> error_messages; error_messages.push_back(ConsoleMessage::CreateForRequest( - kJSMessageSource, kErrorMessageLevel, "Unexpected data error", - fetch_params.Url().GetString(), nullptr, 0)); + kJSMessageSource, mojom::ConsoleMessageLevel::kError, + "Unexpected data error", fetch_params.Url().GetString(), nullptr, 0)); client_->NotifyFetchFinished(base::nullopt, error_messages); return true; }
diff --git a/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc index 6cc54cdc..09e3390 100644 --- a/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc +++ b/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc
@@ -32,7 +32,7 @@ if (!script) { HeapVector<Member<ConsoleMessage>> error_messages; error_messages.push_back(ConsoleMessage::CreateForRequest( - kJSMessageSource, kErrorMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kError, "Failed to load the script unexpectedly", fetch_params.Url().GetString(), nullptr, 0)); client->NotifyFetchFinished(base::nullopt, error_messages);
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.cc index da86ef0..dcec0d8 100644 --- a/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.cc +++ b/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.cc
@@ -63,7 +63,7 @@ "\". Strict MIME type checking is enforced for module scripts per " "HTML spec."; error_messages->push_back(ConsoleMessage::CreateForRequest( - kJSMessageSource, kErrorMessageLevel, message, + kJSMessageSource, mojom::ConsoleMessageLevel::kError, message, response.CurrentRequestUrl().GetString(), nullptr, resource->Identifier())); return false;
diff --git a/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc index 2a508a0..457ef64 100644 --- a/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc +++ b/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc
@@ -72,7 +72,7 @@ !global_scope_->GetSecurityOrigin()->IsSameSchemeHostPort( SecurityOrigin::Create(response_url).get())) { error_messages.push_back(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "Refused to cross-origin redirects of the top-level worker script.")); client_->NotifyFetchFinished(base::nullopt, error_messages); return;
diff --git a/third_party/blink/renderer/core/loader/preload_helper.cc b/third_party/blink/renderer/core/loader/preload_helper.cc index 7b73208..ae7fe2e 100644 --- a/third_party/blink/renderer/core/loader/preload_helper.cc +++ b/third_party/blink/renderer/core/loader/preload_helper.cc
@@ -117,7 +117,7 @@ if (settings->GetLogDnsPrefetchAndPreconnect()) { SendMessageToConsoleForPossiblyNullDocument( ConsoleMessage::Create( - kOtherMessageSource, kVerboseMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kVerbose, String("DNS prefetch triggered for " + params.href.Host())), document, frame); } @@ -141,12 +141,13 @@ if (settings && settings->GetLogDnsPrefetchAndPreconnect()) { SendMessageToConsoleForPossiblyNullDocument( ConsoleMessage::Create( - kOtherMessageSource, kVerboseMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kVerbose, String("Preconnect triggered for ") + params.href.GetString()), document, frame); if (params.cross_origin != kCrossOriginAttributeNotSet) { SendMessageToConsoleForPossiblyNullDocument( - ConsoleMessage::Create(kOtherMessageSource, kVerboseMessageLevel, + ConsoleMessage::Create(kOtherMessageSource, + mojom::ConsoleMessageLevel::kVerbose, String("Preconnect CORS setting is ") + String((params.cross_origin == kCrossOriginAttributeAnonymous) @@ -225,7 +226,7 @@ UseCounter::Count(document, WebFeature::kLinkRelPreload); if (!url.IsValid() || url.IsEmpty()) { document.AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kWarningMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, String("<link rel=preload> has an invalid `href` value"))); return nullptr; } @@ -242,14 +243,14 @@ UseCounter::Count(document, WebFeature::kLinkHeaderPreload); if (resource_type == base::nullopt) { document.AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kWarningMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, String("<link rel=preload> must have a valid `as` value"))); return nullptr; } if (!IsSupportedType(resource_type.value(), params.type)) { document.AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kWarningMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, String("<link rel=preload> has an unsupported `type` value"))); return nullptr; } @@ -276,7 +277,7 @@ Settings* settings = document.GetSettings(); if (settings && settings->GetLogPreload()) { document.AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kVerboseMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kVerbose, String("Preload triggered for " + url.Host() + url.GetPath()))); } link_fetch_params.SetLinkPreload(true); @@ -298,9 +299,9 @@ // Step 1. "If the href attribute's value is the empty string, then return." // [spec text] if (params.href.IsEmpty()) { - document.AddConsoleMessage( - ConsoleMessage::Create(kOtherMessageSource, kWarningMessageLevel, - "<link rel=modulepreload> has no `href` value")); + document.AddConsoleMessage(ConsoleMessage::Create( + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, + "<link rel=modulepreload> has no `href` value")); return; } @@ -323,7 +324,7 @@ // Currently we only support as="script". if (!params.as.IsEmpty() && params.as != "script") { document.AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kWarningMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, String("<link rel=modulepreload> has an invalid `as` value " + params.as))); // This triggers the same logic as Step 11 asynchronously, which will fire @@ -343,7 +344,7 @@ // |href| is already resolved in caller side. if (!params.href.IsValid()) { document.AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kWarningMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, "<link rel=modulepreload> has an invalid `href` value " + params.href.GetString())); return; @@ -405,10 +406,10 @@ Settings* settings = document.GetSettings(); if (settings && settings->GetLogPreload()) { - document.AddConsoleMessage( - ConsoleMessage::Create(kOtherMessageSource, kVerboseMessageLevel, - "Module preload triggered for " + - params.href.Host() + params.href.GetPath())); + document.AddConsoleMessage(ConsoleMessage::Create( + kOtherMessageSource, mojom::ConsoleMessageLevel::kVerbose, + "Module preload triggered for " + params.href.Host() + + params.href.GetPath())); } // Asynchronously continue processing after
diff --git a/third_party/blink/renderer/core/loader/previews_resource_loading_hints.cc b/third_party/blink/renderer/core/loader/previews_resource_loading_hints.cc index 68c172e..f228a5b 100644 --- a/third_party/blink/renderer/core/loader/previews_resource_loading_hints.cc +++ b/third_party/blink/renderer/core/loader/previews_resource_loading_hints.cc
@@ -129,9 +129,9 @@ void PreviewsResourceLoadingHints::ReportBlockedLoading( const KURL& resource_url) const { - execution_context_->AddConsoleMessage( - ConsoleMessage::Create(kOtherMessageSource, kWarningMessageLevel, - GetConsoleLogStringForBlockedLoad(resource_url))); + execution_context_->AddConsoleMessage(ConsoleMessage::Create( + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, + GetConsoleLogStringForBlockedLoad(resource_url))); } void PreviewsResourceLoadingHints::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource.cc b/third_party/blink/renderer/core/loader/resource/image_resource.cc index 20373d7..604990b 100644 --- a/third_party/blink/renderer/core/loader/resource/image_resource.cc +++ b/third_party/blink/renderer/core/loader/resource/image_resource.cc
@@ -89,6 +89,9 @@ private: const KURL& Url() const override { return resource_->Url(); } + TimeTicks LoadResponseEnd() const override { + return resource_->LoadResponseEnd(); + } bool IsSchedulingReload() const override { return resource_->is_scheduling_reload_; }
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_content.cc b/third_party/blink/renderer/core/loader/resource/image_resource_content.cc index 05d7b57..b2a1d1f3 100644 --- a/third_party/blink/renderer/core/loader/resource/image_resource_content.cc +++ b/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
@@ -40,6 +40,7 @@ private: const KURL& Url() const override { return url_; } + TimeTicks LoadResponseEnd() const override { return TimeTicks(); } bool IsSchedulingReload() const override { return false; } const ResourceResponse& GetResponse() const override { return response_; } bool ShouldShowPlaceholder() const override { return false; } @@ -615,6 +616,10 @@ return info_->Url(); } +TimeTicks ImageResourceContent::LoadResponseEnd() const { + return info_->LoadResponseEnd(); +} + bool ImageResourceContent::HasCacheControlNoStoreHeader() const { return info_->HasCacheControlNoStoreHeader(); }
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_content.h b/third_party/blink/renderer/core/loader/resource/image_resource_content.h index e975f4e..bfc1c72c 100644 --- a/third_party/blink/renderer/core/loader/resource/image_resource_content.h +++ b/third_party/blink/renderer/core/loader/resource/image_resource_content.h
@@ -107,6 +107,7 @@ // Redirecting methods to Resource. const KURL& Url() const; + TimeTicks LoadResponseEnd() const; bool IsAccessAllowed(); const ResourceResponse& GetResponse() const; base::Optional<ResourceError> GetResourceError() const;
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_info.h b/third_party/blink/renderer/core/loader/resource/image_resource_info.h index 1e8c7d5..f08d66a 100644 --- a/third_party/blink/renderer/core/loader/resource/image_resource_info.h +++ b/third_party/blink/renderer/core/loader/resource/image_resource_info.h
@@ -29,6 +29,7 @@ public: ~ImageResourceInfo() = default; virtual const KURL& Url() const = 0; + virtual TimeTicks LoadResponseEnd() const = 0; virtual bool IsSchedulingReload() const = 0; virtual const ResourceResponse& GetResponse() const = 0; virtual bool ShouldShowPlaceholder() const = 0;
diff --git a/third_party/blink/renderer/core/loader/subresource_filter.cc b/third_party/blink/renderer/core/loader/subresource_filter.cc index 1c7168a5..fe9566a 100644 --- a/third_party/blink/renderer/core/loader/subresource_filter.cc +++ b/third_party/blink/renderer/core/loader/subresource_filter.cc
@@ -130,7 +130,7 @@ // warning in Lighthouse. if (subresource_filter_->ShouldLogToConsole()) { execution_context_->AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kErrorMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kError, GetErrorStringForDisallowedLoad(resource_url))); } FALLTHROUGH;
diff --git a/third_party/blink/renderer/core/loader/subresource_integrity_helper.cc b/third_party/blink/renderer/core/loader/subresource_integrity_helper.cc index eab35b2..292b52c8d 100644 --- a/third_party/blink/renderer/core/loader/subresource_integrity_helper.cc +++ b/third_party/blink/renderer/core/loader/subresource_integrity_helper.cc
@@ -56,8 +56,8 @@ HeapVector<Member<ConsoleMessage>>* messages) { DCHECK(messages); for (const auto& message : report_info.ConsoleErrorMessages()) { - messages->push_back(ConsoleMessage::Create(kSecurityMessageSource, - kErrorMessageLevel, message)); + messages->push_back(ConsoleMessage::Create( + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, message)); } }
diff --git a/third_party/blink/renderer/core/loader/threadable_loader.cc b/third_party/blink/renderer/core/loader/threadable_loader.cc index d939cb2..36fde33 100644 --- a/third_party/blink/renderer/core/loader/threadable_loader.cc +++ b/third_party/blink/renderer/core/loader/threadable_loader.cc
@@ -622,7 +622,7 @@ ThreadableLoaderClient* client = client_; Clear(); ConsoleMessage* message = ConsoleMessage::Create( - kNetworkMessageSource, kErrorMessageLevel, + kNetworkMessageSource, mojom::ConsoleMessageLevel::kError, "Failed to load resource: net::ERR_TOO_MANY_REDIRECTS", SourceLocation::Capture(original_url, 0, 0)); execution_context_->AddConsoleMessage(message); @@ -1030,7 +1030,8 @@ *GetSecurityOrigin(), ResourceType::kRaw, resource_loader_options_.initiator_info.name); execution_context_->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kErrorMessageLevel, std::move(message))); + kJSMessageSource, mojom::ConsoleMessageLevel::kError, + std::move(message))); } Resource* resource = GetResource(); if (resource)
diff --git a/third_party/blink/renderer/core/page/chrome_client.cc b/third_party/blink/renderer/core/page/chrome_client.cc index e630fd49..3bdf7360 100644 --- a/third_party/blink/renderer/core/page/chrome_client.cc +++ b/third_party/blink/renderer/core/page/chrome_client.cc
@@ -257,7 +257,7 @@ UseCounter::Count(frame->GetDocument(), WebFeature::kDialogInSandboxedContext); frame->Console().AddMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "Ignored call to 'print()'. The document is sandboxed, and the " "'allow-modals' keyword is not set.")); return false;
diff --git a/third_party/blink/renderer/core/page/chrome_client.h b/third_party/blink/renderer/core/page/chrome_client.h index 27de71c..0557ac8 100644 --- a/third_party/blink/renderer/core/page/chrome_client.h +++ b/third_party/blink/renderer/core/page/chrome_client.h
@@ -30,6 +30,7 @@ #include "cc/input/event_listener_properties.h" #include "third_party/blink/public/common/dom_storage/session_storage_namespace_id.h" #include "third_party/blink/public/common/feature_policy/feature_policy.h" +#include "third_party/blink/public/mojom/devtools/console_message.mojom-shared.h" #include "third_party/blink/public/platform/blame_context.h" #include "third_party/blink/public/platform/web_drag_operation.h" #include "third_party/blink/public/platform/web_focus_type.h" @@ -38,7 +39,6 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/frame/sandbox_flags.h" #include "third_party/blink/renderer/core/html/forms/popup_menu.h" -#include "third_party/blink/renderer/core/inspector/console_types.h" #include "third_party/blink/renderer/core/loader/frame_loader.h" #include "third_party/blink/renderer/core/loader/navigation_policy.h" #include "third_party/blink/renderer/core/scroll/scroll_types.h" @@ -179,7 +179,7 @@ const String& source) = 0; virtual void AddMessageToConsole(LocalFrame*, MessageSource, - MessageLevel, + mojom::ConsoleMessageLevel, const String& message, unsigned line_number, const String& source_id,
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.cc b/third_party/blink/renderer/core/page/chrome_client_impl.cc index 15910249..cb0aa30 100644 --- a/third_party/blink/renderer/core/page/chrome_client_impl.cc +++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -309,7 +309,7 @@ void ChromeClientImpl::AddMessageToConsole(LocalFrame* local_frame, MessageSource source, - MessageLevel level, + mojom::ConsoleMessageLevel level, const String& message, unsigned line_number, const String& source_id,
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.h b/third_party/blink/renderer/core/page/chrome_client_impl.h index d3ae2e0..baccaaf 100644 --- a/third_party/blink/renderer/core/page/chrome_client_impl.h +++ b/third_party/blink/renderer/core/page/chrome_client_impl.h
@@ -94,7 +94,7 @@ const String&) override; void AddMessageToConsole(LocalFrame*, MessageSource, - MessageLevel, + mojom::ConsoleMessageLevel, const String& message, unsigned line_number, const String& source_id,
diff --git a/third_party/blink/renderer/core/page/create_window.cc b/third_party/blink/renderer/core/page/create_window.cc index 85519fd..6ee6ab7 100644 --- a/third_party/blink/renderer/core/page/create_window.cc +++ b/third_party/blink/renderer/core/page/create_window.cc
@@ -335,7 +335,7 @@ // FIXME: This message should be moved off the console once a solution to // https://bugs.webkit.org/show_bug.cgi?id=103274 exists. opener_frame.GetDocument()->AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "Blocked opening '" + request.GetResourceRequest().Url().ElidedString() + "' in a new window because the request was made in a sandboxed "
diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc index 926b3bb..27bbf66 100644 --- a/third_party/blink/renderer/core/page/page.cc +++ b/third_party/blink/renderer/core/page/page.cc
@@ -828,9 +828,9 @@ void Page::ReportIntervention(const String& text) { if (LocalFrame* local_frame = DeprecatedLocalMainFrame()) { - ConsoleMessage* message = - ConsoleMessage::Create(kOtherMessageSource, kWarningMessageLevel, text, - SourceLocation::Create(String(), 0, 0, nullptr)); + ConsoleMessage* message = ConsoleMessage::Create( + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, text, + SourceLocation::Create(String(), 0, 0, nullptr)); local_frame->GetDocument()->AddConsoleMessage(message); } }
diff --git a/third_party/blink/renderer/core/page/pointer_lock_controller.cc b/third_party/blink/renderer/core/page/pointer_lock_controller.cc index 7ab0459..7ac1e69 100644 --- a/third_party/blink/renderer/core/page/pointer_lock_controller.cc +++ b/third_party/blink/renderer/core/page/pointer_lock_controller.cc
@@ -61,7 +61,7 @@ // FIXME: This message should be moved off the console once a solution to // https://bugs.webkit.org/show_bug.cgi?id=103274 exists. target->GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, + kSecurityMessageSource, mojom::ConsoleMessageLevel::kError, "Blocked pointer lock on an element because the element's frame is " "sandboxed and the 'allow-pointer-lock' permission is not set.")); EnqueueEvent(event_type_names::kPointerlockerror, target);
diff --git a/third_party/blink/renderer/core/paint/image_element_timing.cc b/third_party/blink/renderer/core/paint/image_element_timing.cc index 57eb727..d5ddb61 100644 --- a/third_party/blink/renderer/core/paint/image_element_timing.cc +++ b/third_party/blink/renderer/core/paint/image_element_timing.cc
@@ -102,14 +102,9 @@ return; } - // Compute the |name| for the entry. Use the 'elementtiming' attribute. If - // empty, use the ID. If empty, use 'img'. - AtomicString name = attr; - if (name.IsEmpty()) - name = element->FastGetAttribute(html_names::kIdAttr); - if (name.IsEmpty()) - name = "img"; - element_timings_.emplace_back(name, visible_new_visual_rect); + element_timings_.emplace_back(AtomicString(cached_image->Url().GetString()), + visible_new_visual_rect, + cached_image->LoadResponseEnd(), attr); // Only queue a swap promise when |element_timings_| was empty. All of the // records in |element_timings_| will be processed when the promise succeeds // or fails, and at that time the vector is cleared. @@ -128,7 +123,8 @@ performance->ShouldBufferEntries())) { for (const auto& element_timing : element_timings_) { performance->AddElementTiming(element_timing.name, element_timing.rect, - timestamp); + timestamp, element_timing.response_end, + element_timing.identifier); } } element_timings_.clear();
diff --git a/third_party/blink/renderer/core/paint/image_element_timing.h b/third_party/blink/renderer/core/paint/image_element_timing.h index 6c08c87..1c3b110 100644 --- a/third_party/blink/renderer/core/paint/image_element_timing.h +++ b/third_party/blink/renderer/core/paint/image_element_timing.h
@@ -52,10 +52,19 @@ // Struct containing information about image element timing. struct ElementTimingInfo { + ElementTimingInfo(const AtomicString& name, + IntRect rect, + TimeTicks response_end, + const AtomicString& identifier) + : name(name), + rect(rect), + response_end(response_end), + identifier(identifier) {} + AtomicString name; IntRect rect; - ElementTimingInfo(AtomicString name, IntRect rect) - : name(name), rect(rect) {} + TimeTicks response_end; + AtomicString identifier; }; // Vector containing the element timing infos that will be reported during the // next swap promise callback.
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc index 5cfbc3b..9504842 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
@@ -83,9 +83,9 @@ // this fragment is at the end of line. if (selection_status.line_break == SelectSoftLineBreak::kNotSelected) return rect; - if (paint_fragment.GetLayoutObject() - ->ContainingNGBlockFlow() - ->ShouldTruncateOverflowingText()) + LayoutBlockFlow* layout_block_flow = + paint_fragment.GetLayoutObject()->ContainingNGBlockFlow(); + if (layout_block_flow && layout_block_flow->ShouldTruncateOverflowingText()) return rect; // Copy from InlineTextBoxPainter::PaintSelection. const LayoutUnit space_width(paint_fragment.Style().GetFont().SpaceWidth());
diff --git a/third_party/blink/renderer/core/script/document_write_intervention.cc b/third_party/blink/renderer/core/script/document_write_intervention.cc index 692610b..c9bfcd3 100644 --- a/third_party/blink/renderer/core/script/document_write_intervention.cc +++ b/third_party/blink/renderer/core/script/document_write_intervention.cc
@@ -31,8 +31,8 @@ "confirmed in a subsequent console message. " "See https://www.chromestatus.com/feature/5718547946799104 " "for more details."; - document.AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, message)); + document.AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); DVLOG(1) << message.Utf8().data(); } @@ -42,8 +42,8 @@ ", invoked via document.write was NOT BLOCKED on this page load, but MAY " "be blocked by the browser in future page loads with poor network " "connectivity."; - document.AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, message)); + document.AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); } void EmitErrorBlocked(const String& url, Document& document) { @@ -54,7 +54,7 @@ ", invoked via document.write was BLOCKED by the browser due to poor " "network connectivity. "; document.AddConsoleMessage(ConsoleMessage::Create( - kInterventionMessageSource, kErrorMessageLevel, message)); + kInterventionMessageSource, mojom::ConsoleMessageLevel::kError, message)); } void AddWarningHeader(FetchParameters* params) {
diff --git a/third_party/blink/renderer/core/script/script_loader.cc b/third_party/blink/renderer/core/script/script_loader.cc index 2fd42f0..689e83e9 100644 --- a/third_party/blink/renderer/core/script/script_loader.cc +++ b/third_party/blink/renderer/core/script/script_loader.cc
@@ -185,16 +185,16 @@ if (!modulator->IsAcquiringImportMaps()) { element_document.AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kErrorMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kError, "An import map is added after module script load was triggered.")); return ShouldFireErrorEvent::kShouldFire; } // TODO(crbug.com/922212): Implemenet external import maps. if (element.HasSourceAttribute()) { - element_document.AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kErrorMessageLevel, - "External import maps are not yet supported.")); + element_document.AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kError, + "External import maps are not yet supported.")); return ShouldFireErrorEvent::kShouldFire; } @@ -408,7 +408,7 @@ if (ShouldBlockSyncScriptForFeaturePolicy(element_.Get(), GetScriptType(), parser_inserted_)) { element_document.AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kErrorMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kError, "Synchronous script execution is disabled by Feature Policy")); return false; }
diff --git a/third_party/blink/renderer/core/script/xml_parser_script_runner.cc b/third_party/blink/renderer/core/script/xml_parser_script_runner.cc index 91340e90..f7b2ed8 100644 --- a/third_party/blink/renderer/core/script/xml_parser_script_runner.cc +++ b/third_party/blink/renderer/core/script/xml_parser_script_runner.cc
@@ -79,10 +79,10 @@ if (script_loader->GetScriptType() != mojom::ScriptType::kClassic) { // XMLDocumentParser does not support a module script, and thus ignores it. success = false; - document.AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kErrorMessageLevel, - "Module scripts in XML documents are currently " - "not supported. See crbug.com/717643")); + document.AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kError, + "Module scripts in XML documents are currently " + "not supported. See crbug.com/717643")); } if (!success)
diff --git a/third_party/blink/renderer/core/svg/svg_element.cc b/third_party/blink/renderer/core/svg/svg_element.cc index 3e64fed..98977d27 100644 --- a/third_party/blink/renderer/core/svg/svg_element.cc +++ b/third_party/blink/renderer/core/svg/svg_element.cc
@@ -159,9 +159,9 @@ // Don't report any errors on attribute removal. if (value.IsNull()) return; - GetDocument().AddConsoleMessage( - ConsoleMessage::Create(kRenderingMessageSource, kErrorMessageLevel, - "Error: " + error.Format(tagName(), name, value))); + GetDocument().AddConsoleMessage(ConsoleMessage::Create( + kRenderingMessageSource, mojom::ConsoleMessageLevel::kError, + "Error: " + error.Format(tagName(), name, value))); } String SVGElement::title() const {
diff --git a/third_party/blink/renderer/core/svg/svg_image_element.cc b/third_party/blink/renderer/core/svg/svg_image_element.cc index 2556bfc..fa9224a 100644 --- a/third_party/blink/renderer/core/svg/svg_image_element.cc +++ b/third_party/blink/renderer/core/svg/svg_image_element.cc
@@ -182,7 +182,7 @@ &is_default_overridden_intrinsic_size_, &message); if (!message.IsEmpty()) { GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kWarningMessageLevel, message)); + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); } if (intrinsic_size_changed) {
diff --git a/third_party/blink/renderer/core/timing/performance.cc b/third_party/blink/renderer/core/timing/performance.cc index 5c850ab..7a08fd1 100644 --- a/third_party/blink/renderer/core/timing/performance.cc +++ b/third_party/blink/renderer/core/timing/performance.cc
@@ -252,7 +252,7 @@ PerformanceEntryVector empty_entries; String message = "Deprecated API for given entry type."; GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, message)); + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); return empty_entries; } return getEntriesByTypeInternal(type); @@ -507,7 +507,7 @@ result.alpn_negotiated_protocol = final_response.AlpnNegotiatedProtocol(); result.connection_info = final_response.ConnectionInfoString(); result.timing = final_response.GetResourceLoadTiming(); - result.finish_time = info.LoadFinishTime(); + result.response_end = info.LoadResponseEnd(); result.allow_timing_details = PassesTimingAllowCheck( final_response, destination_origin, &context_for_use_counter);
diff --git a/third_party/blink/renderer/core/timing/performance_element_timing.cc b/third_party/blink/renderer/core/timing/performance_element_timing.cc index 0d74d8ef..31220830 100644 --- a/third_party/blink/renderer/core/timing/performance_element_timing.cc +++ b/third_party/blink/renderer/core/timing/performance_element_timing.cc
@@ -13,17 +13,23 @@ PerformanceElementTiming* PerformanceElementTiming::Create( const AtomicString& name, const IntRect& intersection_rect, - DOMHighResTimeStamp start_time) { - return MakeGarbageCollected<PerformanceElementTiming>(name, intersection_rect, - start_time); + DOMHighResTimeStamp start_time, + DOMHighResTimeStamp response_end, + const AtomicString& identifier) { + return MakeGarbageCollected<PerformanceElementTiming>( + name, intersection_rect, start_time, response_end, identifier); } PerformanceElementTiming::PerformanceElementTiming( const AtomicString& name, const IntRect& intersection_rect, - DOMHighResTimeStamp start_time) + DOMHighResTimeStamp start_time, + DOMHighResTimeStamp response_end, + const AtomicString& identifier) : PerformanceEntry(name, start_time, start_time), - intersection_rect_(DOMRectReadOnly::FromIntRect(intersection_rect)) {} + intersection_rect_(DOMRectReadOnly::FromIntRect(intersection_rect)), + response_end_(response_end), + identifier_(identifier) {} PerformanceElementTiming::~PerformanceElementTiming() = default;
diff --git a/third_party/blink/renderer/core/timing/performance_element_timing.h b/third_party/blink/renderer/core/timing/performance_element_timing.h index 35c0c913..b7653c1a 100644 --- a/third_party/blink/renderer/core/timing/performance_element_timing.h +++ b/third_party/blink/renderer/core/timing/performance_element_timing.h
@@ -22,11 +22,15 @@ public: static PerformanceElementTiming* Create(const AtomicString& name, const IntRect& intersection_rect, - DOMHighResTimeStamp start_time); + DOMHighResTimeStamp start_time, + DOMHighResTimeStamp response_end, + const AtomicString& identifier); PerformanceElementTiming(const AtomicString& name, const IntRect& intersection_rect, - DOMHighResTimeStamp start_time); + DOMHighResTimeStamp start_time, + DOMHighResTimeStamp response_end, + const AtomicString& identifier); ~PerformanceElementTiming() override; AtomicString entryType() const override; @@ -34,12 +38,18 @@ DOMRectReadOnly* intersectionRect() const { return intersection_rect_; } + DOMHighResTimeStamp responseEnd() const { return response_end_; } + + AtomicString identifier() const { return identifier_; } + void Trace(blink::Visitor*) override; private: void BuildJSONValue(V8ObjectBuilder&) const override; Member<DOMRectReadOnly> intersection_rect_; + DOMHighResTimeStamp response_end_; + AtomicString identifier_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/timing/performance_element_timing.idl b/third_party/blink/renderer/core/timing/performance_element_timing.idl index ef9982f..3796be6 100644 --- a/third_party/blink/renderer/core/timing/performance_element_timing.idl +++ b/third_party/blink/renderer/core/timing/performance_element_timing.idl
@@ -6,6 +6,8 @@ [OriginTrialEnabled=ElementTiming] interface PerformanceElementTiming : PerformanceEntry { readonly attribute DOMRectReadOnly intersectionRect; + readonly attribute DOMHighResTimeStamp responseEnd; + readonly attribute DOMString identifier; // TODO(peria): toJSON is not in spec. https://crbug.com/736332 [CallWith=ScriptState, ImplementedAs=toJSONForBinding] object toJSON();
diff --git a/third_party/blink/renderer/core/timing/performance_observer.cc b/third_party/blink/renderer/core/timing/performance_observer.cc index 9e124dc..1c400b6 100644 --- a/third_party/blink/renderer/core/timing/performance_observer.cc +++ b/third_party/blink/renderer/core/timing/performance_observer.cc
@@ -128,7 +128,7 @@ "its " "entryTypes attribute."; GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, message)); + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); return; } if (RuntimeEnabledFeatures::PerformanceObserverBufferedFlagEnabled() && @@ -137,7 +137,7 @@ "The Performance Observer does not support buffered flag with " "entryTypes. "; GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, message)); + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); } filter_options_ = entry_types; } else { @@ -162,7 +162,7 @@ "The Performance Observer MUST have a valid entryType in its " "type attribute."; GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, message)); + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); return; } if (filter_options_ & entry_type) { @@ -170,7 +170,7 @@ "The Performance Observer has already been called with this " "entryType"; GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, message)); + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); return; } if (RuntimeEnabledFeatures::PerformanceObserverBufferedFlagEnabled() && @@ -179,7 +179,7 @@ String message = "Buffered flag does not support the long task entry type "; GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, message)); + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); } else { // Append all entries of this type to the current performance_entries_ // to be returned on the next callback.
diff --git a/third_party/blink/renderer/core/timing/performance_resource_timing.cc b/third_party/blink/renderer/core/timing/performance_resource_timing.cc index bb8cb0d3..ee5bb1bd 100644 --- a/third_party/blink/renderer/core/timing/performance_resource_timing.cc +++ b/third_party/blink/renderer/core/timing/performance_resource_timing.cc
@@ -53,7 +53,7 @@ info.allow_negative_values), Performance::MonotonicTimeToDOMHighResTimeStamp( time_origin, - info.finish_time, + info.response_end, info.allow_negative_values)), initiator_type_(initiator_type.IsEmpty() ? fetch_initiator_type_names::kOther @@ -64,7 +64,7 @@ time_origin_(time_origin), timing_(info.timing), last_redirect_end_time_(info.last_redirect_end_time), - finish_time_(info.finish_time), + response_end_(info.response_end), transfer_size_(info.transfer_size), encoded_body_size_(info.encoded_body_size), decoded_body_size_(info.decoded_body_size), @@ -303,11 +303,11 @@ } DOMHighResTimeStamp PerformanceResourceTiming::responseEnd() const { - if (finish_time_.is_null()) + if (response_end_.is_null()) return responseStart(); return Performance::MonotonicTimeToDOMHighResTimeStamp( - time_origin_, finish_time_, allow_negative_value_); + time_origin_, response_end_, allow_negative_value_); } unsigned long long PerformanceResourceTiming::transferSize() const {
diff --git a/third_party/blink/renderer/core/timing/performance_resource_timing.h b/third_party/blink/renderer/core/timing/performance_resource_timing.h index 6057885..25da939 100644 --- a/third_party/blink/renderer/core/timing/performance_resource_timing.h +++ b/third_party/blink/renderer/core/timing/performance_resource_timing.h
@@ -118,7 +118,7 @@ TimeTicks time_origin_; scoped_refptr<ResourceLoadTiming> timing_; TimeTicks last_redirect_end_time_; - TimeTicks finish_time_; + TimeTicks response_end_; unsigned long long transfer_size_; unsigned long long encoded_body_size_; unsigned long long decoded_body_size_;
diff --git a/third_party/blink/renderer/core/timing/window_performance.cc b/third_party/blink/renderer/core/timing/window_performance.cc index 69931ecf..b8d9093 100644 --- a/third_party/blink/renderer/core/timing/window_performance.cc +++ b/third_party/blink/renderer/core/timing/window_performance.cc
@@ -399,10 +399,13 @@ void WindowPerformance::AddElementTiming(const AtomicString& name, const IntRect& rect, - TimeTicks timestamp) { + TimeTicks start_time, + TimeTicks response_end, + const AtomicString& identifier) { DCHECK(origin_trials::ElementTimingEnabled(GetExecutionContext())); PerformanceElementTiming* entry = PerformanceElementTiming::Create( - name, rect, MonotonicTimeToDOMHighResTimeStamp(timestamp)); + name, rect, MonotonicTimeToDOMHighResTimeStamp(start_time), + MonotonicTimeToDOMHighResTimeStamp(response_end), identifier); if (HasObserverFor(PerformanceEntry::kElement)) { UseCounter::Count(GetFrame()->GetDocument(), WebFeature::kElementTimingExplicitlyRequested);
diff --git a/third_party/blink/renderer/core/timing/window_performance.h b/third_party/blink/renderer/core/timing/window_performance.h index d4182035..e9c85205 100644 --- a/third_party/blink/renderer/core/timing/window_performance.h +++ b/third_party/blink/renderer/core/timing/window_performance.h
@@ -82,7 +82,9 @@ void AddElementTiming(const AtomicString& name, const IntRect& rect, - TimeTicks timestamp); + TimeTicks start_time, + TimeTicks response_end, + const AtomicString& identifier); void AddLayoutJankFraction(double jank_fraction);
diff --git a/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.cc b/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.cc index 3e7d6d9..f35eb17 100644 --- a/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.cc +++ b/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.cc
@@ -54,10 +54,11 @@ // https://html.spec.whatwg.org/C/#runtime-script-errors-2 } -void SharedWorkerReportingProxy::ReportConsoleMessage(MessageSource, - MessageLevel, - const String& message, - SourceLocation*) { +void SharedWorkerReportingProxy::ReportConsoleMessage( + MessageSource, + mojom::ConsoleMessageLevel, + const String& message, + SourceLocation*) { DCHECK(!IsMainThread()); // Not supported in SharedWorker. }
diff --git a/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.h b/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.h index d2971f91..0b0faaa 100644 --- a/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.h +++ b/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.h
@@ -32,7 +32,7 @@ std::unique_ptr<SourceLocation>, int exception_id) override; void ReportConsoleMessage(MessageSource, - MessageLevel, + mojom::ConsoleMessageLevel, const String& message, SourceLocation*) override; void DidFetchScript() override;
diff --git a/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.cc b/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.cc index 553b6e59..65b8816 100644 --- a/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.cc +++ b/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.cc
@@ -92,7 +92,7 @@ void ThreadedMessagingProxyBase::ReportConsoleMessage( MessageSource source, - MessageLevel level, + mojom::ConsoleMessageLevel level, const String& message, std::unique_ptr<SourceLocation> location) { DCHECK(IsParentContextThread());
diff --git a/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.h b/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.h index d4b61b1..2415fc8 100644 --- a/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.h +++ b/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.h
@@ -6,9 +6,9 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_THREADED_MESSAGING_PROXY_BASE_H_ #include "base/optional.h" +#include "third_party/blink/public/mojom/devtools/console_message.mojom-shared.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/frame/web_feature_forward.h" -#include "third_party/blink/renderer/core/inspector/console_types.h" #include "third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h" #include "third_party/blink/renderer/core/workers/worker_backing_thread_startup_data.h" #include "third_party/blink/renderer/core/workers/worker_thread.h" @@ -56,7 +56,7 @@ void CountDeprecation(WebFeature); void ReportConsoleMessage(MessageSource, - MessageLevel, + mojom::ConsoleMessageLevel, const String& message, std::unique_ptr<SourceLocation>);
diff --git a/third_party/blink/renderer/core/workers/threaded_object_proxy_base.cc b/third_party/blink/renderer/core/workers/threaded_object_proxy_base.cc index 1730f2ef..79d2b67 100644 --- a/third_party/blink/renderer/core/workers/threaded_object_proxy_base.cc +++ b/third_party/blink/renderer/core/workers/threaded_object_proxy_base.cc
@@ -31,10 +31,11 @@ MessagingProxyWeakPtr(), feature)); } -void ThreadedObjectProxyBase::ReportConsoleMessage(MessageSource source, - MessageLevel level, - const String& message, - SourceLocation* location) { +void ThreadedObjectProxyBase::ReportConsoleMessage( + MessageSource source, + mojom::ConsoleMessageLevel level, + const String& message, + SourceLocation* location) { PostCrossThreadTask( *GetParentExecutionContextTaskRunners()->Get(TaskType::kInternalDefault), FROM_HERE,
diff --git a/third_party/blink/renderer/core/workers/threaded_object_proxy_base.h b/third_party/blink/renderer/core/workers/threaded_object_proxy_base.h index b8bbe9e..3de08bc2a 100644 --- a/third_party/blink/renderer/core/workers/threaded_object_proxy_base.h +++ b/third_party/blink/renderer/core/workers/threaded_object_proxy_base.h
@@ -32,7 +32,7 @@ void CountFeature(WebFeature) override; void CountDeprecation(WebFeature) override; void ReportConsoleMessage(MessageSource, - MessageLevel, + mojom::ConsoleMessageLevel, const String& message, SourceLocation*) override; void DidCloseWorkerGlobalScope() override;
diff --git a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc index 59d46b70..87b5d91 100644 --- a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc +++ b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
@@ -234,9 +234,9 @@ // Adds a deprecation message to the console. DCHECK(!Deprecation::DeprecationMessage(feature).IsEmpty()); - AddConsoleMessage( - ConsoleMessage::Create(kDeprecationMessageSource, kWarningMessageLevel, - Deprecation::DeprecationMessage(feature))); + AddConsoleMessage(ConsoleMessage::Create( + kDeprecationMessageSource, mojom::ConsoleMessageLevel::kWarning, + Deprecation::DeprecationMessage(feature))); ReportingProxy().CountDeprecation(feature); }
diff --git a/third_party/blink/renderer/core/workers/worker_reporting_proxy.h b/third_party/blink/renderer/core/workers/worker_reporting_proxy.h index 6362342a..2f48598 100644 --- a/third_party/blink/renderer/core/workers/worker_reporting_proxy.h +++ b/third_party/blink/renderer/core/workers/worker_reporting_proxy.h
@@ -32,6 +32,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_REPORTING_PROXY_H_ #include <memory> +#include "third_party/blink/public/mojom/devtools/console_message.mojom-shared.h" #include "third_party/blink/renderer/bindings/core/v8/source_location.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/frame/web_feature_forward.h" @@ -57,7 +58,7 @@ std::unique_ptr<SourceLocation>, int exception_id) {} virtual void ReportConsoleMessage(MessageSource, - MessageLevel, + mojom::ConsoleMessageLevel, const String& message, SourceLocation*) {}
diff --git a/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc b/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc index 4474f22..66e44e3 100644 --- a/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc +++ b/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc
@@ -577,8 +577,8 @@ XMLDocumentParserScope::current_document_->Url().ElidedString() + ". Domains, protocols and ports must match.\n"; XMLDocumentParserScope::current_document_->AddConsoleMessage( - ConsoleMessage::Create(kSecurityMessageSource, kErrorMessageLevel, - message)); + ConsoleMessage::Create(kSecurityMessageSource, + mojom::ConsoleMessageLevel::kError, message)); } return false; }
diff --git a/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc b/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc index 47e5f3c..67caaaf 100644 --- a/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc +++ b/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc
@@ -65,18 +65,18 @@ if (!console) return; - MessageLevel level; + mojom::ConsoleMessageLevel level; switch (error->level) { case XML_ERR_NONE: - level = kVerboseMessageLevel; + level = mojom::ConsoleMessageLevel::kVerbose; break; case XML_ERR_WARNING: - level = kWarningMessageLevel; + level = mojom::ConsoleMessageLevel::kWarning; break; case XML_ERR_ERROR: case XML_ERR_FATAL: default: - level = kErrorMessageLevel; + level = mojom::ConsoleMessageLevel::kError; break; }
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc index 9496172..5740ad6 100644 --- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc +++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
@@ -193,8 +193,8 @@ // FIXME: It's not good to report the bad usage without indicating what source // line it came from. We should pass additional parameters so we can tell the // console where the mistake occurred. - ConsoleMessage* console_message = - ConsoleMessage::Create(kJSMessageSource, kErrorMessageLevel, message); + ConsoleMessage* console_message = ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kError, message); context->AddConsoleMessage(console_message); }
diff --git a/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc b/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc index 6943cd95..3e7893e 100644 --- a/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc +++ b/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc
@@ -452,10 +452,10 @@ // support is in. if (!playback_rate) { if (document_->GetFrame() && ExecutionContext::From(script_state)) { - document_->GetFrame()->Console().AddMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, - "WorkletAnimation currently does not support " - "playback rate of Zero.")); + document_->GetFrame()->Console().AddMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, + "WorkletAnimation currently does not support " + "playback rate of Zero.")); } return; }
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth.cc index b71004e..d25574f 100644 --- a/third_party/blink/renderer/modules/bluetooth/bluetooth.cc +++ b/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
@@ -166,7 +166,7 @@ #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX) && \ !defined(OS_WIN) context->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kInfoMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kInfo, "Web Bluetooth is experimental on this platform. See " "https://github.com/WebBluetoothCG/web-bluetooth/blob/gh-pages/" "implementation-status.md")); @@ -286,7 +286,7 @@ // Remind developers when they are using Web Bluetooth on unsupported // platforms. context->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kInfoMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kInfo, "Web Bluetooth Scanning is experimental on this platform. See " "https://github.com/WebBluetoothCG/web-bluetooth/blob/gh-pages/" "implementation-status.md"));
diff --git a/third_party/blink/renderer/modules/cache_storage/cache.cc b/third_party/blink/renderer/modules/cache_storage/cache.cc index 807e78e..ea66a8f4 100644 --- a/third_party/blink/renderer/modules/cache_storage/cache.cc +++ b/third_party/blink/renderer/modules/cache_storage/cache.cc
@@ -246,7 +246,8 @@ resolver->Resolve(); if (message) { context->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, message)); + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, + message)); // If the message indicates there were duplicate requests in // the batch argument list, but the operation succeeded @@ -887,7 +888,8 @@ } if (report_to_console && message) { context->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, message)); + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, + message)); } }, WrapPersistent(resolver), base::TimeTicks::Now(),
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc b/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc index 2c427ce86..8cdf0f7 100644 --- a/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc +++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc
@@ -180,7 +180,8 @@ "features.md#sensor-features", event_name.Ascii().data()); ConsoleMessage* console_message = ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, std::move(message)); + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, + std::move(message)); frame->Console().AddMessage(console_message); }
diff --git a/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.cc b/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.cc index e9475fc..4badd6d4 100644 --- a/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.cc +++ b/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.cc
@@ -418,7 +418,8 @@ event = CreateEncryptedEvent(WebEncryptedMediaInitDataType::kUnknown, nullptr, 0); media_element_->GetExecutionContext()->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, + ConsoleMessage::Create(kJSMessageSource, + mojom::ConsoleMessageLevel::kWarning, "Media element must be CORS-same-origin with " "the embedding page. If cross-origin, you " "should use the `crossorigin` attribute and "
diff --git a/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc b/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc index abbac260..9b1b7b8 100644 --- a/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc +++ b/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc
@@ -295,7 +295,7 @@ // using an empty robustness here, and provide the link to the doc in this // message. See http://crbug.com/720013 resolver_->GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "It is recommended that a robustness level be specified. Not " "specifying the robustness level could result in unexpected " "behavior.")); @@ -333,9 +333,9 @@ ReportOptions::kReportOnFailure)) { UseCounter::Count(document, WebFeature::kEncryptedMediaDisabledByFeaturePolicy); - document->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, - kEncryptedMediaFeaturePolicyConsoleWarning)); + document->AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, + kEncryptedMediaFeaturePolicyConsoleWarning)); return ScriptPromise::RejectWithDOMException( script_state, DOMException::Create(
diff --git a/third_party/blink/renderer/modules/eventsource/event_source.cc b/third_party/blink/renderer/modules/eventsource/event_source.cc index 0bbeb3c..8802168 100644 --- a/third_party/blink/renderer/modules/eventsource/event_source.cc +++ b/third_party/blink/renderer/modules/eventsource/event_source.cc
@@ -243,7 +243,8 @@ message.Append("\") that is not UTF-8. Aborting the connection."); // FIXME: We are missing the source line. GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kErrorMessageLevel, message.ToString())); + kJSMessageSource, mojom::ConsoleMessageLevel::kError, + message.ToString())); } } else { // To keep the signal-to-noise ratio low, we only log 200-response with an @@ -256,7 +257,8 @@ "\") that is not \"text/event-stream\". Aborting the connection."); // FIXME: We are missing the source line. GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kErrorMessageLevel, message.ToString())); + kJSMessageSource, mojom::ConsoleMessageLevel::kError, + message.ToString())); } }
diff --git a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc index 48757ee2..3cdea92b 100644 --- a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc +++ b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
@@ -262,27 +262,8 @@ void WebEmbeddedWorkerImpl::AddMessageToConsole( const WebConsoleMessage& message) { - MessageLevel web_core_message_level; - switch (message.level) { - case mojom::ConsoleMessageLevel::kVerbose: - web_core_message_level = kVerboseMessageLevel; - break; - case mojom::ConsoleMessageLevel::kInfo: - web_core_message_level = kInfoMessageLevel; - break; - case mojom::ConsoleMessageLevel::kWarning: - web_core_message_level = kWarningMessageLevel; - break; - case mojom::ConsoleMessageLevel::kError: - web_core_message_level = kErrorMessageLevel; - break; - default: - NOTREACHED(); - return; - } - shadow_page_->GetDocument()->AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, web_core_message_level, message.text, + kOtherMessageSource, message.level, message.text, SourceLocation::Create(message.url, message.line_number, message.column_number, nullptr))); }
diff --git a/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc b/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc index 01b79e3..67c16eb2 100644 --- a/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc +++ b/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc
@@ -90,7 +90,7 @@ if (options->hasAudioBitsPerSecond() || options->hasBitsPerSecond()) { if (audio_bps > kLargestAutoAllocatedOpusBitRate) { context->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "Clamping calculated audio bitrate (" + String::Number(audio_bps) + "bps) to the maximum (" + String::Number(kLargestAutoAllocatedOpusBitRate) + "bps)")); @@ -99,7 +99,7 @@ if (audio_bps < kSmallestPossibleOpusBitRate) { context->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "Clamping calculated audio bitrate (" + String::Number(audio_bps) + "bps) to the minimum (" + String::Number(kSmallestPossibleOpusBitRate) + "bps)")); @@ -119,7 +119,7 @@ if (options->hasVideoBitsPerSecond() || options->hasBitsPerSecond()) { if (video_bps < kSmallestPossibleVpxBitRate) { context->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "Clamping calculated video bitrate (" + String::Number(video_bps) + "bps) to the minimum (" + String::Number(kSmallestPossibleVpxBitRate) + "bps)"));
diff --git a/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.cc b/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.cc index 983ab58..3cf3b0f 100644 --- a/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.cc +++ b/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.cc
@@ -41,7 +41,7 @@ if (!src.ProtocolIs(url::kHttpScheme) && !src.ProtocolIs(url::kHttpsScheme) && !src.ProtocolIs(url::kDataScheme) && !src.ProtocolIs(url::kBlobScheme)) { context->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "MediaImage src can only be of http/https/data/blob scheme: " + src.GetString())); return false; @@ -50,7 +50,7 @@ DCHECK(src.GetString().Is8Bit()); if (src.GetString().length() > url::kMaxURLChars) { context->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "MediaImage src exceeds maximum URL length: " + src.GetString())); return false; } @@ -76,7 +76,7 @@ mojo_image->sizes.push_back(web_size); if (mojo_image->sizes.size() == kMaxNumberOfImageSizes) { context->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "The number of MediaImage sizes exceeds the upper limit. " "All remaining MediaImage will be ignored")); break; @@ -107,7 +107,7 @@ mojo_metadata->artwork.push_back(std::move(mojo_image)); if (mojo_metadata->artwork.size() == kMaxNumberOfMediaImages) { context->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "The number of MediaImage sizes exceeds the upper limit. " "All remaining MediaImage will be ignored")); break;
diff --git a/third_party/blink/renderer/modules/mediastream/media_constraints_impl.cc b/third_party/blink/renderer/modules/mediastream/media_constraints_impl.cc index 1024e47..b637964 100644 --- a/third_party/blink/renderer/modules/mediastream/media_constraints_impl.cc +++ b/third_party/blink/renderer/modules/mediastream/media_constraints_impl.cc
@@ -418,7 +418,7 @@ // TODO(crbug.com/856176): Remove the kGoogBeamforming and // kGoogArrayGeometry special cases. context->AddConsoleMessage(ConsoleMessage::Create( - kDeprecationMessageSource, kWarningMessageLevel, + kDeprecationMessageSource, mojom::ConsoleMessageLevel::kWarning, "Obsolete constraint named " + String(constraint.name_) + " is ignored. Please stop using it.")); } else if (constraint.name_.Equals(kVideoKind)) { @@ -442,7 +442,7 @@ // TODO(hta): UMA stats for unknown constraints passed. // https://crbug.com/576613 context->AddConsoleMessage(ConsoleMessage::Create( - kDeprecationMessageSource, kWarningMessageLevel, + kDeprecationMessageSource, mojom::ConsoleMessageLevel::kWarning, "Unknown constraint named " + String(constraint.name_) + " rejected")); // TODO(crbug.com/856176): Don't throw an error.
diff --git a/third_party/blink/renderer/modules/netinfo/network_information.cc b/third_party/blink/renderer/modules/netinfo/network_information.cc index a7f95a2..da587a1d 100644 --- a/third_party/blink/renderer/modules/netinfo/network_information.cc +++ b/third_party/blink/renderer/modules/netinfo/network_information.cc
@@ -316,9 +316,9 @@ web_holdback_console_message_shown_ = true; if (!GetNetworkStateNotifier().GetWebHoldbackEffectiveType()) return; - GetExecutionContext()->AddConsoleMessage( - ConsoleMessage::Create(kOtherMessageSource, kWarningMessageLevel, - GetConsoleLogStringForWebHoldback())); + GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, + GetConsoleLogStringForWebHoldback())); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/payments/payment_handler_utils.cc b/third_party/blink/renderer/modules/payments/payment_handler_utils.cc index 215faa2..ef536d1 100644 --- a/third_party/blink/renderer/modules/payments/payment_handler_utils.cc +++ b/third_party/blink/renderer/modules/payments/payment_handler_utils.cc
@@ -52,7 +52,7 @@ DCHECK(execution_context); execution_context->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, error_message)); + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, error_message)); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/payments/payment_request.cc b/third_party/blink/renderer/modules/payments/payment_request.cc index a5f100b..b3e57a6d7 100644 --- a/third_party/blink/renderer/modules/payments/payment_request.cc +++ b/third_party/blink/renderer/modules/payments/payment_request.cc
@@ -251,7 +251,7 @@ if (item->label().IsEmpty()) { execution_context.AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kErrorMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kError, "Empty " + item_name + " label may be confusing the user")); return; } @@ -315,7 +315,7 @@ if (option->id().IsEmpty()) { execution_context.AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "Empty shipping option ID may be hard to debug")); return; } @@ -757,8 +757,8 @@ "reject the promise, but allowing continued usage on localhost and " "file:// scheme origins.", method_name); - execution_context.AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, error)); + execution_context.AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, error)); } } // namespace @@ -939,33 +939,33 @@ if (!options_->requestPayerName() && errors->hasPayer() && errors->payer()->hasName()) { - GetExecutionContext()->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, - "The payer.name passed to retry() may not be " - "shown because requestPayerName is false")); + GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, + "The payer.name passed to retry() may not be " + "shown because requestPayerName is false")); } if (!options_->requestPayerEmail() && errors->hasPayer() && errors->payer()->hasEmail()) { - GetExecutionContext()->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, - "The payer.email passed to retry() may not be " - "shown because requestPayerEmail is false")); + GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, + "The payer.email passed to retry() may not be " + "shown because requestPayerEmail is false")); } if (!options_->requestPayerPhone() && errors->hasPayer() && errors->payer()->hasPhone()) { - GetExecutionContext()->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, - "The payer.phone passed to retry() may not be " - "shown because requestPayerPhone is false")); + GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, + "The payer.phone passed to retry() may not be " + "shown because requestPayerPhone is false")); } if (!options_->requestShipping() && errors->hasShippingAddress()) { - GetExecutionContext()->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, - "The shippingAddress passed to retry() may not " - "be shown because requestShipping is false")); + GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, + "The shippingAddress passed to retry() may not " + "be shown because requestShipping is false")); } complete_timer_.Stop(); @@ -1189,7 +1189,7 @@ DispatchEvent(*event); if (!event->is_waiting_for_update()) { GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "No updateWith() call in 'shippingaddresschange' event handler. User " "may see outdated line items and total.")); payment_provider_->NoUpdatedPaymentDetails(); @@ -1208,7 +1208,7 @@ DispatchEvent(*event); if (!event->is_waiting_for_update()) { GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, "No updateWith() call in 'shippingoptionchange' event handler. User " "may see outdated line items and total.")); payment_provider_->NoUpdatedPaymentDetails(); @@ -1468,15 +1468,15 @@ } void PaymentRequest::WarnNoFavicon() { - GetExecutionContext()->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, - "Favicon not found for PaymentRequest UI. User " - "may not recognize the website.")); + GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, + "Favicon not found for PaymentRequest UI. User " + "may not recognize the website.")); } void PaymentRequest::OnCompleteTimeout(TimerBase*) { GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kErrorMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kError, "Timed out waiting for a PaymentResponse.complete() call.")); payment_provider_->Complete(payments::mojom::blink::PaymentComplete(kFail)); ClearResolversAndCloseMojoConnection();
diff --git a/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.cc b/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.cc index cfdcd13..9837c74 100644 --- a/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.cc +++ b/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.cc
@@ -56,11 +56,11 @@ // Check payment response validity. if (!response->hasMethodName() || !response->hasDetails()) { - GetExecutionContext()->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kErrorMessageLevel, - "'PaymentHandlerResponse.methodName' and " - "'PaymentHandlerResponse.details' must not " - "be empty in payment response.")); + GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kError, + "'PaymentHandlerResponse.methodName' and " + "'PaymentHandlerResponse.details' must not " + "be empty in payment response.")); OnResponseRejected(mojom::ServiceWorkerResponseError::kUnknown); return; } @@ -73,7 +73,7 @@ response->details().V8Value().As<v8::Object>()) .ToLocal(&details_value)) { GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kErrorMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kError, "Failed to stringify PaymentHandlerResponse.details in payment " "response.")); OnResponseRejected(mojom::ServiceWorkerResponseError::kUnknown);
diff --git a/third_party/blink/renderer/modules/sensor/sensor.cc b/third_party/blink/renderer/modules/sensor/sensor.cc index 74a088e..8d017828 100644 --- a/third_party/blink/renderer/modules/sensor/sensor.cc +++ b/third_party/blink/renderer/modules/sensor/sensor.cc
@@ -65,7 +65,8 @@ "Maximum allowed frequency value for this sensor type is %.0f Hz.", max_allowed_frequency); ConsoleMessage* console_message = ConsoleMessage::Create( - kJSMessageSource, kInfoMessageLevel, std::move(message)); + kJSMessageSource, mojom::ConsoleMessageLevel::kInfo, + std::move(message)); execution_context->AddConsoleMessage(console_message); } }
diff --git a/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.cc b/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.cc index 296d243..70d1b3f 100644 --- a/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.cc +++ b/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.cc
@@ -79,7 +79,8 @@ Document* document = provider_->GetSupplementable(); if (document) { ConsoleMessage* console_message = ConsoleMessage::Create( - kJSMessageSource, kInfoMessageLevel, kInspectorConsoleMessage); + kJSMessageSource, mojom::ConsoleMessageLevel::kInfo, + kInspectorConsoleMessage); document->AddConsoleMessage(console_message); } provider_->set_inspector_mode(true);
diff --git a/third_party/blink/renderer/modules/service_worker/fetch_event.cc b/third_party/blink/renderer/modules/service_worker/fetch_event.cc index 6d5484ff..93034c5 100644 --- a/third_party/blink/renderer/modules/service_worker/fetch_event.cc +++ b/third_party/blink/renderer/modules/service_worker/fetch_event.cc
@@ -202,7 +202,7 @@ scoped_refptr<ResourceTimingInfo> info = ResourceTimingInfo::Create("navigation", request_time); info->SetNegativeAllowed(true); - info->SetLoadFinishTime(completion_time); + info->SetLoadResponseEnd(completion_time); info->SetInitialURL(request_->url()); info->SetFinalResponse(resource_response); info->AddFinalTransferSize(encoded_data_length);
diff --git a/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc b/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc index ce7d687..d8ea0a16 100644 --- a/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc +++ b/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc
@@ -216,9 +216,9 @@ void FetchRespondWithObserver::OnResponseRejected( ServiceWorkerResponseError error) { DCHECK(GetExecutionContext()); - GetExecutionContext()->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, - GetMessageForResponseError(error, request_url_))); + GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, + GetMessageForResponseError(error, request_url_))); // The default value of WebServiceWorkerResponse's status is 0, which maps // to a network error.
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc index e09cb9b..f7e2c95 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
@@ -291,8 +291,8 @@ "Event handler of '%s' event must be added on the initial evaluation " "of worker script.", event_type.Utf8().data()); - AddConsoleMessage(ConsoleMessage::Create(kJSMessageSource, - kWarningMessageLevel, message)); + AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); } return WorkerGlobalScope::AddEventListenerInternal(event_type, listener, options);
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc index 300a4a1..69f8f1e 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
@@ -434,7 +434,7 @@ : error->unsanitized_message; if (!error_message.IsEmpty()) { WorkerGlobalScope()->AddConsoleMessage(ConsoleMessage::Create( - kWorkerMessageSource, blink::MessageLevel::kErrorMessageLevel, + kWorkerMessageSource, mojom::ConsoleMessageLevel::kError, error_message)); } // Reject the preloadResponse promise. @@ -614,32 +614,12 @@ void ServiceWorkerGlobalScopeProxy::ReportConsoleMessage( MessageSource source, - MessageLevel level, + mojom::ConsoleMessageLevel level, const String& message, SourceLocation* location) { DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); - - // TODO(https://crbug.com/937184): This back-and-forth conversion will be - // unnecessary once we converge on blink::mojom::ConsoleMessageLevel. - blink::mojom::ConsoleMessageLevel console_message_level = - blink::mojom::ConsoleMessageLevel::kInfo; - switch (level) { - case kVerboseMessageLevel: - console_message_level = blink::mojom::ConsoleMessageLevel::kVerbose; - break; - case kInfoMessageLevel: - console_message_level = blink::mojom::ConsoleMessageLevel::kInfo; - break; - case kWarningMessageLevel: - console_message_level = blink::mojom::ConsoleMessageLevel::kWarning; - break; - case kErrorMessageLevel: - console_message_level = blink::mojom::ConsoleMessageLevel::kError; - break; - } - - Client().ReportConsoleMessage(source, console_message_level, message, - location->LineNumber(), location->Url()); + Client().ReportConsoleMessage(source, level, message, location->LineNumber(), + location->Url()); } void ServiceWorkerGlobalScopeProxy::WillInitializeWorkerContext() {
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h index d258eb4..f841f00 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h +++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h
@@ -152,7 +152,7 @@ std::unique_ptr<SourceLocation>, int exception_id) override; void ReportConsoleMessage(MessageSource, - MessageLevel, + mojom::ConsoleMessageLevel, const String& message, SourceLocation*) override; void WillInitializeWorkerContext() override;
diff --git a/third_party/blink/renderer/modules/vr/navigator_vr.cc b/third_party/blink/renderer/modules/vr/navigator_vr.cc index fda8db78..489678d 100644 --- a/third_party/blink/renderer/modules/vr/navigator_vr.cc +++ b/third_party/blink/renderer/modules/vr/navigator_vr.cc
@@ -85,7 +85,7 @@ if (controller_) { if (frame->GetDocument()) { frame->GetDocument()->AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kErrorMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kError, "Cannot use navigator.xr if the legacy VR API is already in use.")); } return nullptr;
diff --git a/third_party/blink/renderer/modules/vr/vr_display.cc b/third_party/blink/renderer/modules/vr/vr_display.cc index a391d79..1bbfb4a 100644 --- a/third_party/blink/renderer/modules/vr/vr_display.cc +++ b/third_party/blink/renderer/modules/vr/vr_display.cc
@@ -221,10 +221,10 @@ if (!in_animation_frame_) { Document* doc = navigator_vr_->GetDocument(); if (doc) { - doc->AddConsoleMessage( - ConsoleMessage::Create(kRenderingMessageSource, kWarningMessageLevel, - "getFrameData must be called within a " - "VRDisplay.requestAnimationFrame callback.")); + doc->AddConsoleMessage(ConsoleMessage::Create( + kRenderingMessageSource, mojom::ConsoleMessageLevel::kWarning, + "getFrameData must be called within a " + "VRDisplay.requestAnimationFrame callback.")); } return false; } @@ -773,16 +773,16 @@ if (!is_presenting_) { doc->AddConsoleMessage(ConsoleMessage::Create( - kRenderingMessageSource, kWarningMessageLevel, + kRenderingMessageSource, mojom::ConsoleMessageLevel::kWarning, "submitFrame has no effect when the VRDisplay is not presenting.")); return; } if (!in_animation_frame_) { - doc->AddConsoleMessage( - ConsoleMessage::Create(kRenderingMessageSource, kWarningMessageLevel, - "submitFrame must be called within a " - "VRDisplay.requestAnimationFrame callback.")); + doc->AddConsoleMessage(ConsoleMessage::Create( + kRenderingMessageSource, mojom::ConsoleMessageLevel::kWarning, + "submitFrame must be called within a " + "VRDisplay.requestAnimationFrame callback.")); return; }
diff --git a/third_party/blink/renderer/modules/webaudio/audio_context.cc b/third_party/blink/renderer/modules/webaudio/audio_context.cc index 75c3b2ab..53c7875 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_context.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_context.cc
@@ -440,13 +440,13 @@ DCHECK(document->GetFrame() && document->GetFrame()->IsCrossOriginSubframe()); document->AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kWarningMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, "The AudioContext was not allowed to start. It must be resumed (or " "created) from a user gesture event handler. https://goo.gl/7K7WLu")); break; case AutoplayPolicy::Type::kDocumentUserActivationRequired: document->AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kWarningMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, "The AudioContext was not allowed to start. It must be resumed (or " "created) after a user gesture on the page. https://goo.gl/7K7WLu")); break;
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param.cc b/third_party/blink/renderer/modules/webaudio/audio_param.cc index c70ddc2..42e36775 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_param.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_param.cc
@@ -375,7 +375,7 @@ void AudioParam::WarnIfOutsideRange(const String& param_method, float value) { if (value < minValue() || value > maxValue()) { Context()->GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, Handler().GetParamName() + "." + param_method + " " + String::Number(value) + " outside nominal range [" + String::Number(minValue()) + ", " + String::Number(maxValue()) +
diff --git a/third_party/blink/renderer/modules/webaudio/base_audio_context.cc b/third_party/blink/renderer/modules/webaudio/base_audio_context.cc index 05393cf..f0c03ece 100644 --- a/third_party/blink/renderer/modules/webaudio/base_audio_context.cc +++ b/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
@@ -211,17 +211,17 @@ DCHECK(handler); if (IsContextClosed() && GetDocument()) { - GetDocument()->AddConsoleMessage( - ConsoleMessage::Create(kOtherMessageSource, kWarningMessageLevel, - "Construction of " + handler->NodeTypeName() + - " is not useful when context is closed.")); + GetDocument()->AddConsoleMessage(ConsoleMessage::Create( + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, + "Construction of " + handler->NodeTypeName() + + " is not useful when context is closed.")); } } void BaseAudioContext::WarnForConnectionIfContextClosed() const { if (IsContextClosed() && GetDocument()) { GetDocument()->AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kWarningMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, "Connecting nodes after the context has been closed is not useful.")); } }
diff --git a/third_party/blink/renderer/modules/webaudio/iir_filter_node.cc b/third_party/blink/renderer/modules/webaudio/iir_filter_node.cc index 93a7970..6a9a8dd 100644 --- a/third_party/blink/renderer/modules/webaudio/iir_filter_node.cc +++ b/third_party/blink/renderer/modules/webaudio/iir_filter_node.cc
@@ -166,7 +166,8 @@ message.Append(']'); context.GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, message.ToString())); + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, + message.ToString())); } return MakeGarbageCollected<IIRFilterNode>(context, feedforward_coef,
diff --git a/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.cc b/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.cc index 6970b57..8438502 100644 --- a/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.cc +++ b/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.cc
@@ -142,11 +142,11 @@ void MediaElementAudioSourceHandler::PrintCorsMessage(const String& message) { if (Context()->GetExecutionContext()) { - Context()->GetExecutionContext()->AddConsoleMessage( - ConsoleMessage::Create(kSecurityMessageSource, kInfoMessageLevel, - "MediaElementAudioSource outputs zeroes due to " - "CORS access restrictions for " + - message)); + Context()->GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( + kSecurityMessageSource, mojom::ConsoleMessageLevel::kInfo, + "MediaElementAudioSource outputs zeroes due to " + "CORS access restrictions for " + + message)); } }
diff --git a/third_party/blink/renderer/modules/webdatabase/database.cc b/third_party/blink/renderer/modules/webdatabase/database.cc index bd70c42f..b5a1235 100644 --- a/third_party/blink/renderer/modules/webdatabase/database.cc +++ b/third_party/blink/renderer/modules/webdatabase/database.cc
@@ -764,7 +764,7 @@ void Database::LogErrorMessage(const String& message) { GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( - kStorageMessageSource, kErrorMessageLevel, message)); + kStorageMessageSource, mojom::ConsoleMessageLevel::kError, message)); } ExecutionContext* Database::GetExecutionContext() const {
diff --git a/third_party/blink/renderer/modules/webdatabase/database_manager.cc b/third_party/blink/renderer/modules/webdatabase/database_manager.cc index eafeea1..9dda0be 100644 --- a/third_party/blink/renderer/modules/webdatabase/database_manager.cc +++ b/third_party/blink/renderer/modules/webdatabase/database_manager.cc
@@ -200,7 +200,7 @@ void DatabaseManager::LogErrorMessage(ExecutionContext* context, const String& message) { context->AddConsoleMessage(ConsoleMessage::Create( - kStorageMessageSource, kErrorMessageLevel, message)); + kStorageMessageSource, mojom::ConsoleMessageLevel::kError, message)); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc index 3d63dd3..780aab9 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -7384,7 +7384,7 @@ if (!canvas()) return; canvas()->GetDocument().AddConsoleMessage(ConsoleMessage::Create( - kRenderingMessageSource, kWarningMessageLevel, message)); + kRenderingMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); } bool WebGLRenderingContextBase::ValidateFramebufferFuncParameters(
diff --git a/third_party/blink/renderer/modules/websockets/dom_websocket.cc b/third_party/blink/renderer/modules/websockets/dom_websocket.cc index c0f9402..89e5629d 100644 --- a/third_party/blink/renderer/modules/websockets/dom_websocket.cc +++ b/third_party/blink/renderer/modules/websockets/dom_websocket.cc
@@ -254,8 +254,8 @@ void DOMWebSocket::LogError(const String& message) { if (GetExecutionContext()) { - GetExecutionContext()->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kErrorMessageLevel, message)); + GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kError, message)); } } @@ -613,7 +613,7 @@ if (state_ == kConnecting) { state_ = kClosing; channel_->Fail("WebSocket is closed before the connection is established.", - kWarningMessageLevel, + mojom::ConsoleMessageLevel::kWarning, SourceLocation::Create(String(), 0, 0, nullptr)); return; }
diff --git a/third_party/blink/renderer/modules/websockets/dom_websocket_test.cc b/third_party/blink/renderer/modules/websockets/dom_websocket_test.cc index 430aadc..1771832 100644 --- a/third_party/blink/renderer/modules/websockets/dom_websocket_test.cc +++ b/third_party/blink/renderer/modules/websockets/dom_websocket_test.cc
@@ -66,9 +66,12 @@ } MOCK_CONST_METHOD0(BufferedAmount, unsigned()); MOCK_METHOD2(Close, void(int, const String&)); - MOCK_METHOD3(FailMock, void(const String&, MessageLevel, SourceLocation*)); + MOCK_METHOD3(FailMock, + void(const String&, + mojom::ConsoleMessageLevel, + SourceLocation*)); void Fail(const String& reason, - MessageLevel level, + mojom::ConsoleMessageLevel level, std::unique_ptr<SourceLocation> location) override { FailMock(reason, level, location.get()); } @@ -485,7 +488,7 @@ websocket_scope.Channel(), FailMock( String("WebSocket is closed before the connection is established."), - kWarningMessageLevel, _)); + mojom::ConsoleMessageLevel::kWarning, _)); } websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(), scope.GetExceptionState());
diff --git a/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.cc b/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.cc index 8f832b8..4eb1db5 100644 --- a/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.cc +++ b/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.cc
@@ -122,7 +122,7 @@ } void WebPepperSocketImpl::Fail(const WebString& reason) { - private_->Fail(reason, kErrorMessageLevel, + private_->Fail(reason, mojom::ConsoleMessageLevel::kError, SourceLocation::Create(String(), 0, 0, nullptr)); }
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel.h b/third_party/blink/renderer/modules/websockets/websocket_channel.h index aa300aa4..31c006a7 100644 --- a/third_party/blink/renderer/modules/websockets/websocket_channel.h +++ b/third_party/blink/renderer/modules/websockets/websocket_channel.h
@@ -33,8 +33,8 @@ #include <memory> #include "base/macros.h" +#include "third_party/blink/public/mojom/devtools/console_message.mojom-shared.h" #include "third_party/blink/renderer/bindings/core/v8/source_location.h" -#include "third_party/blink/renderer/core/inspector/console_types.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/wtf/forward.h" @@ -82,15 +82,14 @@ virtual void Close(int code, const String& reason) = 0; // Log the reason text and close the connection. Will call DidClose(). - // The MessageLevel parameter will be used for the level of the message - // shown at the devtools console. - // SourceLocation parameter may be shown with the reason text - // at the devtools console. Even if location is specified, it may be ignored - // and the "current" location in the sense of JavaScript execution - // may be shown if this method is called in a JS execution context. - // Location should not be null. + // The mojom::ConsoleMessageLevel parameter will be used for the level + // of the message shown at the devtools console. SourceLocation parameter may + // be shown with the reason text at the devtools console. Even if location is + // specified, it may be ignored and the "current" location in the sense of + // JavaScript execution may be shown if this method is called in a JS + // execution context. Location should not be null. virtual void Fail(const String& reason, - MessageLevel, + mojom::ConsoleMessageLevel, std::unique_ptr<SourceLocation>) = 0; // Do not call any methods after calling this method.
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc index 2469f220..fc2b705e 100644 --- a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc +++ b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc
@@ -228,7 +228,7 @@ "Connecting to a non-secure WebSocket server from a secure origin is " "deprecated."; execution_context_->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kWarningMessageLevel, message)); + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, message)); } url_ = url; @@ -362,7 +362,7 @@ } void WebSocketChannelImpl::Fail(const String& reason, - MessageLevel level, + mojom::ConsoleMessageLevel level, std::unique_ptr<SourceLocation> location) { NETWORK_DVLOG(1) << this << " Fail(" << reason << ")"; probe::DidReceiveWebSocketMessageError(execution_context_, identifier_,
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h index dd367d46..402fa3a0 100644 --- a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h +++ b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h
@@ -106,7 +106,7 @@ // argument to omit payload. void Close(int code, const String& reason) override; void Fail(const String& reason, - MessageLevel, + mojom::ConsoleMessageLevel, std::unique_ptr<SourceLocation>) override; void Disconnect() override; @@ -141,7 +141,8 @@ void FlowControlIfNecessary(); void InitialFlowControl(); void FailAsError(const String& reason) { - Fail(reason, kErrorMessageLevel, location_at_construction_->Clone()); + Fail(reason, mojom::ConsoleMessageLevel::kError, + location_at_construction_->Clone()); } void AbortAsyncOperations(); void HandleDidClose(bool was_clean, uint16_t code, const String& reason);
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc b/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc index eafd07f0..75362aa8 100644 --- a/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc +++ b/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc
@@ -799,7 +799,8 @@ WebSocketChannel::kCloseEventCodeAbnormalClosure, String())); } - Channel()->Fail("fail message from WebSocket", kErrorMessageLevel, + Channel()->Fail("fail message from WebSocket", + mojom::ConsoleMessageLevel::kError, SourceLocation::Create(String(), 0, 0, nullptr)); } @@ -876,7 +877,8 @@ EXPECT_CALL(checkpoint, Call(1)); } Channel()->Connect(url(), ""); - Channel()->Fail("close during handshake", kWarningMessageLevel, + Channel()->Fail("close during handshake", + mojom::ConsoleMessageLevel::kWarning, SourceLocation::Create(String(), 0, 0, nullptr)); checkpoint.Call(1); } @@ -896,7 +898,8 @@ } Channel()->Connect(url(), ""); HandleClient()->DidConnect(Handle(), String("a"), String("b")); - Channel()->Fail("close during handshake", kWarningMessageLevel, + Channel()->Fail("close during handshake", + mojom::ConsoleMessageLevel::kWarning, SourceLocation::Create(String(), 0, 0, nullptr)); checkpoint.Call(1); }
diff --git a/third_party/blink/renderer/modules/webusb/usb_device.cc b/third_party/blink/renderer/modules/webusb/usb_device.cc index 091e727..c8aad9d 100644 --- a/third_party/blink/renderer/modules/webusb/usb_device.cc +++ b/third_party/blink/renderer/modules/webusb/usb_device.cc
@@ -239,11 +239,11 @@ } else if (claimed_interfaces_.Get(interface_index)) { resolver->Resolve(); } else if (IsProtectedInterfaceClass(interface_index)) { - GetExecutionContext()->AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, - "An attempt to claim a USB device interface " - "has been blocked because it " - "implements a protected interface class.")); + GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, mojom::ConsoleMessageLevel::kWarning, + "An attempt to claim a USB device interface " + "has been blocked because it " + "implements a protected interface class.")); resolver->Reject(DOMException::Create( DOMExceptionCode::kSecurityError, "The requested interface implements a protected class."));
diff --git a/third_party/blink/renderer/modules/xr/xr.cc b/third_party/blink/renderer/modules/xr/xr.cc index 39b7e9e..ef7a4f44 100644 --- a/third_party/blink/renderer/modules/xr/xr.cc +++ b/third_party/blink/renderer/modules/xr/xr.cc
@@ -239,7 +239,7 @@ } doc->AddConsoleMessage(ConsoleMessage::Create( - kOtherMessageSource, kWarningMessageLevel, + kOtherMessageSource, mojom::ConsoleMessageLevel::kWarning, "Inline AR is deprecated and will be removed soon.")); }
diff --git a/third_party/blink/renderer/platform/heap/persistent_node.h b/third_party/blink/renderer/platform/heap/persistent_node.h index 31c31cd6f..51df614 100644 --- a/third_party/blink/renderer/platform/heap/persistent_node.h +++ b/third_party/blink/renderer/platform/heap/persistent_node.h
@@ -219,7 +219,7 @@ }; // Protected by ProcessHeap::CrossThreadPersistentMutex. -class CrossThreadPersistentRegion final { +class PLATFORM_EXPORT CrossThreadPersistentRegion final { USING_FAST_MALLOC(CrossThreadPersistentRegion); public:
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource.cc b/third_party/blink/renderer/platform/loader/fetch/resource.cc index 1f33f1bb..b28da80 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource.cc
@@ -338,10 +338,10 @@ } } -void Resource::Finish(TimeTicks load_finish_time, +void Resource::Finish(TimeTicks load_response_end, base::SingleThreadTaskRunner* task_runner) { DCHECK(!is_revalidating_); - load_finish_time_ = load_finish_time; + load_response_end_ = load_response_end; if (!ErrorOccurred()) status_ = ResourceStatus::kCached; loader_ = nullptr;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource.h b/third_party/blink/renderer/platform/loader/fetch/resource.h index 4fd6b2d1..3a641467 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource.h
@@ -347,7 +347,7 @@ virtual void DidDownloadData(unsigned long long) {} virtual void DidDownloadToBlob(scoped_refptr<BlobDataHandle>) {} - TimeTicks LoadFinishTime() const { return load_finish_time_; } + TimeTicks LoadResponseEnd() const { return load_response_end_; } void SetEncodedDataLength(int64_t value) { response_.SetEncodedDataLength(value); @@ -531,7 +531,7 @@ base::Optional<ResourceError> error_; - TimeTicks load_finish_time_; + TimeTicks load_response_end_; unsigned long identifier_;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc index 8275a42..c4e42d31 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -574,7 +574,7 @@ ResourceResponse final_response = resource->GetResponse(); final_response.SetResourceLoadTiming(nullptr); info->SetFinalResponse(final_response); - info->SetLoadFinishTime(info->InitialTime()); + info->SetLoadResponseEnd(info->InitialTime()); scheduled_resource_timing_reports_.push_back(std::move(info)); if (!resource_timing_report_timer_.IsActive()) resource_timing_report_timer_.StartOneShot(TimeDelta(), FROM_HERE); @@ -1711,7 +1711,7 @@ void ResourceFetcher::HandleLoaderFinish( Resource* resource, - TimeTicks finish_time, + TimeTicks response_end, LoaderFinishType type, uint32_t inflight_keepalive_bytes, bool should_report_corb_blocking, @@ -1747,7 +1747,7 @@ : resource->GetResourceRequest() .GetInitialUrlForResourceTiming()); info->SetFinalResponse(resource->GetResponse()); - info->SetLoadFinishTime(finish_time); + info->SetLoadResponseEnd(response_end); // encodedDataLength == -1 means "not available". // TODO(ricea): Find cases where it is not available but the // PerformanceResourceTiming spec requires it to be available and fix @@ -1768,7 +1768,7 @@ ResourceTimingInfo::Create(info->InitiatorType(), timing_info.start_time); preflight_info->SetInitialURL(info->InitialURL()); - preflight_info->SetLoadFinishTime(timing_info.finish_time); + preflight_info->SetLoadResponseEnd(timing_info.response_end); preflight_info->AddFinalTransferSize(timing_info.transfer_size); // Set a provisional response to provide possible other information. @@ -1788,7 +1788,7 @@ resource->VirtualTimePauser().UnpauseVirtualTime(); if (type == kDidFinishLoading) { - resource->Finish(finish_time, task_runner_.get()); + resource->Finish(response_end, task_runner_.get()); // Since this resource came from the network stack we only schedule a stale // while revalidate request if the network asked us to. If we called @@ -1818,7 +1818,7 @@ } } Context().DispatchDidFinishLoading( - resource->Identifier(), finish_time, encoded_data_length, + resource->Identifier(), response_end, encoded_data_length, resource->GetResponse().DecodedBodyLength(), should_report_corb_blocking, FetchContext::ResourceResponseType::kNotFromMemoryCache); resource->ReloadIfLoFiOrPlaceholderImage(this, Resource::kReloadIfNeeded);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc index 0674429a..0d97155 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc
@@ -16,6 +16,7 @@ #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/scheduler/public/aggregated_metric_reporter.h" #include "third_party/blink/renderer/platform/scheduler/public/frame_status.h" +#include "third_party/blink/renderer/platform/wtf/time.h" namespace blink { @@ -421,7 +422,7 @@ DCHECK(ThrottleOption::kStoppable == option || ThrottleOption::kThrottleable == option); if (pending_requests_[option].empty()) - pending_queue_update_times_[option] = base::TimeTicks::Now(); + pending_queue_update_times_[option] = CurrentTime(); pending_requests_[option].insert(request_info); pending_request_map_.insert( *id, MakeGarbageCollected<ClientInfo>(client, option, priority, @@ -656,14 +657,12 @@ if (use_stoppable) { *id = stoppable_it->client_id; stoppable_queue.erase(stoppable_it); - pending_queue_update_times_[ThrottleOption::kStoppable] = - base::TimeTicks::Now(); + pending_queue_update_times_[ThrottleOption::kStoppable] = CurrentTime(); return true; } *id = throttleable_it->client_id; throttleable_queue.erase(throttleable_it); - pending_queue_update_times_[ThrottleOption::kThrottleable] = - base::TimeTicks::Now(); + pending_queue_update_times_[ThrottleOption::kThrottleable] = CurrentTime(); return true; } @@ -727,8 +726,7 @@ if (is_console_info_shown_ || pending_request_map_.IsEmpty()) return; - const base::TimeTicks limit = - base::TimeTicks::Now() - base::TimeDelta::FromMinutes(1); + const double limit = CurrentTime() - 60; // In seconds ThrottleOption target_option; if (pending_queue_update_times_[ThrottleOption::kThrottleable] < limit && !IsPendingRequestEffectivelyEmpty(ThrottleOption::kThrottleable)) {
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h index ed4e985..050ef933 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h
@@ -331,8 +331,9 @@ std::set<ClientIdWithPriority, ClientIdWithPriority::Compare>> pending_requests_; - // Remembers times when the top request in each queue is processed. - std::map<ThrottleOption, base::TimeTicks> pending_queue_update_times_; + // Remembers elapsed times in seconds when the top request in each queue is + // processed. + std::map<ThrottleOption, double> pending_queue_update_times_; // Holds an internal class instance to monitor and report traffic. std::unique_ptr<TrafficMonitor> traffic_monitor_;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc index 8db7407..88e7858 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc
@@ -12,6 +12,7 @@ #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/scheduler/test/fake_frame_scheduler.h" #include "third_party/blink/renderer/platform/testing/testing_platform_support.h" +#include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink { @@ -44,14 +45,17 @@ void SetDelegate(MockClientDelegate* delegate) { delegate_ = delegate; } void Run() override { - if (delegate_) { + if (delegate_) delegate_->NotifyRun(this); - } EXPECT_FALSE(was_run_); was_run_ = true; } - ConsoleLogger* GetConsoleLogger() override { return console_logger_; } bool WasRun() { return was_run_; } + ConsoleLogger* GetConsoleLogger() override { + was_console_logger_obtained_ = true; + return console_logger_; + } + bool WasConsoleLoggerObtained() { return was_console_logger_obtained_; } void Trace(blink::Visitor* visitor) override { ResourceLoadSchedulerClient::Trace(visitor); @@ -63,6 +67,7 @@ MakeGarbageCollected<NullConsoleLogger>(); MockClientDelegate* delegate_; bool was_run_ = false; + bool was_console_logger_obtained_ = false; }; class ResourceLoadSchedulerTest : public testing::Test { @@ -619,5 +624,51 @@ EXPECT_TRUE(Release(id1)); } +TEST_F(ResourceLoadSchedulerTest, ConsoleMessage) { + WTF::ScopedMockClock mock_clock; + Scheduler()->SetOutstandingLimitForTesting(0, 0); + Scheduler()->OnLifecycleStateChanged( + scheduler::SchedulingLifecycleState::kThrottled); + + // Push two requests into the queue. + MockClient* client1 = MakeGarbageCollected<MockClient>(); + ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId; + Scheduler()->Request(client1, ThrottleOption::kThrottleable, + ResourceLoadPriority::kLowest, 0 /* intra_priority */, + &id1); + EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1); + EXPECT_FALSE(client1->WasRun()); + + MockClient* client2 = MakeGarbageCollected<MockClient>(); + ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId; + Scheduler()->Request(client2, ThrottleOption::kThrottleable, + ResourceLoadPriority::kLowest, 0 /* intra_priority */, + &id2); + EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2); + EXPECT_FALSE(client2->WasRun()); + + // Cancel the first request + EXPECT_TRUE(Release(id1)); + + // Advance current time a little and triggers an life cycle event, but it + // still won't awake the warning logic. + mock_clock.Advance(WTF::TimeDelta::FromSeconds(50)); + Scheduler()->OnLifecycleStateChanged( + scheduler::SchedulingLifecycleState::kNotThrottled); + EXPECT_FALSE(client1->WasConsoleLoggerObtained()); + EXPECT_FALSE(client2->WasConsoleLoggerObtained()); + Scheduler()->OnLifecycleStateChanged( + scheduler::SchedulingLifecycleState::kThrottled); + + // Modify current time to awake the console warning logic, and the second + // client should be used for console logging. + mock_clock.Advance(WTF::TimeDelta::FromSeconds(15)); + Scheduler()->OnLifecycleStateChanged( + scheduler::SchedulingLifecycleState::kNotThrottled); + EXPECT_FALSE(client1->WasConsoleLoggerObtained()); + EXPECT_TRUE(client2->WasConsoleLoggerObtained()); + EXPECT_TRUE(Release(id2)); +} + } // namespace } // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc index d015a32..5de5fbf6 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -499,7 +499,7 @@ const ResourceResponse& response = resource_->GetResponse(); if (deferred_finish_loading_info_) { - DidFinishLoading(deferred_finish_loading_info_->finish_time, + DidFinishLoading(deferred_finish_loading_info_->response_end, response.EncodedDataLength(), response.EncodedBodyLength(), response.DecodedBodyLength(), deferred_finish_loading_info_->should_report_corb_blocking, @@ -1114,7 +1114,7 @@ } void ResourceLoader::DidFinishLoading( - TimeTicks finish_time, + TimeTicks response_end, int64_t encoded_data_length, int64_t encoded_body_length, int64_t decoded_body_length, @@ -1131,7 +1131,7 @@ if ((response_body_loader_ && !has_seen_end_of_body_) || (is_downloading_to_blob_ && !blob_finished_ && blob_response_started_)) { deferred_finish_loading_info_ = DeferredFinishLoadingInfo{ - finish_time, should_report_corb_blocking, cors_preflight_timing_info}; + response_end, should_report_corb_blocking, cors_preflight_timing_info}; return; } @@ -1151,7 +1151,7 @@ "endData", EndResourceLoadData(RequestOutcome::kSuccess)); fetcher_->HandleLoaderFinish( - resource_.Get(), finish_time, ResourceFetcher::kDidFinishLoading, + resource_.Get(), response_end, ResourceFetcher::kDidFinishLoading, inflight_keepalive_bytes_, should_report_corb_blocking, cors_preflight_timing_info); } @@ -1383,7 +1383,7 @@ blob_finished_ = true; if (deferred_finish_loading_info_) { const ResourceResponse& response = resource_->GetResponse(); - DidFinishLoading(deferred_finish_loading_info_->finish_time, + DidFinishLoading(deferred_finish_loading_info_->response_end, response.EncodedDataLength(), response.EncodedBodyLength(), response.DecodedBodyLength(), deferred_finish_loading_info_->should_report_corb_blocking,
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.h b/third_party/blink/renderer/platform/loader/fetch/resource_loader.h index 498766f0..3b83852f2 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
@@ -135,7 +135,7 @@ void DidStartLoadingResponseBody( mojo::ScopedDataPipeConsumerHandle body) override; void DidFinishLoading( - TimeTicks finish_time, + TimeTicks response_end, int64_t encoded_data_length, int64_t encoded_body_length, int64_t decoded_body_length, @@ -244,7 +244,7 @@ // struct is used to store the information needed to refire DidFinishLoading // when the blob is finished too. struct DeferredFinishLoadingInfo { - TimeTicks finish_time; + TimeTicks response_end; bool should_report_corb_blocking; std::vector<network::cors::PreflightTimingInfo> cors_preflight_timing_info; };
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h b/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h index 59a7c71..7094d25 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h
@@ -56,8 +56,8 @@ const AtomicString& InitiatorType() const { return type_; } - void SetLoadFinishTime(TimeTicks time) { load_finish_time_ = time; } - TimeTicks LoadFinishTime() const { return load_finish_time_; } + void SetLoadResponseEnd(TimeTicks time) { load_response_end_ = time; } + TimeTicks LoadResponseEnd() const { return load_response_end_; } void SetInitialURL(const KURL& url) { initial_url_ = url; } const KURL& InitialURL() const { return initial_url_; } @@ -95,7 +95,7 @@ AtomicString type_; TimeTicks initial_time_; - TimeTicks load_finish_time_; + TimeTicks load_response_end_; KURL initial_url_; ResourceResponse final_response_; Vector<ResourceResponse> redirect_chain_;
diff --git a/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc b/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc index 9a63f9b..ab2f54a1 100644 --- a/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc +++ b/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc
@@ -21,11 +21,11 @@ GetMemoryCache()->Remove(stale_resource_); ClearResource(); - TimeTicks finish_time = resource->LoadFinishTime(); - if (!finish_time.is_null()) { + TimeTicks response_end = resource->LoadResponseEnd(); + if (!response_end.is_null()) { UMA_HISTOGRAM_LONG_TIMES( "Blink.ResourceFetcher.StaleWhileRevalidateDuration", - finish_time - start_time_); + response_end - start_time_); } }
diff --git a/third_party/blink/renderer/platform/network/http_parsers.cc b/third_party/blink/renderer/platform/network/http_parsers.cc index b064ed9..6cc666a 100644 --- a/third_party/blink/renderer/platform/network/http_parsers.cc +++ b/third_party/blink/renderer/platform/network/http_parsers.cc
@@ -583,10 +583,10 @@ wtf_size_t* end) { DCHECK(IsMainThread()); - int headers_end_pos = + size_t headers_end_pos = net::HttpUtil::LocateEndOfAdditionalHeaders(bytes, size, 0); - if (headers_end_pos < 0) + if (headers_end_pos == std::string::npos) return false; *end = static_cast<wtf_size_t>(headers_end_pos); @@ -597,8 +597,8 @@ headers.append(bytes, headers_end_pos); scoped_refptr<net::HttpResponseHeaders> response_headers = - new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders( - headers.data(), static_cast<int>(headers.length()))); + new net::HttpResponseHeaders( + net::HttpUtil::AssembleRawHeaders(headers.data(), headers.length())); std::string mime_type, charset; response_headers->GetMimeTypeAndCharset(&mime_type, &charset); @@ -627,10 +627,10 @@ wtf_size_t* end) { DCHECK_EQ(0u, header_fields->size()); - int headers_end_pos = + size_t headers_end_pos = net::HttpUtil::LocateEndOfAdditionalHeaders(bytes, size, 0); - if (headers_end_pos < 0) + if (headers_end_pos == std::string::npos) return false; *end = static_cast<wtf_size_t>(headers_end_pos); @@ -641,8 +641,8 @@ headers.append(bytes, headers_end_pos); scoped_refptr<net::HttpResponseHeaders> responseHeaders = - new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders( - headers.data(), static_cast<wtf_size_t>(headers.length()))); + new net::HttpResponseHeaders( + net::HttpUtil::AssembleRawHeaders(headers.data(), headers.length())); // Copy selected header fields. const AtomicString* const headerNamePointers[] = {
diff --git a/third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h b/third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h index a070892..864fda4 100644 --- a/third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h +++ b/third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h
@@ -7,6 +7,7 @@ #include "base/cancelable_callback.h" #include "base/macros.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink { namespace scheduler { @@ -14,6 +15,8 @@ // A CancelableClosureHolder is a CancelableCallback which resets its wrapped // callback with a cached closure whenever it is canceled. class CancelableClosureHolder { + DISALLOW_NEW(); + public: CancelableClosureHolder(); ~CancelableClosureHolder();
diff --git a/third_party/blink/renderer/platform/scheduler/common/thread_load_tracker.h b/third_party/blink/renderer/platform/scheduler/common/thread_load_tracker.h index 35014aaa..258a33130 100644 --- a/third_party/blink/renderer/platform/scheduler/common/thread_load_tracker.h +++ b/third_party/blink/renderer/platform/scheduler/common/thread_load_tracker.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "base/time/time.h" #include "third_party/blink/renderer/platform/platform_export.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink { namespace scheduler { @@ -19,6 +20,8 @@ // Every |reporting_interval_| time units, it reports the average thread load // level computed using a sliding window of width |reporting_interval_|. class PLATFORM_EXPORT ThreadLoadTracker { + DISALLOW_NEW(); + public: // Callback is called with (current_time, load_level) parameters. using Callback = base::RepeatingCallback<void(base::TimeTicks, double)>;
diff --git a/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h b/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h index 807c4ae4..9f3e7c0a 100644 --- a/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h +++ b/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h
@@ -13,6 +13,7 @@ #include "base/task/sequence_manager/lazy_now.h" #include "base/time/time.h" #include "third_party/blink/renderer/platform/platform_export.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace base { namespace sequence_manager { @@ -33,6 +34,8 @@ // on a resource. This limit applies when task queues are already throttled // by TaskQueueThrottler. class PLATFORM_EXPORT BudgetPool { + USING_FAST_MALLOC(BudgetPool); + public: virtual ~BudgetPool();
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h b/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h index a59ef9a..0bbbc4e 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h
@@ -11,12 +11,15 @@ #include "base/time/time.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink { namespace scheduler { // Runs a posted task at latest by a given deadline, but possibly sooner. class PLATFORM_EXPORT DeadlineTaskRunner { + USING_FAST_MALLOC(DeadlineTaskRunner); + public: DeadlineTaskRunner(const base::RepeatingClosure& callback, scoped_refptr<base::SingleThreadTaskRunner> task_runner);
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h index 336e778e..c80ac68 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h
@@ -14,6 +14,7 @@ #include "base/memory/scoped_refptr.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h" @@ -38,6 +39,8 @@ // MainThreadTaskQueues for non-loading queues, for accessing task queues and // their related voters, and for creating new task queues. class PLATFORM_EXPORT FrameTaskQueueController { + USING_FAST_MALLOC(FrameTaskQueueController); + public: using TaskQueueAndEnabledVoterPair = std::pair<MainThreadTaskQueue*,
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h index e2c2a5cb..5fe86ec 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
@@ -45,6 +45,7 @@ #include "third_party/blink/renderer/platform/scheduler/main_thread/use_case.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/user_model.h" #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace base { namespace trace_event { @@ -455,6 +456,8 @@ }; class Policy { + DISALLOW_NEW(); + public: Policy(); ~Policy() = default; @@ -548,24 +551,6 @@ policies_; }; - class PollableNeedsUpdateFlag { - public: - explicit PollableNeedsUpdateFlag(base::Lock* write_lock); - ~PollableNeedsUpdateFlag(); - - // Set the flag. May only be called if |write_lock| is held. - void SetWhileLocked(bool value); - - // Returns true iff the flag is set to true. - bool IsSet() const; - - private: - base::subtle::Atomic32 flag_; - base::Lock* write_lock_; // Not owned. - - DISALLOW_COPY_AND_ASSIGN(PollableNeedsUpdateFlag); - }; - class TaskDurationMetricTracker; class RendererPauseHandleImpl : public ThreadScheduler::RendererPauseHandle {
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h index 630cd7b..e9e0e9a 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h
@@ -22,6 +22,7 @@ #include "third_party/blink/renderer/platform/scheduler/public/page_lifecycle_state.h" #include "third_party/blink/renderer/platform/scheduler/public/page_scheduler.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace base { namespace trace_event { @@ -155,6 +156,8 @@ }; class PageLifecycleStateTracker { + USING_FAST_MALLOC(PageLifecycleStateTracker); + public: explicit PageLifecycleStateTracker(PageSchedulerImpl*, PageLifecycleState); ~PageLifecycleStateTracker() = default;
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h b/third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h index 46bf3336..64608d7 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h
@@ -15,10 +15,14 @@ namespace scheduler { class PLATFORM_EXPORT PendingUserInput { + DISALLOW_NEW(); + public: // Handles the dispatch of WebInputEvents from the main thread scheduler, // keeping track of the set of in-flight input events. class PLATFORM_EXPORT Monitor { + DISALLOW_NEW(); + public: Monitor() { this->counters_.fill(0); } void OnEnqueue(WebInputEvent::Type);
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.h b/third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.h index 6caf61e594..8a95c20 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.h
@@ -7,6 +7,7 @@ #include "base/task/sequence_manager/task_queue.h" #include "third_party/blink/renderer/platform/platform_export.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink { namespace scheduler { @@ -15,6 +16,8 @@ class MainThreadTaskQueue; class PLATFORM_EXPORT PrioritizeCompositingAfterInputExperiment { + DISALLOW_NEW(); + public: explicit PrioritizeCompositingAfterInputExperiment( MainThreadSchedulerImpl* scheduler);
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h b/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h index d8554dd..9bc8bc589 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h
@@ -13,6 +13,7 @@ #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h" #include "third_party/blink/renderer/platform/scheduler/public/frame_status.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink { namespace scheduler { @@ -20,6 +21,8 @@ // Records the expected queueing time for a high priority task occurring // randomly during each interval of length equal to window's duration. class PLATFORM_EXPORT QueueingTimeEstimator { + DISALLOW_NEW(); + public: class PLATFORM_EXPORT Client { public: @@ -36,6 +39,8 @@ }; class RunningAverage { + DISALLOW_NEW(); + public: explicit RunningAverage(int steps_per_window); int GetStepsPerWindow() const; @@ -50,6 +55,8 @@ }; class PLATFORM_EXPORT Calculator { + DISALLOW_NEW(); + public: explicit Calculator(int steps_per_window);
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals.h b/third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals.h index 6674227..feed3ae 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals.h
@@ -10,6 +10,7 @@ #include "base/trace_event/trace_event.h" #include "base/trace_event/traced_value.h" #include "third_party/blink/renderer/platform/platform_export.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink { namespace scheduler { @@ -17,6 +18,8 @@ class WebRenderWidgetSchedulingState; class PLATFORM_EXPORT RenderWidgetSignals { + USING_FAST_MALLOC(RenderWidgetSignals); + public: class PLATFORM_EXPORT Observer { public:
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.h b/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.h index 81270ec..4f520427 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_TASK_TYPE_NAMES_H_ #include "third_party/blink/public/platform/task_type.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h" #include "third_party/blink/renderer/platform/wtf/text/string_hash.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -14,11 +15,10 @@ namespace scheduler { class TaskTypeNames { + STATIC_ONLY(TaskTypeNames); + public: static const char* TaskTypeToString(TaskType task_type); - - private: - TaskTypeNames(); }; } // namespace scheduler
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h b/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h index 32ad7b6..6f55b44 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h
@@ -11,11 +11,14 @@ #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" #include "third_party/blink/public/platform/web_input_event.h" #include "third_party/blink/renderer/platform/platform_export.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink { namespace scheduler { class PLATFORM_EXPORT UserModel { + USING_FAST_MALLOC(UserModel); + public: UserModel(); ~UserModel();
diff --git a/third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h b/third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h index 585c28f..8ccca07 100644 --- a/third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h +++ b/third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h
@@ -12,6 +12,7 @@ #include "base/sequenced_task_runner.h" #include "base/time/time.h" #include "third_party/blink/renderer/platform/platform_export.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink { @@ -19,6 +20,8 @@ // PostCancellableDelayedTask() and cancels the associated task on // TaskHandle::cancel() call or on TaskHandle destruction. class PLATFORM_EXPORT TaskHandle { + DISALLOW_NEW(); + public: class Runner;
diff --git a/third_party/blink/renderer/platform/scheduler/public/thread.h b/third_party/blink/renderer/platform/scheduler/public/thread.h index 0774757..b3ad7f0 100644 --- a/third_party/blink/renderer/platform/scheduler/public/thread.h +++ b/third_party/blink/renderer/platform/scheduler/public/thread.h
@@ -32,6 +32,7 @@ #include "base/threading/thread.h" #include "third_party/blink/public/platform/web_thread_type.h" #include "third_party/blink/renderer/platform/platform_export.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace base { class SingleThreadTaskRunner; @@ -70,6 +71,8 @@ // Deleting the thread blocks until all pending, non-delayed tasks have been // run. class PLATFORM_EXPORT Thread { + USING_FAST_MALLOC(Thread); + public: friend class Platform; // For SetMainThread() and IsSimpleMainThread(). friend class ScopedMainThreadOverrider; // For SetMainThread().
diff --git a/third_party/blink/renderer/platform/scheduler/public/thread_cpu_throttler.h b/third_party/blink/renderer/platform/scheduler/public/thread_cpu_throttler.h index 03b1105e..10b1c4b 100644 --- a/third_party/blink/renderer/platform/scheduler/public/thread_cpu_throttler.h +++ b/third_party/blink/renderer/platform/scheduler/public/thread_cpu_throttler.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "third_party/blink/renderer/platform/platform_export.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace base { template <typename T> @@ -23,6 +24,8 @@ // additional thread which frequently interrupts main thread // and sleeps. class PLATFORM_EXPORT ThreadCPUThrottler final { + USING_FAST_MALLOC(ThreadCPUThrottler); + public: static ThreadCPUThrottler* GetInstance();
diff --git a/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h b/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h index 738f21d8..63ef7485 100644 --- a/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h +++ b/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h
@@ -10,6 +10,7 @@ #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h" #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink { namespace scheduler { @@ -29,6 +30,8 @@ ~WorkerScheduler() override; class PLATFORM_EXPORT PauseHandle { + USING_FAST_MALLOC(PauseHandle); + public: PauseHandle(base::WeakPtr<WorkerScheduler>); ~PauseHandle();
diff --git a/third_party/blink/renderer/platform/scheduler/test/DEPS b/third_party/blink/renderer/platform/scheduler/test/DEPS index f97ca86..545b352 100644 --- a/third_party/blink/renderer/platform/scheduler/test/DEPS +++ b/third_party/blink/renderer/platform/scheduler/test/DEPS
@@ -1,7 +1,3 @@ -include_rules = [ - "+cc/base/lap_timer.h" -] - specific_include_rules = { "renderer_scheduler_test_support\.cc": [ "+base/task/sequence_manager/test/lazy_thread_controller_for_test.h",
diff --git a/third_party/blink/renderer/platform/scheduler/test/fake_frame_scheduler.h b/third_party/blink/renderer/platform/scheduler/test/fake_frame_scheduler.h index fb070668..70379c3 100644 --- a/third_party/blink/renderer/platform/scheduler/test/fake_frame_scheduler.h +++ b/third_party/blink/renderer/platform/scheduler/test/fake_frame_scheduler.h
@@ -11,6 +11,7 @@ #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h" #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h" #include "third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink { namespace scheduler { @@ -58,6 +59,8 @@ ~FakeFrameScheduler() override = default; class Builder { + USING_FAST_MALLOC(Builder); + public: Builder() = default;
diff --git a/third_party/blink/renderer/platform/scheduler/test/fuzzer/sequence_manager_fuzzer_processor.h b/third_party/blink/renderer/platform/scheduler/test/fuzzer/sequence_manager_fuzzer_processor.h index 627836e..a150d20f 100644 --- a/third_party/blink/renderer/platform/scheduler/test/fuzzer/sequence_manager_fuzzer_processor.h +++ b/third_party/blink/renderer/platform/scheduler/test/fuzzer/sequence_manager_fuzzer_processor.h
@@ -11,6 +11,7 @@ #include "base/time/time.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/scheduler/test/fuzzer/proto/sequence_manager_test_description.pb.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace base { namespace sequence_manager { @@ -25,6 +26,8 @@ // by the |thread_pool_manager_| should live for the scope of the main thread // entry function i.e RunTest. class PLATFORM_EXPORT SequenceManagerFuzzerProcessor { + DISALLOW_NEW(); + public: // Public interface used to parse the fuzzer's test description and // run the relevant APIs.
diff --git a/third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_manager.h b/third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_manager.h index fd53e91..3b7351a9 100644 --- a/third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_manager.h +++ b/third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_manager.h
@@ -19,12 +19,15 @@ #include "third_party/blink/renderer/platform/scheduler/test/fuzzer/proto/sequence_manager_test_description.pb.h" #include "third_party/blink/renderer/platform/scheduler/test/fuzzer/sequence_manager_fuzzer_processor.h" #include "third_party/blink/renderer/platform/scheduler/test/fuzzer/task_queue_with_voters.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace base { namespace sequence_manager { // Used by the SequenceManagerFuzzerProcessor to execute actions on a thread. class PLATFORM_EXPORT ThreadManager { + USING_FAST_MALLOC(ThreadManager); + public: // |initial_time| is the time in which |this| was instantiated. ThreadManager(TimeTicks initial_time, @@ -62,6 +65,8 @@ protected: class Task { + USING_FAST_MALLOC(Task); + public: explicit Task(ThreadManager* thread_manager); ~Task() = default;
diff --git a/third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_pool_manager.h b/third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_pool_manager.h index a802c9ac..5644fda 100644 --- a/third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_pool_manager.h +++ b/third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_pool_manager.h
@@ -14,6 +14,7 @@ #include "base/time/time.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/scheduler/test/fuzzer/proto/sequence_manager_test_description.pb.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace base { namespace sequence_manager { @@ -24,6 +25,8 @@ // Used by the SequenceManagerFuzzerProcessor to manage threads and synchronize // their clocks. class PLATFORM_EXPORT ThreadPoolManager { + USING_FAST_MALLOC(ThreadPoolManager); + public: explicit ThreadPoolManager(SequenceManagerFuzzerProcessor* processor); ~ThreadPoolManager();
diff --git a/third_party/blink/renderer/platform/scheduler/test/queueing_time_estimator_perf_test.cc b/third_party/blink/renderer/platform/scheduler/test/queueing_time_estimator_perf_test.cc index 6cd179e..59a75ee 100644 --- a/third_party/blink/renderer/platform/scheduler/test/queueing_time_estimator_perf_test.cc +++ b/third_party/blink/renderer/platform/scheduler/test/queueing_time_estimator_perf_test.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/base/lap_timer.h" +#include "base/timer/lap_timer.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/perf/perf_test.h" #include "third_party/blink/renderer/platform/scheduler/test/test_queueing_time_estimator_client.h" @@ -21,7 +21,7 @@ public: QueueingTimeEstimatorTestPerfTest() : timer_(kWarmupRuns, kTimeLimit, kCheckInterval) {} - cc::LapTimer timer_; + base::LapTimer timer_; base::TimeTicks time; TestQueueingTimeEstimatorClient client; };
diff --git a/third_party/blink/renderer/platform/testing/shape_result_perf_test.cc b/third_party/blink/renderer/platform/testing/shape_result_perf_test.cc index ce5241c..e635da9 100644 --- a/third_party/blink/renderer/platform/testing/shape_result_perf_test.cc +++ b/third_party/blink/renderer/platform/testing/shape_result_perf_test.cc
@@ -3,8 +3,7 @@ // found in the LICENSE file. #include "base/time/time.h" -#include "cc/base/lap_timer.h" - +#include "base/timer/lap_timer.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/perf/perf_test.h" @@ -58,7 +57,7 @@ {roboto, "third_party/Roboto/roboto-regular.woff2"}, }; - cc::LapTimer timer; + base::LapTimer timer; }; class OffsetForPositionPerfTest : public ShapeResultPerfTest,
diff --git a/third_party/blink/renderer/platform/testing/shaping_line_breaker_perf_test.cc b/third_party/blink/renderer/platform/testing/shaping_line_breaker_perf_test.cc index 9ce98802..c265e21 100644 --- a/third_party/blink/renderer/platform/testing/shaping_line_breaker_perf_test.cc +++ b/third_party/blink/renderer/platform/testing/shaping_line_breaker_perf_test.cc
@@ -5,8 +5,9 @@ #include "third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h" #include <unicode/uscript.h> + #include "base/time/time.h" -#include "cc/base/lap_timer.h" +#include "base/timer/lap_timer.h" #include "third_party/blink/renderer/platform/fonts/font.h" #include "third_party/blink/renderer/platform/fonts/font_cache.h" #include "third_party/blink/renderer/platform/fonts/font_test_utilities.h" @@ -77,7 +78,7 @@ unsigned start_index = 0; unsigned num_glyphs = 0; hb_script_t script = HB_SCRIPT_INVALID; - cc::LapTimer timer_; + base::LapTimer timer_; }; TEST_F(ShapingLineBreakerPerfTest, ShapeLatinText) {
diff --git a/third_party/blink/renderer/platform/wtf/math_extras.h b/third_party/blink/renderer/platform/wtf/math_extras.h index 6913d3dc..6ff8162 100644 --- a/third_party/blink/renderer/platform/wtf/math_extras.h +++ b/third_party/blink/renderer/platform/wtf/math_extras.h
@@ -145,7 +145,7 @@ return (value <= min) ? min : static_cast<LimitType>(value); } -// For any floating-point limits, or integral limits smaller than long long, we +// For any floating-point limits, or integral limits smaller than int64_t, we // can cast the limits to double without losing precision; then the only cases // where |value| can't be represented accurately as a double are the ones where // it's outside the limit range anyway. So doing all comparisons as doubles @@ -193,8 +193,8 @@ }; // The unspecialized version of this templated class handles clamping to -// anything other than [unsigned] long long int limits. It simply uses the -// class above to toggle between the "fast" and "safe" clamp implementations. +// anything other than [u]int64_t limits. It simply uses the class above +// to toggle between the "fast" and "safe" clamp implementations. template <typename LimitType, typename ValueType> class ClampToHelper { public: @@ -224,75 +224,66 @@ } }; -// Clamping to [unsigned] long long int limits requires more care. These may -// not be accurately representable as doubles, so instead we cast |value| to the -// limit type. But that cast is undefined if |value| is floating point and +// Clamping to [u]int64_t limits requires more care. These may not be +// accurately representable as doubles, so instead we cast |value| to the +// limit type. But that cast is undefined if |value| is floating point and // outside the representable range of the limit type, so we also have to check // for that case explicitly. template <typename ValueType> -class ClampToHelper<long long int, ValueType> { +class ClampToHelper<int64_t, ValueType> { STATIC_ONLY(ClampToHelper); public: - static inline long long int clampTo(ValueType value, - long long int min, - long long int max) { + static inline int64_t clampTo(ValueType value, int64_t min, int64_t max) { if (!std::numeric_limits<ValueType>::is_integer) { if (value > 0) { if (static_cast<double>(value) >= - static_cast<double>(std::numeric_limits<long long int>::max())) + static_cast<double>(std::numeric_limits<int64_t>::max())) return max; } else if (static_cast<double>(value) <= - static_cast<double>( - std::numeric_limits<long long int>::min())) { + static_cast<double>(std::numeric_limits<int64_t>::min())) { return min; } } - // Note: If |value| were unsigned long long int, it could be larger than - // the largest long long int, and this code would be wrong; we handle - // this case with a separate full specialization below. - return clampToDirectComparison(static_cast<long long int>(value), min, max); + // Note: If |value| were uint64_t it could be larger than the largest + // int64_t, and this code would be wrong; we handle this case with + // a separate full specialization below. + return clampToDirectComparison(static_cast<int64_t>(value), min, max); } }; // This specialization handles the case where the above partial specialization // would be potentially incorrect. template <> -class ClampToHelper<long long int, unsigned long long int> { +class ClampToHelper<int64_t, uint64_t> { STATIC_ONLY(ClampToHelper); public: - static inline long long int clampTo(unsigned long long int value, - long long int min, - long long int max) { - if (max <= 0 || value >= static_cast<unsigned long long int>(max)) + static inline int64_t clampTo(uint64_t value, int64_t min, int64_t max) { + if (max <= 0 || value >= static_cast<uint64_t>(max)) return max; - const long long int longLongValue = static_cast<long long int>(value); + const int64_t longLongValue = static_cast<int64_t>(value); return (longLongValue <= min) ? min : longLongValue; } }; -// This is similar to the partial specialization that clamps to long long int, -// but because the lower-bound check is done for integer value types as well, we -// don't need a <unsigned long long int, long long int> full specialization. +// This is similar to the partial specialization that clamps to int64_t, but +// because the lower-bound check is done for integer value types as well, we +// don't need a <uint64_t, int64_t> full specialization. template <typename ValueType> -class ClampToHelper<unsigned long long int, ValueType> { +class ClampToHelper<uint64_t, ValueType> { STATIC_ONLY(ClampToHelper); public: - static inline unsigned long long int clampTo(ValueType value, - unsigned long long int min, - unsigned long long int max) { + static inline uint64_t clampTo(ValueType value, uint64_t min, uint64_t max) { if (value <= 0) return min; if (!std::numeric_limits<ValueType>::is_integer) { if (static_cast<double>(value) >= - static_cast<double>( - std::numeric_limits<unsigned long long int>::max())) + static_cast<double>(std::numeric_limits<uint64_t>::max())) return max; } - return clampToDirectComparison(static_cast<unsigned long long int>(value), - min, max); + return clampToDirectComparison(static_cast<uint64_t>(value), min, max); } };
diff --git a/third_party/blink/renderer/platform/wtf/math_extras_test.cc b/third_party/blink/renderer/platform/wtf/math_extras_test.cc index e90ac43..64f2b9c 100644 --- a/third_party/blink/renderer/platform/wtf/math_extras_test.cc +++ b/third_party/blink/renderer/platform/wtf/math_extras_test.cc
@@ -71,10 +71,10 @@ } TEST(MathExtrasTest, clampToIntLongLong) { - long long max_int = std::numeric_limits<int>::max(); - long long min_int = std::numeric_limits<int>::min(); - long long overflow_int = max_int + 1; - long long underflow_int = min_int - 1; + int64_t max_int = std::numeric_limits<int>::max(); + int64_t min_int = std::numeric_limits<int>::min(); + int64_t overflow_int = max_int + 1; + int64_t underflow_int = min_int - 1; EXPECT_GT(overflow_int, max_int); EXPECT_LT(underflow_int, min_int); @@ -158,26 +158,25 @@ EXPECT_EQ(0.0, clampTo<double>(0)); EXPECT_EQ(0.0, clampTo<double>(0.0f)); EXPECT_EQ(0.0, clampTo<double>(0ULL)); - EXPECT_EQ(3.5, clampTo<double>(std::numeric_limits<unsigned long long>::max(), - 0.0, 3.5)); + EXPECT_EQ(3.5, + clampTo<double>(std::numeric_limits<uint64_t>::max(), 0.0, 3.5)); } TEST(MathExtrasText, clampToLongLongDouble) { double overflow_ll = - static_cast<double>(std::numeric_limits<long long>::max()) * 2; - EXPECT_EQ(std::numeric_limits<long long>::max(), - clampTo<long long>(overflow_ll)); - EXPECT_EQ(std::numeric_limits<long long>::min(), - clampTo<long long>(-overflow_ll)); + static_cast<double>(std::numeric_limits<int64_t>::max()) * 2; + EXPECT_EQ(std::numeric_limits<int64_t>::max(), clampTo<int64_t>(overflow_ll)); + EXPECT_EQ(std::numeric_limits<int64_t>::min(), + clampTo<int64_t>(-overflow_ll)); } TEST(MathExtrasText, clampToUnsignedLongLongDouble) { double overflow_ull = - static_cast<double>(std::numeric_limits<unsigned long long>::max()) * 2; - EXPECT_EQ(std::numeric_limits<unsigned long long>::max(), - clampTo<unsigned long long>(overflow_ull)); - EXPECT_EQ(std::numeric_limits<unsigned long long>::min(), - clampTo<unsigned long long>(-overflow_ull)); + static_cast<double>(std::numeric_limits<uint64_t>::max()) * 2; + EXPECT_EQ(std::numeric_limits<uint64_t>::max(), + clampTo<uint64_t>(overflow_ull)); + EXPECT_EQ(std::numeric_limits<uint64_t>::min(), + clampTo<uint64_t>(-overflow_ull)); } TEST(MathExtrasTest, clampToUnsignedUnsignedLong) { @@ -196,8 +195,8 @@ } TEST(MathExtrasTest, clampToUnsignedUnsignedLongLong) { - unsigned long long max_unsigned = std::numeric_limits<unsigned>::max(); - unsigned long long overflow_unsigned = max_unsigned + 1; + uint64_t max_unsigned = std::numeric_limits<unsigned>::max(); + uint64_t overflow_unsigned = max_unsigned + 1; EXPECT_GT(overflow_unsigned, max_unsigned); @@ -208,31 +207,30 @@ } TEST(MathExtrasTest, clampToLongLongUnsignedLongLong) { - long long max_long_long_ll = std::numeric_limits<long long>::max(); - unsigned long long max_long_long_ull = max_long_long_ll; - unsigned long long overflow_long_long = max_long_long_ull + 1; + int64_t max_long_long_ll = std::numeric_limits<int64_t>::max(); + uint64_t max_long_long_ull = max_long_long_ll; + uint64_t overflow_long_long = max_long_long_ull + 1; EXPECT_GT(overflow_long_long, max_long_long_ull); - EXPECT_EQ(max_long_long_ll, clampTo<long long>(max_long_long_ull)); - EXPECT_EQ(max_long_long_ll - 1, clampTo<long long>(max_long_long_ull - 1)); - EXPECT_EQ(max_long_long_ll, clampTo<long long>(overflow_long_long)); + EXPECT_EQ(max_long_long_ll, clampTo<int64_t>(max_long_long_ull)); + EXPECT_EQ(max_long_long_ll - 1, clampTo<int64_t>(max_long_long_ull - 1)); + EXPECT_EQ(max_long_long_ll, clampTo<int64_t>(overflow_long_long)); - EXPECT_EQ(-3LL, clampTo<long long>(2ULL, -5LL, -3LL)); + EXPECT_EQ(-3LL, clampTo<int64_t>(2ULL, -5LL, -3LL)); } TEST(MathExtrasTest, clampToUnsignedLongLongInt) { - EXPECT_EQ(0ULL, clampTo<unsigned long long>(-1)); - EXPECT_EQ(0ULL, clampTo<unsigned long long>(0)); - EXPECT_EQ(1ULL, clampTo<unsigned long long>(1)); + EXPECT_EQ(0ULL, clampTo<uint64_t>(-1)); + EXPECT_EQ(0ULL, clampTo<uint64_t>(0)); + EXPECT_EQ(1ULL, clampTo<uint64_t>(1)); } TEST(MathExtrasTest, clampToUnsignedLongLongUnsignedLongLong) { - EXPECT_EQ(0ULL, clampTo<unsigned long long>(0ULL)); - EXPECT_EQ(1ULL, clampTo<unsigned long long>(0ULL, 1ULL, 2ULL)); - EXPECT_EQ(2ULL, clampTo<unsigned long long>(3ULL, 1ULL, 2ULL)); - EXPECT_EQ(0xFFFFFFFFFFFFFFF5ULL, - clampTo<unsigned long long>(0xFFFFFFFFFFFFFFF5ULL)); + EXPECT_EQ(0ULL, clampTo<uint64_t>(0ULL)); + EXPECT_EQ(1ULL, clampTo<uint64_t>(0ULL, 1ULL, 2ULL)); + EXPECT_EQ(2ULL, clampTo<uint64_t>(3ULL, 1ULL, 2ULL)); + EXPECT_EQ(0xFFFFFFFFFFFFFFF5ULL, clampTo<uint64_t>(0xFFFFFFFFFFFFFFF5ULL)); } // Make sure that various +-inf cases are handled properly (they weren't
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index c6aee88..4d39582b 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -3024,6 +3024,8 @@ crbug.com/918664 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/sizing/block-size-with-min-or-max-content-table-1a.html [ Failure Pass ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Mac10.10 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller.https.html [ Failure ] +crbug.com/626703 [ Mac10.11 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller.https.html [ Failure ] crbug.com/626703 external/wpt/html/semantics/forms/the-fieldset-element/accessibility/fieldset-div-display-contents-manual.html [ Skip ] crbug.com/626703 external/wpt/html/semantics/forms/the-fieldset-element/accessibility/role-manual.html [ Skip ] crbug.com/626703 external/wpt/html/semantics/forms/the-fieldset-element/accessibility/shadow-dom-manual.html [ Skip ] @@ -5997,5 +5999,8 @@ crbug.com/937991 [ Win7 Release ] http/tests/devtools/cache-storage/cache-data.js [ Pass Timeout ] # Sheriff 2019-03-05 -crbug.com/938200 http/tests/devtools/network/network-blocked-reason.js [ Timeout Pass ] http/tests/devtools/network/network-blocked-reason.js +crbug.com/938200 http/tests/devtools/network/network-blocked-reason.js [ Timeout Pass ] crbug.com/938780 [ Mac ] external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller.https.html [ Failure ] + +# Sheriff 2019-03-06 +crbug.com/938591 [ Linux ] fast/events/middleClickAutoscroll-nested-divs-forbidden.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/accessibility/inline-text-changes.html b/third_party/blink/web_tests/accessibility/inline-text-changes.html index 72151ca..7515f0b 100644 --- a/third_party/blink/web_tests/accessibility/inline-text-changes.html +++ b/third_party/blink/web_tests/accessibility/inline-text-changes.html
@@ -30,7 +30,8 @@ assert_equals(axInlineBefore1.name, 'two lines of text.'); // Modify the text. - document.getElementById("p").innerText += ' One more sentence.'; + var p = document.getElementById("p"); + p.firstChild.data = p.innerText + ' One more sentence.'; // Wait for a notification on the element before checking the new state. axStaticText.addNotificationListener(t.step_func((notification) => {
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json index a2b6717..ef9a991 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -6403,12 +6403,6 @@ {} ] ], - "uievents/click/click_event_target-manual.html": [ - [ - "/uievents/click/click_event_target-manual.html", - {} - ] - ], "uievents/interface/click-event-manual.htm": [ [ "/uievents/interface/click-event-manual.htm", @@ -7011,6 +7005,30 @@ {} ] ], + "animation-worklet/worklet-animation-with-scroll-timeline-and-overflow-hidden.https.html": [ + [ + "/animation-worklet/worklet-animation-with-scroll-timeline-and-overflow-hidden.https.html", + [ + [ + "/animation-worklet/worklet-animation-with-scroll-timeline-and-overflow-hidden-ref.html", + "==" + ] + ], + {} + ] + ], + "animation-worklet/worklet-animation-with-scroll-timeline-root-scroller.https.html": [ + [ + "/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller.https.html", + [ + [ + "/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller-ref.html", + "==" + ] + ], + {} + ] + ], "animation-worklet/worklet-animation-with-scroll-timeline.https.html": [ [ "/animation-worklet/worklet-animation-with-scroll-timeline.https.html", @@ -40987,6 +41005,18 @@ {} ] ], + "css/css-flexbox/flex-basis-010.html": [ + [ + "/css/css-flexbox/flex-basis-010.html", + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], "css/css-flexbox/flex-box-wrap.html": [ [ "/css/css-flexbox/flex-box-wrap.html", @@ -41479,6 +41509,18 @@ {} ] ], + "css/css-flexbox/flex-minimum-height-flex-items-013.html": [ + [ + "/css/css-flexbox/flex-minimum-height-flex-items-013.html", + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], "css/css-flexbox/flex-minimum-width-flex-items-001.xht": [ [ "/css/css-flexbox/flex-minimum-width-flex-items-001.xht", @@ -55767,6 +55809,18 @@ {} ] ], + "css/css-overflow/webkit-line-clamp/webkit-line-clamp-with-line-height.tentative.html": [ + [ + "/css/css-overflow/webkit-line-clamp/webkit-line-clamp-with-line-height.tentative.html", + [ + [ + "/css/css-overflow/webkit-line-clamp/webkit-line-clamp-with-line-height-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-paint-api/background-image-alpha.https.html": [ [ "/css/css-paint-api/background-image-alpha.https.html", @@ -117106,11 +117160,21 @@ {} ] ], + "animation-worklet/worklet-animation-with-scroll-timeline-and-overflow-hidden-ref.html": [ + [ + {} + ] + ], "animation-worklet/worklet-animation-with-scroll-timeline-ref.html": [ [ {} ] ], + "animation-worklet/worklet-animation-with-scroll-timeline-root-scroller-ref.html": [ + [ + {} + ] + ], "apng/META.yml": [ [ {} @@ -141421,6 +141485,11 @@ {} ] ], + "css/css-overflow/webkit-line-clamp/webkit-line-clamp-with-line-height-ref.html": [ + [ + {} + ] + ], "css/css-overscroll-behavior/META.yml": [ [ {} @@ -186886,6 +186955,11 @@ {} ] ], + "signed-exchange/resources/sxg-navigation-timing.html": [ + [ + {} + ] + ], "signed-exchange/resources/sxg-util.js": [ [ {} @@ -187006,6 +187080,11 @@ {} ] ], + "signed-exchange/resources/sxg/sxg-navigation-timing.sxg": [ + [ + {} + ] + ], "signed-exchange/resources/sxg/sxg-noncacheable.sxg": [ [ {} @@ -195946,6 +196025,11 @@ {} ] ], + "web-nfc/nfc_hw_disabled-manual.https-expected.txt": [ + [ + {} + ] + ], "web-nfc/nfc_push.https-expected.txt": [ [ {} @@ -200271,11 +200355,6 @@ {} ] ], - "workers/constructors/Worker/unresolvable-url-expected.txt": [ - [ - {} - ] - ], "workers/data-url-shared-window.html": [ [ {} @@ -200751,11 +200830,46 @@ {} ] ], + "workers/support/Worker-messageport.js": [ + [ + {} + ] + ], + "workers/support/Worker-run-forever.js": [ + [ + {} + ] + ], + "workers/support/Worker-structure-message.js": [ + [ + {} + ] + ], "workers/support/Worker-termination-with-port-messages.js": [ [ {} ] ], + "workers/support/Worker-thread-multi-port.js": [ + [ + {} + ] + ], + "workers/support/Worker-timeout-cancel-order.js": [ + [ + {} + ] + ], + "workers/support/Worker-timeout-decreasing-order.js": [ + [ + {} + ] + ], + "workers/support/Worker-timeout-increasing-order.js": [ + [ + {} + ] + ], "workers/support/WorkerBasic.js": [ [ {} @@ -200776,6 +200890,11 @@ {} ] ], + "workers/support/WorkerGlobalScope-close.js": [ + [ + {} + ] + ], "workers/support/WorkerLocation-origin.html": [ [ {} @@ -200811,11 +200930,31 @@ {} ] ], + "workers/support/importScripts-1.js": [ + [ + {} + ] + ], + "workers/support/importScripts-2.js": [ + [ + {} + ] + ], + "workers/support/importScripts-3.js": [ + [ + {} + ] + ], "workers/support/imported_script.py": [ [ {} ] ], + "workers/support/invalidScript.js": [ + [ + {} + ] + ], "workers/support/name-as-accidental-global.js": [ [ {} @@ -221035,6 +221174,12 @@ {} ] ], + "css/css-position/position-absolute-container-dynamic-002.html": [ + [ + "/css/css-position/position-absolute-container-dynamic-002.html", + {} + ] + ], "css/css-position/position-absolute-container-dynamic.html": [ [ "/css/css-position/position-absolute-container-dynamic.html", @@ -221047,6 +221192,12 @@ {} ] ], + "css/css-position/position-absolute-crash-chrome-002.html": [ + [ + "/css/css-position/position-absolute-crash-chrome-002.html", + {} + ] + ], "css/css-position/position-absolute-dynamic-containing-block.html": [ [ "/css/css-position/position-absolute-dynamic-containing-block.html", @@ -287689,6 +287840,12 @@ {} ] ], + "signed-exchange/sxg-navigation-timing.tentative.html": [ + [ + "/signed-exchange/sxg-navigation-timing.tentative.html", + {} + ] + ], "signed-exchange/sxg-non-secure-origin.tentative.html": [ [ "/signed-exchange/sxg-non-secure-origin.tentative.html", @@ -290883,6 +291040,14 @@ } ] ], + "uievents/click/click_event_target.html": [ + [ + "/uievents/click/click_event_target.html", + { + "testdriver": true + } + ] + ], "uievents/click/mouse-dblclick-event.html": [ [ "/uievents/click/mouse-dblclick-event.html", @@ -299089,6 +299254,24 @@ {} ] ], + "workers/Worker-messageport.html": [ + [ + "/workers/Worker-messageport.html", + {} + ] + ], + "workers/Worker-multi-port.html": [ + [ + "/workers/Worker-multi-port.html", + {} + ] + ], + "workers/Worker-nested-importScripts-error.html": [ + [ + "/workers/Worker-nested-importScripts-error.html", + {} + ] + ], "workers/Worker-replace-global-constructor.any.js": [ [ "/workers/Worker-replace-global-constructor.any.serviceworker.html", @@ -299123,12 +299306,48 @@ {} ] ], + "workers/Worker-structure-message.html": [ + [ + "/workers/Worker-structure-message.html", + {} + ] + ], + "workers/Worker-terminate-forever.html": [ + [ + "/workers/Worker-terminate-forever.html", + {} + ] + ], "workers/Worker-termination-with-port-messages.html": [ [ "/workers/Worker-termination-with-port-messages.html", {} ] ], + "workers/Worker-timeout-cancel-order.html": [ + [ + "/workers/Worker-timeout-cancel-order.html", + {} + ] + ], + "workers/Worker-timeout-decreasing-order.html": [ + [ + "/workers/Worker-timeout-decreasing-order.html", + {} + ] + ], + "workers/Worker-timeout-increasing-order.html": [ + [ + "/workers/Worker-timeout-increasing-order.html", + {} + ] + ], + "workers/WorkerGlobalScope-close.html": [ + [ + "/workers/WorkerGlobalScope-close.html", + {} + ] + ], "workers/WorkerGlobalScope_ErrorEvent_colno.htm": [ [ "/workers/WorkerGlobalScope_ErrorEvent_colno.htm", @@ -299153,12 +299372,6 @@ {} ] ], - "workers/WorkerGlobalScope_close.htm": [ - [ - "/workers/WorkerGlobalScope_close.htm", - {} - ] - ], "workers/WorkerGlobalScope_importScripts.htm": [ [ "/workers/WorkerGlobalScope_importScripts.htm", @@ -299587,6 +299800,12 @@ {} ] ], + "workers/constructors/Worker/Worker-constructor.html": [ + [ + "/workers/constructors/Worker/Worker-constructor.html", + {} + ] + ], "workers/constructors/Worker/ctor-1.html": [ [ "/workers/constructors/Worker/ctor-1.html", @@ -299611,18 +299830,6 @@ {} ] ], - "workers/constructors/Worker/no-arguments-ctor.html": [ - [ - "/workers/constructors/Worker/no-arguments-ctor.html", - {} - ] - ], - "workers/constructors/Worker/resolve-empty-string.html": [ - [ - "/workers/constructors/Worker/resolve-empty-string.html", - {} - ] - ], "workers/constructors/Worker/same-origin.html": [ [ "/workers/constructors/Worker/same-origin.html", @@ -299641,12 +299848,6 @@ {} ] ], - "workers/constructors/Worker/unresolvable-url.html": [ - [ - "/workers/constructors/Worker/unresolvable-url.html", - {} - ] - ], "workers/constructors/Worker/use-base-url.html": [ [ "/workers/constructors/Worker/use-base-url.html", @@ -317546,10 +317747,26 @@ "6f981854d38877d42b1c7b63afdb9ec989a32d42", "reftest" ], + "animation-worklet/worklet-animation-with-scroll-timeline-and-overflow-hidden-ref.html": [ + "c6d7314e396e85225f245905f5afa17fb848b469", + "support" + ], + "animation-worklet/worklet-animation-with-scroll-timeline-and-overflow-hidden.https.html": [ + "8c3ebb66434f49c6ce2f21b0c0976dacc89516f3", + "reftest" + ], "animation-worklet/worklet-animation-with-scroll-timeline-ref.html": [ "fe92232d9afa24f78e9cc7cc3bae341ba2a471bc", "support" ], + "animation-worklet/worklet-animation-with-scroll-timeline-root-scroller-ref.html": [ + "5810e1738c1d5927223037e97a7a14a52c405a5e", + "support" + ], + "animation-worklet/worklet-animation-with-scroll-timeline-root-scroller.https.html": [ + "be577dcc50f2cd462455bac1361bf4fab8b8a5ec", + "reftest" + ], "animation-worklet/worklet-animation-with-scroll-timeline.https.html": [ "000517162af20406e39831afc0b6cefa0b367f2c", "reftest" @@ -346618,6 +346835,10 @@ "3e2026958fdd899349126ebe4778fb62a692d631", "testharness" ], + "css/css-flexbox/flex-basis-010.html": [ + "79992974b054b553b9052cba32a16fd89c37a866", + "reftest" + ], "css/css-flexbox/flex-box-wrap.html": [ "2a1ab9c00cda7b78026eb04e31894bda43392a5d", "reftest" @@ -346858,6 +347079,10 @@ "a193c29cb6001bfc1bc7dc2c7258a48ae9da17a6", "testharness" ], + "css/css-flexbox/flex-minimum-height-flex-items-013.html": [ + "9989b6463780fad120724ab52998353958650c81", + "reftest" + ], "css/css-flexbox/flex-minimum-width-flex-items-001.xht": [ "b8e2866edaa46af46900c287238894cd8ddef24c", "reftest" @@ -364046,6 +364271,14 @@ "de894fab610b31257d73ef5488c376e50d899fb9", "support" ], + "css/css-overflow/webkit-line-clamp/webkit-line-clamp-with-line-height-ref.html": [ + "5c27ecce55ef0c3c2e6a9ae120dabab988b37a06", + "support" + ], + "css/css-overflow/webkit-line-clamp/webkit-line-clamp-with-line-height.tentative.html": [ + "2cd7177ece8d2d0a2193c794fe6312b84568e337", + "reftest" + ], "css/css-overscroll-behavior/META.yml": [ "97705c2df87277d9e5af97d53e453305449c94b8", "support" @@ -364762,6 +364995,10 @@ "2b158a86f6599e43f6a2315a2943b4d394405ba5", "testharness" ], + "css/css-position/position-absolute-container-dynamic-002.html": [ + "91d862835e6d1351deefb26f7e2b71a9539bbd6c", + "testharness" + ], "css/css-position/position-absolute-container-dynamic.html": [ "711d31766da2e324d3d5ddf0362bc1c71b76d7f3", "testharness" @@ -364770,6 +365007,10 @@ "592e5d22e70f1b0c5e3e4b9222cbd1ccef99bdef", "testharness" ], + "css/css-position/position-absolute-crash-chrome-002.html": [ + "9a4ff0ae58349d7be0583b9e8ccc6bcf6104ab89", + "testharness" + ], "css/css-position/position-absolute-dynamic-containing-block.html": [ "3968f685849663574ca213fcb90dc5fb3eaffaa3", "testharness" @@ -444811,7 +445052,7 @@ "testharness" ], "performance-timeline/po-observe.html": [ - "d65c8a40c981e1e79db9096df3a6991ab62b1e0a", + "1132f12fc8883fec4599bf5ded70209ed1532920", "testharness" ], "performance-timeline/po-resource.html": [ @@ -460603,7 +460844,7 @@ "support" ], "signed-exchange/resources/generate-test-sxgs.sh": [ - "cc2b6dd5a215046d2943b041620ba656b69ea0b0", + "60746ff34caaec9e83942aeae6a6cc74aa8138e0", "support" ], "signed-exchange/resources/inner-url.html": [ @@ -460622,6 +460863,10 @@ "b3ebd2bde7acd2d1885838a37ab9cfc91c250551", "support" ], + "signed-exchange/resources/sxg-navigation-timing.html": [ + "ddbe3503548ae2915253ad1f0ccc62d4278bf17a", + "support" + ], "signed-exchange/resources/sxg-util.js": [ "7abb3cf2079087092ac4a7f7332ecf72f9cabd75", "support" @@ -460718,6 +460963,10 @@ "0c6dce01da270bdacf5d280551d56d1519aff3a3", "support" ], + "signed-exchange/resources/sxg/sxg-navigation-timing.sxg": [ + "56a90d5125e68a5cacb37a239b2b95f35f95c124", + "support" + ], "signed-exchange/resources/sxg/sxg-noncacheable.sxg": [ "88439982f6044b3ddbd1a1e0198bebb6409b0837", "support" @@ -460786,6 +461035,10 @@ "5f923d205421ca30e360ddf0de41bb64733de1d3", "testharness" ], + "signed-exchange/sxg-navigation-timing.tentative.html": [ + "b3f088241f8e2cf3467752d556d8cd58d30d5b07", + "testharness" + ], "signed-exchange/sxg-non-secure-origin.tentative.html": [ "84938da76d09dbe4f045b763e49ba95a4936003f", "testharness" @@ -468559,7 +468812,7 @@ "testharness" ], "trusted-types/TrustedTypePolicyFactory-isXXX.tentative.html": [ - "fada29a209b777eb6b34cb14fceb0bfd2d249142", + "854f69ed1e550bd660b8cf7a18b4a81a666072fd", "testharness" ], "trusted-types/Window-TrustedTypes.tentative.html": [ @@ -468682,9 +468935,9 @@ "9f4ffed96e6cb186f8441e9681c281d087ff8faf", "testharness" ], - "uievents/click/click_event_target-manual.html": [ - "1e5670262b5cb39cf74e34616f908d7cc3cc09cf", - "manual" + "uievents/click/click_event_target.html": [ + "ffe5dbaf3988a4908cda76bf3f4edf901b24833b", + "testharness" ], "uievents/click/mouse-dblclick-event.html": [ "5bf0bbc07e00d3d01bfcc1379b8ac0c2f78fb7b7", @@ -470966,8 +471219,12 @@ "ab0d6cd191a5b576674c0c038087ef17ece4cdfd", "testharness" ], + "web-nfc/nfc_hw_disabled-manual.https-expected.txt": [ + "104d42a9e9a0b5d82ab2b21d9d701dd0a27b9dfa", + "support" + ], "web-nfc/nfc_hw_disabled-manual.https.html": [ - "cd84961c91becdd5bfd29f78ca4f8af3b4d80973", + "bb2cd42f1e65cca49b03385e9e553cc8077aa08d", "manual" ], "web-nfc/nfc_insecure_context.html": [ @@ -479138,6 +479395,18 @@ "2ef944553105767535f6e3119048091f959bfac8", "testharness" ], + "workers/Worker-messageport.html": [ + "f7734b2543fc7ace5c2d330c9f1be4d45c8cb392", + "testharness" + ], + "workers/Worker-multi-port.html": [ + "9a89583ad91b40e64c7a3682da1e5053e18b4d26", + "testharness" + ], + "workers/Worker-nested-importScripts-error.html": [ + "8863b7523010dd8566d1ed42094e519efc500a65", + "testharness" + ], "workers/Worker-replace-global-constructor.any.js": [ "f208f3736362a82a322527b2f983b9e3ccaff33e", "testharness" @@ -479150,10 +479419,34 @@ "4339f2e33436010e0f05ea3d2c5f4ec26039cef0", "testharness" ], + "workers/Worker-structure-message.html": [ + "9eb12dc6c55bc8252ee92746259ef10f4b9a08be", + "testharness" + ], + "workers/Worker-terminate-forever.html": [ + "3528bb6246dd9abd03b68702a1bb12a5616cadce", + "testharness" + ], "workers/Worker-termination-with-port-messages.html": [ "bc19784adae8e060813da4cf6f20dc47ef87ecf4", "testharness" ], + "workers/Worker-timeout-cancel-order.html": [ + "78d930df783b9572395c6dcf1ead552dbb7da898", + "testharness" + ], + "workers/Worker-timeout-decreasing-order.html": [ + "f459461ec061f9e9dd3d829241b117686c053b5b", + "testharness" + ], + "workers/Worker-timeout-increasing-order.html": [ + "34b029466bb29e8a3478e040641415354045fa0f", + "testharness" + ], + "workers/WorkerGlobalScope-close.html": [ + "a193a3478f4a58176314727898593428a53726a3", + "testharness" + ], "workers/WorkerGlobalScope_ErrorEvent_colno.htm": [ "793d6c1807b2966fb28da9cc491df5549d1382ed", "testharness" @@ -479170,10 +479463,6 @@ "bc1d2c45b42cb0e3cb96a243d00f2b7351e8b1d3", "testharness" ], - "workers/WorkerGlobalScope_close.htm": [ - "2ad5205d1b90ff12b1b3d8e8d6bbbb20b33fbff8", - "testharness" - ], "workers/WorkerGlobalScope_importScripts.htm": [ "1a3616df98bc4f9fee566990210203890a8d9af0", "testharness" @@ -479590,6 +479879,10 @@ "2ef466ccdc30484120ff81730d90bd13cb0e52eb", "testharness" ], + "workers/constructors/Worker/Worker-constructor.html": [ + "e073df76f36f0117cdf61e04f05cc8cb0f5530ff", + "testharness" + ], "workers/constructors/Worker/ctor-1.html": [ "bd865261fc6e50bb25f073d68c7c11c20ddcabe9", "testharness" @@ -479610,18 +479903,10 @@ "0ce41b59e7496dfda26053cdfac6bd090b40a3b6", "testharness" ], - "workers/constructors/Worker/no-arguments-ctor.html": [ - "770c7cc93a928229e521117dbd54aa6a5a3263d6", - "testharness" - ], "workers/constructors/Worker/null": [ "6d079b514cf50a42deb039a2503a6f7ca1f2f70d", "support" ], - "workers/constructors/Worker/resolve-empty-string.html": [ - "0426223e0a81d72091d6df5a6cd60c7a9ccc4e2c", - "testharness" - ], "workers/constructors/Worker/same-origin.html": [ "560b34679674a98a9639fdf613a25f4e8c537572", "testharness" @@ -479642,14 +479927,6 @@ "69d29b2297847124206b392fea67949106a8a3fe", "testharness" ], - "workers/constructors/Worker/unresolvable-url-expected.txt": [ - "f6e2da6493fce113e82a939cad82cc656d774c3a", - "support" - ], - "workers/constructors/Worker/unresolvable-url.html": [ - "8c04b0087839808e98f66b79797e38a2e58912f6", - "testharness" - ], "workers/constructors/Worker/use-base-url.html": [ "94ce2a71f14296a66bec0325f2d1d22ba1355b16", "testharness" @@ -480530,10 +480807,38 @@ "f0b8efe46bd8c93e5c2af1e239139faae76a16be", "support" ], + "workers/support/Worker-messageport.js": [ + "1e01b0a52b586b00cbbb28b2352959f7fa150e39", + "support" + ], + "workers/support/Worker-run-forever.js": [ + "912e49de65081d216980a54d4f5479ff880079c4", + "support" + ], + "workers/support/Worker-structure-message.js": [ + "81cd98243b4d6d21977da64d8fa858747b6ddbe3", + "support" + ], "workers/support/Worker-termination-with-port-messages.js": [ "a827db357e2305b32716c447dc70883b8ff3184a", "support" ], + "workers/support/Worker-thread-multi-port.js": [ + "2ce7cae596b561caf5efec6353ed2948d250756e", + "support" + ], + "workers/support/Worker-timeout-cancel-order.js": [ + "afc66cf6a0b4597b6befb58262cedf15b1e55954", + "support" + ], + "workers/support/Worker-timeout-decreasing-order.js": [ + "b93dd5dc771ab4e0901bf1c8f31680feba1f1bdd", + "support" + ], + "workers/support/Worker-timeout-increasing-order.js": [ + "42f81daa29c021bd5b40472a93c5f5bd222548a7", + "support" + ], "workers/support/WorkerBasic.js": [ "6bb6d32b141916146257bbad665e2526111a0849", "support" @@ -480550,6 +480855,10 @@ "4ad700bcce464611b3c3f07e8555b4c6ccb6cfd6", "support" ], + "workers/support/WorkerGlobalScope-close.js": [ + "e2b1c0a2fddfeafd701d7b1a0cbcba87e69a51bc", + "support" + ], "workers/support/WorkerLocation-origin.html": [ "3d948030a79e431efd8d33974ca0f2cd2092ddca", "support" @@ -480578,10 +480887,26 @@ "0fb0ec228079de8dd15626fb3161b53d48c68112", "support" ], + "workers/support/importScripts-1.js": [ + "8869a4fbcafce79b72b8c18e3100dd1ee2a2f7a0", + "support" + ], + "workers/support/importScripts-2.js": [ + "7f3f1116e76ce3f1d2aca375322185db7f2c3fc3", + "support" + ], + "workers/support/importScripts-3.js": [ + "2d103a0411fea792112f52ddbbd90bc3fedab2ba", + "support" + ], "workers/support/imported_script.py": [ "88cd2285e82162679c0bcbcc1ff756c91c12a5a0", "support" ], + "workers/support/invalidScript.js": [ + "8655d4d1f18c83f20e4516f992b25646c7de5c5e", + "support" + ], "workers/support/name-as-accidental-global.js": [ "f2c39ea715aa64a990eda923931969a890ce336d", "support"
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html index 6f98185..9841c575 100644 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html
@@ -61,10 +61,7 @@ const animation = new WorkletAnimation('passthrough', effect, timeline); animation.play(); - // Ensure that the WorkletAnimation will have been started on the compositor. waitForAsyncAnimationFrames(1).then(_ => { - // Now return the scroller to the world, which will cause it to be composited - // and the animation should update on the compositor side. scroller.classList.remove('removed'); const maxScroll = scroller.scrollHeight - scroller.clientHeight; scroller.scrollTop = 0.5 * maxScroll;
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-overflow-hidden-ref.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-overflow-hidden-ref.html index c6d7314e..2004e6df 100644 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-overflow-hidden-ref.html +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-overflow-hidden-ref.html
@@ -7,7 +7,6 @@ background-color: green; transform: translate(0, 100px); opacity: 0.5; - will-change: transform; /* force compositing */ } #covered { @@ -20,7 +19,6 @@ overflow: hidden; height: 100px; width: 100px; - will-change: transform; /* force compositing */ } #contents {
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-ref.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-ref.html index fe92232..f30c861f 100644 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-ref.html +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-ref.html
@@ -7,7 +7,6 @@ background-color: green; transform: translate(0, 100px); opacity: 0.5; - will-change: transform; /* force compositing */ } #covered { @@ -20,7 +19,8 @@ overflow: auto; height: 100px; width: 100px; - will-change: transform; /* force compositing */ + /* TODO(yigu): Rewrite the test to not rely on compositing. */ + will-change: transform; } #contents {
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller-ref.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller-ref.html index 5810e17..3b527dc 100644 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller-ref.html +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller-ref.html
@@ -14,7 +14,6 @@ background-color: green; transform: translate(0, 100px); opacity: 0.5; - will-change: transform; /* force compositing */ } #covered {
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/buffer-before-onload.html b/third_party/blink/web_tests/external/wpt/element-timing/buffer-before-onload.html index 4d59d4af..1fd0277 100644 --- a/third_party/blink/web_tests/external/wpt/element-timing/buffer-before-onload.html +++ b/third_party/blink/web_tests/external/wpt/element-timing/buffer-before-onload.html
@@ -20,12 +20,14 @@ img.setAttribute('elementtiming', 'my_image'); document.body.appendChild(img); window.onload = t.step_func_done( () => { - const entries = performance.getEntriesByName('my_image'); - assert_equals(entries.length, 1); - assert_greater_than_equal(performance.getEntriesByType('element').length, 1); - assert_equals(performance.getEntries().filter(e => e.name === 'my_image').length, 1); + const entries = performance.getEntriesByType('element'); + assert_greater_than_equal(entries.length, 1); + assert_equals(performance.getEntries().filter(e => e.identifier === 'my_image').length, 1); const entry = entries[0]; - checkElement(entry, 'my_image', beforeRender); + const index = window.location.href.lastIndexOf('/'); + const pathname = window.location.href.substring(0, index) + + '/resources/square20.jpg'; + checkElement(entry, pathname, 'my_image', beforeRender); }); }, "Element Timing: image loads before onload.");
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/image-TAO-wildcard.sub.html b/third_party/blink/web_tests/external/wpt/element-timing/image-TAO-wildcard.sub.html index 6d5abe2..3ba12a7d0 100644 --- a/third_party/blink/web_tests/external/wpt/element-timing/image-TAO-wildcard.sub.html +++ b/third_party/blink/web_tests/external/wpt/element-timing/image-TAO-wildcard.sub.html
@@ -13,11 +13,13 @@ <script> async_test((t) => { let beforeRender; + const img_src = 'http://{{domains[www]}}:{{ports[http][1]}}/element-timing/' + + 'resources/TAOImage.py?tao=wildcard'; const observer = new PerformanceObserver( t.step_func_done((entryList) => { assert_equals(entryList.getEntries().length, 1); const entry = entryList.getEntries()[0]; - checkElement(entry, 'my_image', beforeRender); + checkElement(entry, img_src, 'my_image', beforeRender); // Assume viewport has size at least 20, so the element is fully visible. checkRect(entry, [0, 20, 0, 20]); }) @@ -28,8 +30,7 @@ // TODO(npm): change observer to use buffered flag. window.onload = t.step_func(() => { const img = document.createElement('img'); - img.src = 'http://{{domains[www]}}:{{ports[http][1]}}/' - + 'element-timing/resources/TAOImage.py?tao=wildcard'; + img.src = img_src; img.setAttribute('elementtiming', 'my_image'); img.onload = t.step_func(() => { // After a short delay, assume that the entry was not dispatched.
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/image-not-fully-visible.html b/third_party/blink/web_tests/external/wpt/element-timing/image-not-fully-visible.html index 8ab3f343..d3e2c105 100644 --- a/third_party/blink/web_tests/external/wpt/element-timing/image-not-fully-visible.html +++ b/third_party/blink/web_tests/external/wpt/element-timing/image-not-fully-visible.html
@@ -17,7 +17,10 @@ t.step_func_done(function(entryList) { assert_equals(entryList.getEntries().length, 1); const entry = entryList.getEntries()[0]; - checkElement(entry, 'not_fully_visible', beforeRender); + const index = window.location.href.lastIndexOf('/'); + const pathname = window.location.href.substring(0, index) + + '/resources/square20.png'; + checkElement(entry, pathname, 'not_fully_visible', beforeRender); // Image will not be fully visible. It should start from the top left part // of the document, excluding the margin, and then overflow. checkRect(entry,
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/images-repeated-resource.html b/third_party/blink/web_tests/external/wpt/element-timing/images-repeated-resource.html new file mode 100644 index 0000000..18c72cd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/element-timing/images-repeated-resource.html
@@ -0,0 +1,61 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>Element Timing: observe elements with the same resource</title> +<body> +<style> +body { + margin: 0; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/element-timing-helpers.js"></script> +<script> + let beforeRender; + let numEntries = 0; + let responseEnd1; + let responseEnd2; + const index = window.location.href.lastIndexOf('/'); + const pathname = window.location.href.substring(0, index) + + '/resources/square100.png'; + async_test(function (t) { + const observer = new PerformanceObserver( + t.step_func(function(entryList) { + entryList.getEntries().forEach(entry => { + checkElement(entry, pathname, entry.identifier, beforeRender); + if (entry.identifier === 'my_image') { + ++numEntries; + responseEnd1 = entry.responseEnd; + } + else if (entry.identifier === 'my_image2') { + ++numEntries; + responseEnd2 = entry.responseEnd; + } + }); + if (numEntries == 2) { + assert_equals(responseEnd1, responseEnd2); + t.done(); + } + }) + ); + observer.observe({entryTypes: ['element']}); + // We add the images during onload to be sure that the observer is registered + // in time for it to observe the element timing. + window.onload = () => { + // Add image of width and height equal to 100. + const img = document.createElement('img'); + img.src = 'resources/square100.png'; + img.setAttribute('elementtiming', 'my_image'); + document.body.appendChild(img); + + const img2 = document.createElement('img'); + img2.src = 'resources/square100.png'; + img2.setAttribute('elementtiming', 'my_image2'); + document.body.appendChild(img2); + + beforeRender = performance.now(); + }; + }, 'Element with elementtiming attribute is observable.'); +</script> + +</body>
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/observe-elementtiming.html b/third_party/blink/web_tests/external/wpt/element-timing/observe-elementtiming.html index c148d33a..9170b36 100644 --- a/third_party/blink/web_tests/external/wpt/element-timing/observe-elementtiming.html +++ b/third_party/blink/web_tests/external/wpt/element-timing/observe-elementtiming.html
@@ -17,7 +17,10 @@ t.step_func_done(function(entryList) { assert_equals(entryList.getEntries().length, 1); const entry = entryList.getEntries()[0]; - checkElement(entry, 'my_image', beforeRender); + const index = window.location.href.lastIndexOf('/'); + const pathname = window.location.href.substring(0, index) + + '/resources/square100.png'; + checkElement(entry, pathname, 'my_image', beforeRender); // Assume viewport has size at least 100, so the element is fully visible. checkRect(entry, [0, 100, 0, 100]); })
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/observe-large-image.html b/third_party/blink/web_tests/external/wpt/element-timing/observe-large-image.html index ef3eab8..fb288438 100644 --- a/third_party/blink/web_tests/external/wpt/element-timing/observe-large-image.html +++ b/third_party/blink/web_tests/external/wpt/element-timing/observe-large-image.html
@@ -17,7 +17,10 @@ t.step_func_done(function(entryList) { assert_equals(entryList.getEntries().length, 1); const entry = entryList.getEntries()[0]; - checkElement(entry, 'img', beforeRender) + const index = window.location.href.lastIndexOf('/'); + const pathname = window.location.href.substring(0, index) + + '/resources/square20.jpg'; + checkElement(entry, pathname, '', beforeRender); // Assume viewport hasn't changed, so the element occupies all of it. checkRect(entry, [0, document.documentElement.clientWidth, 0, document.documentElement.clientHeight]);
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/observe-multiple-images.html b/third_party/blink/web_tests/external/wpt/element-timing/observe-multiple-images.html index e56092c6..aa91aa83 100644 --- a/third_party/blink/web_tests/external/wpt/element-timing/observe-multiple-images.html +++ b/third_party/blink/web_tests/external/wpt/element-timing/observe-multiple-images.html
@@ -22,16 +22,19 @@ <script> let beforeRender, image1Observed=0, image2Observed=0, image3Observed=0; async_test(function (t) { + const index = window.location.href.lastIndexOf('/'); const observer = new PerformanceObserver( t.step_func(function(entryList) { entryList.getEntries().forEach( entry => { - if (entry.name === 'image1') { + if (entry.identifier === 'image1') { if (image1Observed) { assert_unreached("Observer received image1 more than once"); t.done(); } image1Observed = 1; - checkElement(entry, 'image1', beforeRender); + const pathname1 = window.location.href.substring(0, index) + + '/resources/square100.png'; + checkElement(entry, pathname1, 'image1', beforeRender); // This image is horizontally centered. // Using abs and comparing to 1 because the viewport sizes could be odd. // If a size is odd, then image cannot be in the pure center, but left @@ -46,28 +49,32 @@ assert_equals(entry.intersectionRect.bottom, 100, 'bottom of rect for image1'); } - else if (entry.name === 'image2') { + else if (entry.identifier === 'image2') { if (image2Observed) { assert_unreached("Observer received image2 more than once"); t.done(); } image2Observed = 1; - checkElement(entry, 'image2', beforeRender); + const pathname2 = window.location.href.substring(0, index) + + '/resources/square20.png'; + checkElement(entry, pathname2, 'image2', beforeRender); // This image should be below image 1, and should respect the margin. checkRect(entry, [50, 250, 250, 450], "of image2"); } - else if (entry.name === 'image3') { + else if (entry.identifier === 'image3') { if (image3Observed) { assert_unreached("Observer received image3 more than once"); t.done(); } image3Observed = 1; - checkElement(entry, 'image3', beforeRender); + const pathname3 = window.location.href.substring(0, index) + + '/resources/circle.svg'; + checkElement(entry, pathname3, 'image3', beforeRender); // This image is just to the right of image2. checkRect(entry, [250, 450, 250, 450], "of image3"); } else { - assert_unreached("Received an unexpected name."); + assert_unreached("Received an unexpected identifier."); t.done(); } if (image1Observed && image2Observed && image3Observed) {
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/observe-svg-image.html b/third_party/blink/web_tests/external/wpt/element-timing/observe-svg-image.html index 327ab69..f127152c 100644 --- a/third_party/blink/web_tests/external/wpt/element-timing/observe-svg-image.html +++ b/third_party/blink/web_tests/external/wpt/element-timing/observe-svg-image.html
@@ -11,7 +11,10 @@ t.step_func_done(function(entryList) { assert_equals(entryList.getEntries().length, 1); const entry = entryList.getEntries()[0]; - checkElement(entry, 'my_svg', beforeRender); + const index = window.location.href.lastIndexOf('/'); + const pathname = window.location.href.substring(0, index) + + '/resources/circle.svg'; + checkElement(entry, pathname, 'my_svg', beforeRender); // Assume viewport has size at least 200, so the element is fully visible. checkRect(entry, [0, 200, 0, 200]); })
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/progressively-loaded-image.html b/third_party/blink/web_tests/external/wpt/element-timing/progressively-loaded-image.html index 6fdff39..cf54e1e 100644 --- a/third_party/blink/web_tests/external/wpt/element-timing/progressively-loaded-image.html +++ b/third_party/blink/web_tests/external/wpt/element-timing/progressively-loaded-image.html
@@ -13,20 +13,24 @@ let numInitial = 75; let sleep = 500; async_test(function(t) { + const img_src = 'resources/progressive-image.py?name=square20.jpg&numInitial=' + + numInitial + '&sleep=' + sleep; const observer = new PerformanceObserver( t.step_func_done(function(entryList) { assert_equals(entryList.getEntries().length, 1); const entry = entryList.getEntries()[0]; + const index = window.location.href.lastIndexOf('/'); + const pathname = window.location.href.substring(0, index) + '/' + + img_src; // Since the image is only fully loaded after the sleep, the render timestamp // must be greater than |beforeRender| + |sleep|. - checkElement(entry, 'my_image', beforeRender + sleep); + checkElement(entry, pathname, 'my_image', beforeRender + sleep); }) ); observer.observe({entryTypes: ['element']}); const img = document.createElement('img'); - img.src = 'resources/progressive-image.py?name=square20.jpg&numInitial=' - + numInitial + '&sleep=' + sleep; + img.src = img_src; img.setAttribute('elementtiming', 'my_image'); document.body.appendChild(img); beforeRender = performance.now();
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/resources/element-timing-helpers.js b/third_party/blink/web_tests/external/wpt/element-timing/resources/element-timing-helpers.js index 0be97e4..e952930 100644 --- a/third_party/blink/web_tests/external/wpt/element-timing/resources/element-timing-helpers.js +++ b/third_party/blink/web_tests/external/wpt/element-timing/resources/element-timing-helpers.js
@@ -1,11 +1,15 @@ // Checks that this is an ElementTiming entry with name |expectedName|. It also // does a very basic check on |startTime|: after |beforeRender| and before now(). -function checkElement(entry, expectedName, beforeRender) { +function checkElement(entry, expectedName, expectedIdentifier, beforeRender) { assert_equals(entry.entryType, 'element'); assert_equals(entry.name, expectedName); + assert_equals(entry.identifier, expectedIdentifier); assert_equals(entry.duration, 0); assert_greater_than_equal(entry.startTime, beforeRender); assert_greater_than_equal(performance.now(), entry.startTime); + const rt_entries = performance.getEntriesByName(expectedName, 'resource'); + assert_equals(rt_entries.length, 1); + assert_equals(rt_entries[0].responseEnd, entry.responseEnd); } // Checks that the rect matches the desired values [left right top bottom]
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/elements/the-innertext-idl-attribute/setter-expected.txt b/third_party/blink/web_tests/external/wpt/html/dom/elements/the-innertext-idl-attribute/setter-expected.txt deleted file mode 100644 index e263930..0000000 --- a/third_party/blink/web_tests/external/wpt/html/dom/elements/the-innertext-idl-attribute/setter-expected.txt +++ /dev/null
@@ -1,130 +0,0 @@ -This is a testharness.js-based test. -Found 126 tests; 95 PASS, 31 FAIL, 0 TIMEOUT, 0 NOTRUN. -PASS Simplest possible test -PASS Simplest possible test, detached -PASS Newlines convert to <br> in non-white-space:pre elements -PASS Newlines convert to <br> in non-white-space:pre elements, detached -PASS Newlines convert to <br> in <pre> element -PASS Newlines convert to <br> in <pre> element, detached -PASS Newlines convert to <br> in <textarea> element -PASS Newlines convert to <br> in <textarea> element, detached -PASS Newlines convert to <br> in white-space:pre element -PASS Newlines convert to <br> in white-space:pre element, detached -PASS CRs convert to <br> in non-white-space:pre elements -PASS CRs convert to <br> in non-white-space:pre elements, detached -PASS CRs convert to <br> in <pre> element -PASS CRs convert to <br> in <pre> element, detached -PASS Newline/CR pair converts to <br> in non-white-space:pre element -PASS Newline/CR pair converts to <br> in non-white-space:pre element, detached -PASS Newline/newline pair converts to two <br>s in non-white-space:pre element -PASS Newline/newline pair converts to two <br>s in non-white-space:pre element, detached -PASS CR/CR pair converts to two <br>s in non-white-space:pre element -PASS CR/CR pair converts to two <br>s in non-white-space:pre element, detached -PASS CRs convert to <br> in white-space:pre element -PASS CRs convert to <br> in white-space:pre element, detached -PASS < preserved -PASS < preserved, detached -PASS > preserved -PASS > preserved, detached -PASS & preserved -PASS & preserved, detached -PASS " preserved -PASS " preserved, detached -PASS ' preserved -PASS ' preserved, detached -PASS innerText not supported on SVG elements -PASS innerText not supported on SVG elements, detached -PASS innerText not supported on MathML elements -PASS innerText not supported on MathML elements, detached -PASS Null characters preserved -PASS Null characters preserved, detached -PASS Tabs preserved -PASS Tabs preserved, detached -PASS Leading whitespace preserved -PASS Leading whitespace preserved, detached -PASS Trailing whitespace preserved -PASS Trailing whitespace preserved, detached -PASS Whitespace not compressed -PASS Whitespace not compressed, detached -FAIL Existing text deleted assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -FAIL Existing text deleted, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS Existing <br> deleted -PASS Existing <br> deleted, detached -PASS Assigning the empty string -PASS Assigning the empty string, detached -PASS Assigning null -PASS Assigning null, detached -PASS Assigning undefined -PASS Assigning undefined, detached -PASS Start with CR -PASS Start with CR, detached -PASS Start with LF -PASS Start with LF, detached -PASS Start with CRLF -PASS Start with CRLF, detached -PASS End with CR -PASS End with CR, detached -PASS End with LF -PASS End with LF, detached -PASS End with CRLF -PASS End with CRLF, detached -PASS innerText on <area> element -FAIL innerText on <area> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <base> element -FAIL innerText on <base> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <basefont> element -FAIL innerText on <basefont> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <bgsound> element -FAIL innerText on <bgsound> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <br> element -FAIL innerText on <br> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <col> element -FAIL innerText on <col> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <embed> element -FAIL innerText on <embed> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <frame> element -FAIL innerText on <frame> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <hr> element -FAIL innerText on <hr> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <image> element -FAIL innerText on <image> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <img> element -FAIL innerText on <img> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <input> element -FAIL innerText on <input> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <keygen> element -FAIL innerText on <keygen> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <link> element -FAIL innerText on <link> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <menuitem> element -FAIL innerText on <menuitem> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <meta> element -FAIL innerText on <meta> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <param> element -FAIL innerText on <param> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <source> element -FAIL innerText on <source> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <track> element -FAIL innerText on <track> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <wbr> element -FAIL innerText on <wbr> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <colgroup> element -FAIL innerText on <colgroup> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <frameset> element -FAIL innerText on <frameset> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <head> element -FAIL innerText on <head> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <html> element -FAIL innerText on <html> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <table> element -FAIL innerText on <table> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <tbody> element -FAIL innerText on <tbody> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <tfoot> element -FAIL innerText on <tfoot> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <thead> element -FAIL innerText on <thead> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -PASS innerText on <tr> element -FAIL innerText on <tr> element, detached assert_not_equals: Child should be a *new* text node got disallowed value Text node "abc" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/reflection-embedded-expected.txt b/third_party/blink/web_tests/external/wpt/html/dom/reflection-embedded-expected.txt index d109dc5..aea251d9 100644 --- a/third_party/blink/web_tests/external/wpt/html/dom/reflection-embedded-expected.txt +++ b/third_party/blink/web_tests/external/wpt/html/dom/reflection-embedded-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 7087 tests; 6958 PASS, 129 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 7085 tests; 6956 PASS, 129 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS picture.title: 32 tests PASS picture.lang: 32 tests PASS picture.dir: 62 tests @@ -20,8 +20,8 @@ PASS img.crossOrigin: 52 tests PASS img.useMap: 32 tests PASS img.isMap: 33 tests -PASS img.width: 9 tests -PASS img.height: 9 tests +PASS img.width: 8 tests +PASS img.height: 8 tests PASS img.referrerPolicy: 27 tests FAIL img.referrerPolicy: setAttribute() to "same-origin" assert_equals: IDL get expected "same-origin" but got "" PASS img.referrerPolicy: 3 tests
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/reflection-forms-expected.txt b/third_party/blink/web_tests/external/wpt/html/dom/reflection-forms-expected.txt deleted file mode 100644 index 6be164e..0000000 --- a/third_party/blink/web_tests/external/wpt/html/dom/reflection-forms-expected.txt +++ /dev/null
@@ -1,195 +0,0 @@ -This is a testharness.js-based test. -Found 6725 tests; 6722 PASS, 3 FAIL, 0 TIMEOUT, 0 NOTRUN. -PASS form.title: 32 tests -PASS form.lang: 32 tests -PASS form.dir: 62 tests -PASS form.className (<form class>): 32 tests -PASS form.hidden: 33 tests -PASS form.accessKey: 32 tests -PASS form.tabIndex: 24 tests -PASS form.acceptCharset (<form accept-charset>): 32 tests -PASS form.action: 38 tests -PASS form.autocomplete: 52 tests -PASS form.enctype: 62 tests -PASS form.encoding (<form enctype>): 62 tests -PASS form.method: 62 tests -PASS form.name: 32 tests -PASS form.noValidate: 33 tests -PASS form.target: 32 tests -PASS fieldset.title: 32 tests -PASS fieldset.lang: 32 tests -PASS fieldset.dir: 62 tests -PASS fieldset.className (<fieldset class>): 32 tests -PASS fieldset.hidden: 33 tests -PASS fieldset.accessKey: 32 tests -PASS fieldset.tabIndex: 24 tests -PASS fieldset.disabled: 33 tests -PASS fieldset.name: 32 tests -PASS legend.title: 32 tests -PASS legend.lang: 32 tests -PASS legend.dir: 62 tests -PASS legend.className (<legend class>): 32 tests -PASS legend.hidden: 33 tests -PASS legend.accessKey: 32 tests -PASS legend.tabIndex: 24 tests -PASS legend.align: 32 tests -PASS label.title: 32 tests -PASS label.lang: 32 tests -PASS label.dir: 62 tests -PASS label.className (<label class>): 32 tests -PASS label.hidden: 33 tests -PASS label.accessKey: 32 tests -PASS label.tabIndex: 24 tests -PASS label.htmlFor (<label for>): 32 tests -PASS input.title: 32 tests -PASS input.lang: 32 tests -PASS input.dir: 62 tests -PASS input.className (<input class>): 32 tests -PASS input.hidden: 33 tests -PASS input.accessKey: 32 tests -PASS input.tabIndex: 24 tests -PASS input.accept: 32 tests -PASS input.alt: 32 tests -PASS input.autocomplete: 17 tests -PASS input.autofocus: 33 tests -PASS input.defaultChecked (<input checked>): 33 tests -PASS input.dirName: 32 tests -PASS input.disabled: 33 tests -PASS input.formAction: 38 tests -PASS input.formEnctype: 62 tests -PASS input.formMethod: 52 tests -PASS input.formNoValidate: 33 tests -PASS input.formTarget: 32 tests -PASS input.height: 9 tests -PASS input.max: 32 tests -PASS input.maxLength: 61 tests -PASS input.min: 32 tests -PASS input.minLength: 61 tests -PASS input.multiple: 33 tests -PASS input.name: 32 tests -PASS input.pattern: 32 tests -PASS input.placeholder: 32 tests -PASS input.readOnly: 33 tests -PASS input.required: 33 tests -PASS input.size: 59 tests -PASS input.src: 38 tests -PASS input.step: 32 tests -PASS input.type: 256 tests -PASS input.width: 9 tests -PASS input.defaultValue (<input value>): 32 tests -PASS input.align: 32 tests -PASS input.useMap: 32 tests -PASS button.title: 32 tests -PASS button.lang: 32 tests -PASS button.dir: 62 tests -PASS button.className (<button class>): 32 tests -PASS button.hidden: 33 tests -PASS button.accessKey: 32 tests -PASS button.tabIndex: 24 tests -PASS button.autofocus: 33 tests -PASS button.disabled: 33 tests -PASS button.formAction: 38 tests -PASS button.formEnctype: 62 tests -PASS button.formMethod: 62 tests -PASS button.formNoValidate: 33 tests -PASS button.formTarget: 32 tests -PASS button.name: 32 tests -PASS button.type: 62 tests -PASS button.value: 32 tests -PASS select.title: 32 tests -PASS select.lang: 32 tests -PASS select.dir: 62 tests -PASS select.className (<select class>): 32 tests -PASS select.hidden: 33 tests -PASS select.accessKey: 32 tests -PASS select.tabIndex: 24 tests -PASS select.autocomplete: 17 tests -PASS select.autofocus: 33 tests -PASS select.disabled: 33 tests -PASS select.multiple: 33 tests -PASS select.name: 32 tests -PASS select.required: 33 tests -PASS select.size: 62 tests -PASS datalist.title: 32 tests -PASS datalist.lang: 32 tests -PASS datalist.dir: 62 tests -PASS datalist.className (<datalist class>): 32 tests -PASS datalist.hidden: 33 tests -PASS datalist.accessKey: 32 tests -PASS datalist.tabIndex: 24 tests -PASS optgroup.title: 32 tests -PASS optgroup.lang: 32 tests -PASS optgroup.dir: 62 tests -PASS optgroup.className (<optgroup class>): 32 tests -PASS optgroup.hidden: 33 tests -PASS optgroup.accessKey: 32 tests -PASS optgroup.tabIndex: 24 tests -PASS optgroup.disabled: 33 tests -PASS optgroup.label: 32 tests -PASS option.title: 32 tests -PASS option.lang: 32 tests -PASS option.dir: 62 tests -PASS option.className (<option class>): 32 tests -PASS option.hidden: 33 tests -PASS option.accessKey: 32 tests -PASS option.tabIndex: 24 tests -PASS option.disabled: 33 tests -PASS option.label: 17 tests -PASS option.defaultSelected (<option selected>): 33 tests -PASS option.value: 17 tests -PASS textarea.title: 32 tests -PASS textarea.lang: 32 tests -PASS textarea.dir: 62 tests -PASS textarea.className (<textarea class>): 32 tests -PASS textarea.hidden: 33 tests -PASS textarea.accessKey: 32 tests -PASS textarea.tabIndex: 24 tests -PASS textarea.autocomplete: 17 tests -PASS textarea.autofocus: 33 tests -PASS textarea.cols: 59 tests -PASS textarea.dirName: 32 tests -PASS textarea.disabled: 33 tests -PASS textarea.maxLength: 61 tests -PASS textarea.minLength: 61 tests -PASS textarea.name: 32 tests -PASS textarea.placeholder: 32 tests -PASS textarea.readOnly: 33 tests -PASS textarea.required: 33 tests -PASS textarea.rows: 59 tests -PASS textarea.wrap: 32 tests -PASS output.title: 32 tests -PASS output.lang: 32 tests -PASS output.dir: 62 tests -PASS output.className (<output class>): 32 tests -PASS output.hidden: 33 tests -PASS output.accessKey: 32 tests -PASS output.tabIndex: 24 tests -PASS output.name: 32 tests -PASS progress.title: 32 tests -PASS progress.lang: 32 tests -PASS progress.dir: 62 tests -PASS progress.className (<progress class>): 32 tests -PASS progress.hidden: 33 tests -PASS progress.accessKey: 32 tests -PASS progress.tabIndex: 24 tests -PASS meter.title: 32 tests -PASS meter.lang: 32 tests -PASS meter.dir: 62 tests -PASS meter.className (<meter class>): 32 tests -PASS meter.hidden: 33 tests -PASS meter.accessKey: 32 tests -PASS meter.tabIndex: 24 tests -PASS meter.value: 8 tests -PASS meter.min: 8 tests -PASS meter.max: typeof IDL attribute -FAIL meter.max: IDL get with DOM attribute unset assert_equals: expected 0 but got 1 -PASS meter.max: 6 tests -PASS meter.low: 8 tests -PASS meter.high: typeof IDL attribute -FAIL meter.high: IDL get with DOM attribute unset assert_equals: expected 0 but got 1 -PASS meter.high: 6 tests -PASS meter.optimum: typeof IDL attribute -FAIL meter.optimum: IDL get with DOM attribute unset assert_equals: expected 0 but got 0.5 -PASS meter.optimum: 6 tests -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/reflection-metadata-expected.txt b/third_party/blink/web_tests/external/wpt/html/dom/reflection-metadata-expected.txt index 408ab6f..7cc499c 100644 --- a/third_party/blink/web_tests/external/wpt/html/dom/reflection-metadata-expected.txt +++ b/third_party/blink/web_tests/external/wpt/html/dom/reflection-metadata-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 2446 tests; 2365 PASS, 81 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 2445 tests; 2365 PASS, 80 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS head.title: 32 tests PASS head.lang: 32 tests PASS head.dir: 62 tests @@ -21,9 +21,7 @@ PASS base.hidden: 33 tests PASS base.accessKey: 32 tests PASS base.tabIndex: 24 tests -PASS base.href: typeof IDL attribute -FAIL base.href: IDL get with DOM attribute unset assert_equals: expected "" but got "http://web-platform.test:8001/html/dom/reflection-metadata.html" -PASS base.href: 18 tests +PASS base.href: 19 tests PASS base.target: 32 tests PASS link.title: 32 tests PASS link.lang: 32 tests
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/reflection.js b/third_party/blink/web_tests/external/wpt/html/dom/reflection.js index 9a98478..3f8d7c1e 100644 --- a/third_party/blink/web_tests/external/wpt/html/dom/reflection.js +++ b/third_party/blink/web_tests/external/wpt/html/dom/reflection.js
@@ -636,7 +636,7 @@ // Hard-coded special case defaultVal = domObj.ownerDocument.URL; } - if (defaultVal !== null || data.isNullable) { + if (!data.customGetter && (defaultVal !== null || data.isNullable)) { ReflectionHarness.test(function() { ReflectionHarness.assertEquals(idlObj[idlName], defaultVal); }, "IDL get with DOM attribute unset");
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resource-timing.https.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resource-timing.https.html index 123bbc8..7fc3fcd 100644 --- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resource-timing.https.html +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resource-timing.https.html
@@ -15,7 +15,7 @@ function verify(options) { const url = options.mode === 'cross-origin' ? crossOriginUrl(options.resource) : resourceUrl(options.resource); - const entryList = options.performance.getEntriesByName(url); + const entryList = options.performance.getEntriesByName(url, 'resource'); if (options.should_no_performance_entry) { // The performance timeline may not have an entry for a resource // which failed to load. @@ -137,7 +137,7 @@ test(() => { const url = resourceUrl('resources/test-helpers.sub.js'); - const entry = window.performance.getEntriesByName(url)[0]; + const entry = window.performance.getEntriesByName(url, 'resource')[0]; assert_equals(entry.workerStart, 0, 'Non-controlled'); }, 'Non-controlled resource loads');
diff --git a/third_party/blink/web_tests/external/wpt/web-nfc/nfc_hw_disabled-manual.https-expected.txt b/third_party/blink/web_tests/external/wpt/web-nfc/nfc_hw_disabled-manual.https-expected.txt new file mode 100644 index 0000000..104d42a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/web-nfc/nfc_hw_disabled-manual.https-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +FAIL NFCReader.start should fail if NFC HW is disabled. promise_test: Unhandled rejection with value: object "ReferenceError: NFCReader is not defined" +FAIL NFCWriter.push should fail when NFC HW is disabled. NFCWriter is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/web-nfc/nfc_hw_disabled-manual.https.html b/third_party/blink/web_tests/external/wpt/web-nfc/nfc_hw_disabled-manual.https.html index cd84961c..bb2cd42 100644 --- a/third_party/blink/web_tests/external/wpt/web-nfc/nfc_hw_disabled-manual.https.html +++ b/third_party/blink/web_tests/external/wpt/web-nfc/nfc_hw_disabled-manual.https.html
@@ -11,7 +11,7 @@ <h2>Precondition</h2> <ol> <li> - Disable the NFC Module. + Disable the NFC module or run test on a device without NFC module. </li> </ol> @@ -21,12 +21,17 @@ "use strict"; -promise_test(t => { - return promise_rejects(t, 'NotSupportedError', navigator.nfc.watch(noop)); -}, "Test that nfc.watch fails if NFC HW is disabled."); +promise_test(async t => { + const reader = new NFCReader(); + const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]); + reader.start(); + const event = await readerWatcher.wait_for("error"); + assert_equals(event.error.name, 'NotReadableError'); +}, "NFCReader.start should fail if NFC HW is disabled."); promise_test(t => { - return promise_rejects(t, 'NotSupportedError', navigator.nfc.push(test_text_data)); -}, "nfc.push should fail when NFC HW is disabled."); + const writer = new NFCWriter(); + return promise_rejects(t, 'NotReadableError', writer.push(test_text_data)); +}, "NFCWriter.push should fail when NFC HW is disabled."); </script>
diff --git a/third_party/blink/web_tests/fast/dom/HTMLElement/set-inner-outer-optimization.html b/third_party/blink/web_tests/fast/dom/HTMLElement/set-inner-outer-optimization.html index 3c774041..016c0833 100644 --- a/third_party/blink/web_tests/fast/dom/HTMLElement/set-inner-outer-optimization.html +++ b/third_party/blink/web_tests/fast/dom/HTMLElement/set-inner-outer-optimization.html
@@ -99,8 +99,8 @@ runTest('', 'innerText', '<a></a><b></b>', 'modified'); runTest('text', 'innerText', '', 'modified'); - runTest('text', 'innerText', 'different text', 'modified, with same first child'); - runTest('text', 'innerText', 'text', 'modified, with same first child'); + runTest('text', 'innerText', 'different text', 'modified'); + runTest('text', 'innerText', 'text', 'modified'); runTest('<a></a>', 'innerText', '', 'modified'); runTest('<a></a>', 'innerText', 'text', 'modified');
diff --git a/third_party/blink/web_tests/paint/invalidation/block-no-inflow-children.html b/third_party/blink/web_tests/paint/invalidation/block-no-inflow-children.html index 3be22ea..b604afe 100644 --- a/third_party/blink/web_tests/paint/invalidation/block-no-inflow-children.html +++ b/third_party/blink/web_tests/paint/invalidation/block-no-inflow-children.html
@@ -2,7 +2,7 @@ <script> function repaintTest() { - document.getElementById("target").innerText += " la"; + document.getElementById("target").firstChild.data += " la"; } </script> <script src="resources/text-based-repaint.js"></script>
diff --git a/third_party/blink/web_tests/paint/invalidation/position/layout-state-relative.html b/third_party/blink/web_tests/paint/invalidation/position/layout-state-relative.html index 284d5e1..16419ae2 100644 --- a/third_party/blink/web_tests/paint/invalidation/position/layout-state-relative.html +++ b/third_party/blink/web_tests/paint/invalidation/position/layout-state-relative.html
@@ -6,7 +6,7 @@ <script type="text/javascript"> function repaintTest() { - document.getElementById("target").innerText = "PASS"; + document.getElementById("target").firstChild.data = "PASS"; } </script> </head>
diff --git a/third_party/blink/web_tests/paint/invalidation/reflection/reflection-with-rotation.html b/third_party/blink/web_tests/paint/invalidation/reflection/reflection-with-rotation.html index fa2810c..5840c5e1 100644 --- a/third_party/blink/web_tests/paint/invalidation/reflection/reflection-with-rotation.html +++ b/third_party/blink/web_tests/paint/invalidation/reflection/reflection-with-rotation.html
@@ -6,7 +6,7 @@ <script type="text/javascript"> function repaintTest() { - document.getElementById("target").innerText = "PASS"; + document.getElementById("target").firstChild.data = "PASS"; } </script> <style type="text/css" media="screen">
diff --git a/third_party/blink/web_tests/paint/invalidation/scroll/layout-state-scrolloffset.html b/third_party/blink/web_tests/paint/invalidation/scroll/layout-state-scrolloffset.html index 26d1094..326ea3c 100644 --- a/third_party/blink/web_tests/paint/invalidation/scroll/layout-state-scrolloffset.html +++ b/third_party/blink/web_tests/paint/invalidation/scroll/layout-state-scrolloffset.html
@@ -16,7 +16,7 @@ parent.scrollLeft = 10; function repaintTest() { - document.getElementById('target').innerText = 'after'; + document.getElementById('target').firstChild.data = 'after'; } </script> </html>
diff --git a/third_party/blink/web_tests/paint/invalidation/scroll/layout-state-scrolloffset2.html b/third_party/blink/web_tests/paint/invalidation/scroll/layout-state-scrolloffset2.html index 30b3aa4..ed10369 100644 --- a/third_party/blink/web_tests/paint/invalidation/scroll/layout-state-scrolloffset2.html +++ b/third_party/blink/web_tests/paint/invalidation/scroll/layout-state-scrolloffset2.html
@@ -22,7 +22,7 @@ parent2.scrollLeft = 7; function repaintTest() { - document.getElementById('target').innerText = 'after' + document.getElementById('target').firstChild.data = 'after' } </script> </html>
diff --git a/third_party/blink/web_tests/paint/invalidation/scroll/layout-state-scrolloffset3.html b/third_party/blink/web_tests/paint/invalidation/scroll/layout-state-scrolloffset3.html index 242cb67..7d92c1d2 100644 --- a/third_party/blink/web_tests/paint/invalidation/scroll/layout-state-scrolloffset3.html +++ b/third_party/blink/web_tests/paint/invalidation/scroll/layout-state-scrolloffset3.html
@@ -16,7 +16,7 @@ parent.scrollLeft = 10; function repaintTest() { - document.getElementById('target').innerText = 'after'; + document.getElementById('target').firstChild.data = 'after'; } </script> </html>
diff --git a/third_party/blink/web_tests/paint/invalidation/scroll/line-in-scrolled-clipped-block.html b/third_party/blink/web_tests/paint/invalidation/scroll/line-in-scrolled-clipped-block.html index 60d6714..32223e8 100644 --- a/third_party/blink/web_tests/paint/invalidation/scroll/line-in-scrolled-clipped-block.html +++ b/third_party/blink/web_tests/paint/invalidation/scroll/line-in-scrolled-clipped-block.html
@@ -7,6 +7,6 @@ function repaintTest() { - target.innerText = " PASS ."; + target.firstChild.data = " PASS ."; } </script>
diff --git a/third_party/blink/web_tests/paint/invalidation/transform/transform-layout-repaint.html b/third_party/blink/web_tests/paint/invalidation/transform/transform-layout-repaint.html index 174d17a..dbee7284 100644 --- a/third_party/blink/web_tests/paint/invalidation/transform/transform-layout-repaint.html +++ b/third_party/blink/web_tests/paint/invalidation/transform/transform-layout-repaint.html
@@ -6,7 +6,7 @@ <script type="text/javascript"> function repaintTest() { - document.getElementById("target").innerText = "PASS"; + document.getElementById("target").firstChild.data = "PASS"; } </script> <style type="text/css" media="screen">
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 8594e74..6cb1c315 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -5285,7 +5285,9 @@ setter onresourcetimingbufferfull interface PerformanceElementTiming : PerformanceEntry attribute @@toStringTag + getter identifier getter intersectionRect + getter responseEnd method constructor method toJSON interface PerformanceEntry
diff --git a/third_party/freetype/BUILD.gn b/third_party/freetype/BUILD.gn index 4046a4b..0dcf7742 100644 --- a/third_party/freetype/BUILD.gn +++ b/third_party/freetype/BUILD.gn
@@ -61,6 +61,10 @@ defines = [] include_dirs = [] + # FreeType only exposes ft2build.h, all other FreeType headers are accessed by macro names. + # gn check does not expand macros, so list only this header. + public = [ "src/include/ft2build.h" ] + sources = [ "include/freetype-custom-config/ftconfig.h", "include/freetype-custom-config/ftmodule.h",
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index 318973e6..a0eeb6c2 100644 --- a/third_party/freetype/README.chromium +++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@ Name: FreeType URL: http://www.freetype.org/ -Version: VER-2-9-1-349 -Revision: 6d65c60fca0ebce88e2bcfeac92a7a791e03bf42 +Version: VER-2-9-1-351 +Revision: 31757f969fba60d75404f31e8f1168bef5011770 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses" License File: src/docs/FTL.TXT
diff --git a/third_party/ink/README.chromium b/third_party/ink/README.chromium index 314199e..405ce3c 100644 --- a/third_party/ink/README.chromium +++ b/third_party/ink/README.chromium
@@ -1,7 +1,7 @@ Name: Google Ink Short Name: ink URL: https://github.com/google/ink -Version: 233314166 +Version: 236729529 License: Apache 2.0 Security Critical: yes
diff --git a/third_party/ink/build/ink_lib_binary.js.sha1 b/third_party/ink/build/ink_lib_binary.js.sha1 index 55ca656..d9f90f8 100644 --- a/third_party/ink/build/ink_lib_binary.js.sha1 +++ b/third_party/ink/build/ink_lib_binary.js.sha1
@@ -1 +1 @@ -36d392d7bec3d8550e40a947c0db29b40e19d60b \ No newline at end of file +b64c8e4dbec4b01a3aa0cd4a0b7fd37ff735fb72 \ No newline at end of file
diff --git a/third_party/ink/build/ink_lib_externs.js.sha1 b/third_party/ink/build/ink_lib_externs.js.sha1 index 26f1cfff..f68aa91 100644 --- a/third_party/ink/build/ink_lib_externs.js.sha1 +++ b/third_party/ink/build/ink_lib_externs.js.sha1
@@ -1 +1 @@ -b866a5dbc00ee771cf56ed08cc78015cef160758 \ No newline at end of file +90f553cbf55aa906cdd43c4b27dc3d5ef9e75ebb \ No newline at end of file
diff --git a/third_party/ink/build/wasm-threads/glcore_base.js.mem.sha1 b/third_party/ink/build/wasm-threads/glcore_base.js.mem.sha1 new file mode 100644 index 0000000..6aaf19f --- /dev/null +++ b/third_party/ink/build/wasm-threads/glcore_base.js.mem.sha1
@@ -0,0 +1 @@ +d346855d34df6a757683494be06cad9aac8e1a01 \ No newline at end of file
diff --git a/third_party/ink/build/wasm-threads/glcore_base.js.sha1 b/third_party/ink/build/wasm-threads/glcore_base.js.sha1 new file mode 100644 index 0000000..cb76fe4 --- /dev/null +++ b/third_party/ink/build/wasm-threads/glcore_base.js.sha1
@@ -0,0 +1 @@ +4d8f1d787a8c0f496b733c7578824cf6e0608840 \ No newline at end of file
diff --git a/third_party/ink/build/wasm-threads/glcore_base.wasm.sha1 b/third_party/ink/build/wasm-threads/glcore_base.wasm.sha1 new file mode 100644 index 0000000..714e08a --- /dev/null +++ b/third_party/ink/build/wasm-threads/glcore_base.wasm.sha1
@@ -0,0 +1 @@ +3e0eaa76ec1238f9cd1cecf7808d700cd9a84924 \ No newline at end of file
diff --git a/third_party/ink/build/wasm-threads/glcore_wasm_bootstrap_compiled.js.sha1 b/third_party/ink/build/wasm-threads/glcore_wasm_bootstrap_compiled.js.sha1 new file mode 100644 index 0000000..67c5116 --- /dev/null +++ b/third_party/ink/build/wasm-threads/glcore_wasm_bootstrap_compiled.js.sha1
@@ -0,0 +1 @@ +4ab63d6214d411e2b096d5d0f3a072d0c9332201 \ No newline at end of file
diff --git a/third_party/ink/build/wasm-threads/pthread-main.js.sha1 b/third_party/ink/build/wasm-threads/pthread-main.js.sha1 new file mode 100644 index 0000000..1e5ae02a --- /dev/null +++ b/third_party/ink/build/wasm-threads/pthread-main.js.sha1
@@ -0,0 +1 @@ +89f47a099c85e412a4dc1755c8f01deef42e4713 \ No newline at end of file
diff --git a/third_party/ink/build/wasm/glcore_base.js.sha1 b/third_party/ink/build/wasm/glcore_base.js.sha1 index dbc150f2..8c62ba4 100644 --- a/third_party/ink/build/wasm/glcore_base.js.sha1 +++ b/third_party/ink/build/wasm/glcore_base.js.sha1
@@ -1 +1 @@ -529bc90cbda84c1c1ea684f3b74203932e6897da \ No newline at end of file +c8b78d6f7b0b9639cf05f68100568f54024bd621 \ No newline at end of file
diff --git a/third_party/ink/build/wasm/glcore_base.wasm.sha1 b/third_party/ink/build/wasm/glcore_base.wasm.sha1 index 9278463..68dc8071 100644 --- a/third_party/ink/build/wasm/glcore_base.wasm.sha1 +++ b/third_party/ink/build/wasm/glcore_base.wasm.sha1
@@ -1 +1 @@ -a27172fe2f09c9c5c194219754beb0e7433f6264 \ No newline at end of file +5310afd49946994abbf109c77d06831143d7f623 \ No newline at end of file
diff --git a/third_party/ink/build/wasm/glcore_wasm_bootstrap_compiled.js.sha1 b/third_party/ink/build/wasm/glcore_wasm_bootstrap_compiled.js.sha1 index 5a7db281..4d72bb83 100644 --- a/third_party/ink/build/wasm/glcore_wasm_bootstrap_compiled.js.sha1 +++ b/third_party/ink/build/wasm/glcore_wasm_bootstrap_compiled.js.sha1
@@ -1 +1 @@ -c742f9bc02eeb6189d07d7acb893af6ec7c0f49e \ No newline at end of file +49ed90d6ccc69b214c88fe99c43700099ef00bdb \ No newline at end of file
diff --git a/tools/metrics/histograms/OWNERS b/tools/metrics/histograms/OWNERS index 98dfc58d..70ef08f 100644 --- a/tools/metrics/histograms/OWNERS +++ b/tools/metrics/histograms/OWNERS
@@ -8,6 +8,7 @@ per-file histograms.xml=csharrison@chromium.org per-file histograms.xml=cthomp@chromium.org # For security-related metrics only. per-file histograms.xml=schenney@chromium.org +per-file histograms.xml=tbansal@chromium.org per-file histograms.xml=set noparent
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 4c5e61c..06f8fa3d 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -31082,6 +31082,7 @@ <int value="-1869845022" label="force-show-update-menu-item"/> <int value="-1869432243" label="GoogleBrandedContextMenu:disabled"/> <int value="-1868978829" label="spurious-power-button-accel-count"/> + <int value="-1868957045" label="SyncUSSAutofillWalletMetadata:enabled"/> <int value="-1868284723" label="DirectManipulationStylus:disabled"/> <int value="-1867382602" label="WebRTC-H264WithOpenH264FFmpeg:enabled"/> <int value="-1867342522" label="MaterialDesignHistory:enabled"/> @@ -31636,6 +31637,7 @@ label="OmniboxSpeculativeServiceWorkerStartOnQueryInput:disabled"/> <int value="-989671895" label="OfflineIndicatorAlwaysHttpProbe:enabled"/> <int value="-984052166" label="DoodlesOnLocalNtp:enabled"/> + <int value="-981237342" label="SyncUSSAutofillWalletMetadata:disabled"/> <int value="-980260493" label="NTPSnippets:disabled"/> <int value="-979313250" label="enable-google-branded-context-menu"/> <int value="-979057409" label="enable-seccomp-filter-sandbox"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 7fd239bd..1c518a28 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -78377,6 +78377,119 @@ </summary> </histogram> +<histogram + name="PageLoad.Clients.AMP.Experimental.PageTiming.InputToNavigation.Subframe" + units="ms"> + <owner>bmcquade@chromium.org</owner> + <summary> + The time from the user input that triggers the top-level navigation for an + AMP document to the time that the navigation for the AMP document is + initiated in the AMP frame. This gives insight into how often AMP documents + are navigated to via same document navigations without being prerendered. + </summary> +</histogram> + +<histogram + name="PageLoad.Clients.AMP.Experimental.PageTiming.MainFrameToSubFrameNavigationDelta.Subframe" + units="ms"> + <owner>bmcquade@chromium.org</owner> + <summary> + The time from the main frame navigation to the subsequent subframe + navigation for the AMP document. Only recorded for non-same-page + navigations. + </summary> +</histogram> + +<histogram + name="PageLoad.Clients.AMP.Experimental.PageTiming.NavigationToInput.Subframe" + units="ms"> + <owner>bmcquade@chromium.org</owner> + <summary> + The time from navigation in the AMP frame to the user input that triggers + the top-level navigation for that AMP document. This gives insight into the + delta between when an AMP frame is prerendered and when it is actually + displayed for same document navigations. + </summary> +</histogram> + +<histogram + name="PageLoad.Clients.AMP.InteractiveTiming.FirstInputDelay3.Subframe" + units="ms"> + <owner>bmcquade@chromium.org</owner> + <summary> + Measures First Input Delay, the duration between the hardware timestamp and + the start of event processing on the main thread for the first meaningful + input per navigation, in an AMP subframe document. Recorded on first page + interaction. See https://goo.gl/tr1oTZ for a detailed explanation. Excludes + scrolls. Only same-document navigations are included. + </summary> +</histogram> + +<histogram + name="PageLoad.Clients.AMP.InteractiveTiming.FirstInputDelay3.Subframe.FullNavigation" + units="ms"> + <owner>bmcquade@chromium.org</owner> + <summary> + Measures First Input Delay, the duration between the hardware timestamp and + the start of event processing on the main thread for the first meaningful + input per navigation, in an AMP subframe document. Recorded on first page + interaction. See https://goo.gl/tr1oTZ for a detailed explanation. Excludes + scrolls. Only non-same-document navigations are included. + </summary> +</histogram> + +<histogram + name="PageLoad.Clients.AMP.PaintTiming.InputToFirstContentfulPaint.Subframe" + units="ms"> + <owner>bmcquade@chromium.org</owner> + <summary> + The time from user input to first "contentful" paint in an AMP + subframe document. Will be zero or near-zero in cases where the AMP subframe + document was prerendered. Only same-document navigations are included. + </summary> +</histogram> + +<histogram + name="PageLoad.Clients.AMP.PaintTiming.InputToFirstContentfulPaint.Subframe.FullNavigation" + units="ms"> + <owner>bmcquade@chromium.org</owner> + <summary> + The time from user input to first "contentful" paint in an AMP + subframe document. Only non-same-document navigations are included. + </summary> +</histogram> + +<histogram + name="PageLoad.Clients.AMP.PaintTiming.InputToLargestContentPaint.Subframe" + units="ms"> + <owner>bmcquade@chromium.org</owner> + <summary> + The time from user input to largest "contentful" paint in an AMP + subframe document. Only same-document navigations are included. + + Excludes any content painted after user input. The value is recorded at the + end of each page load unless there is an abort or user input before text or + image paint. See http://bit.ly/fcp_plus_plus for details. + + Will be zero or near-zero in cases where the AMP subframe document was + prerendered. + </summary> +</histogram> + +<histogram + name="PageLoad.Clients.AMP.PaintTiming.InputToLargestContentPaint.Subframe.FullNavigation" + units="ms"> + <owner>bmcquade@chromium.org</owner> + <summary> + The time from user input to largest "contentful" paint in an AMP + subframe document. Only non-same-document navigations are included. + + Excludes any content painted after user input. The value is recorded at the + end of each page load unless there is an abort or user input before text or + image paint. See http://bit.ly/fcp_plus_plus for details. + </summary> +</histogram> + <histogram name="PageLoad.Clients.AMP.SameDocumentView" enum="PageLoadMetricsAMPViewType"> <owner>bmcquade@chromium.org</owner>
diff --git a/tools/perf/cli_tools/update_wpr/update_wpr.py b/tools/perf/cli_tools/update_wpr/update_wpr.py index 6727857..2f8d00e 100644 --- a/tools/perf/cli_tools/update_wpr/update_wpr.py +++ b/tools/perf/cli_tools/update_wpr/update_wpr.py
@@ -9,10 +9,13 @@ import datetime import json import os +import random import re import shutil import subprocess import tempfile +import time +import webbrowser from core import cli_helpers from core import path_util @@ -24,7 +27,7 @@ SRC_ROOT = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..')) + os.path.join(os.path.dirname(__file__), '..', '..', '..', '..')) RESULTS2JSON = os.path.join( SRC_ROOT, 'third_party', 'catapult', 'tracing', 'bin', 'results2json') HISTOGRAM2CSV = os.path.join( @@ -35,6 +38,41 @@ DEFAULT_REVIEWERS = ['perezju@chromium.org'] +def _GetBranchName(): + return subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD']) + + +def _OpenBrowser(url): + # Redirect I/O before invoking browser to avoid it spamming our output. + # Based on https://stackoverflow.com/a/2323563. + savout = os.dup(1) + saverr = os.dup(2) + os.close(1) + os.close(2) + os.open(os.devnull, os.O_RDWR) + try: + webbrowser.open(url) + finally: + os.dup2(savout, 1) + os.dup2(saverr, 2) + + +def _SendCLForReview(comment): + subprocess.check_call( + ['git', 'cl', 'comments', '--publish', '--add-comment', comment]) + + +def _EnsureEditor(): + if 'EDITOR' not in os.environ: + os.environ['EDITOR'] = cli_helpers.Prompt( + 'Looks like EDITOR environment varible is not defined. Please enter ' + 'the command to view logs: ') + + +def _OpenEditor(filepath): + subprocess.check_call([os.environ['EDITOR'], filepath]) + + class WprUpdater(object): def __init__(self, args): self.story = args.story @@ -226,6 +264,48 @@ with open(output_file, 'r') as output_fd: return json.load(output_fd)['issue_url'] + def _CreateBranch(self): + sanitized_story = re.sub(r'[^A-Za-z0-9-_.]', r'-', self.story) + subprocess.check_call([ + 'git', 'new-branch', + 'update-wpr-%s-%d' % (sanitized_story, random.randint(0, 10000)), + ]) + + def _FilterLogForDiff(self, log_filename): + """Removes unimportant details from console logs for cleaner diffs. + + For example, log line from file `log_filename` + + 2018-02-01 22:23:22,123 operation abcdef01-abcd-abcd-0123-abcdef012345 + from /tmp/tmpX34v/results.html took 22145ms when accessed via + https://127.0.0.1:1233/endpoint + + would become + + <timestamp> operation <guid> from /tmp/tmp<random>/results.html took + <duration> when accessed via https://127.0.0.1:<port>/endpoint + + Returns: + Path to the filtered log. + """ + with open(log_filename) as src, tempfile.NamedTemporaryFile( + suffix='diff', dir=self.output_dir, delete=False) as dest: + for line in src: + # Remove timestamps. + line = re.sub( + r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3}', r'<timestamp>', line) + # Remove GUIDs. + line = re.sub( + r'[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}', r'<guid>', line) + # Remove random letters in paths to temp dirs and files. + line = re.sub(r'(/tmp/tmp)[^/\s]+', r'\1<random>', line) + # Remove random port in localhost URLs. + line = re.sub(r'(://127.0.0.1:)\d+', r'\1<port>', line) + # Remove random durations in ms. + line = re.sub(r'\d+ ms', r'<duration>', line) + dest.write(line) + return dest.name + def _StartPinpointJob(self, configuration): """Creates, starts a Pinpoint job and returns its URL.""" try: @@ -328,6 +408,153 @@ job_urls.append(job_url) return job_urls, failed_configs + def AutoRun(self): + # Let the quest begin... + cli_helpers.Comment( + 'This script will help you update the recording of a story. It will go ' + 'through the following stages, which you can also invoke manually via ' + 'subcommand specified in parentheses:') + cli_helpers.Comment(' - help create a new branch if needed') + cli_helpers.Comment(' - run story with live network connection (live)') + cli_helpers.Comment(' - record story (record)') + cli_helpers.Comment(' - replay the recording (replay)') + cli_helpers.Comment(' - upload the recording to Google Storage (upload)') + cli_helpers.Comment( + ' - upload CL with updated recording reference (review)') + cli_helpers.Comment(' - trigger pinpoint tryjobs (pinpoint)') + cli_helpers.Comment(' - post links to these jobs on the CL') + cli_helpers.Comment( + 'Note that you can always enter prefix of the answer to any of the ' + 'questions asked below, e.g. "y" for "yes" or "j" for "just-replay".') + + # TODO(sergiyb): Detect if benchmark is not implemented and try to add it + # automatically by copying the same benchmark without :<current-year> suffix + # and changing name of the test, name of the benchmark and the year tag. + + # Create branch if needed. + reuse_cl = False + branch = _GetBranchName() + if branch == 'HEAD': + cli_helpers.Comment('You are not on a branch.') + if not cli_helpers.Ask( + 'Should script create a new branch automatically?'): + cli_helpers.Comment( + 'Please create a new branch and start this script again') + return + self._CreateBranch() + else: + issue = self._GetBranchIssueUrl() + if issue is not None: + issue_message = 'with an associated issue: %s' % issue + else: + issue_message = 'without an associated issue' + cli_helpers.Comment( + 'You are on a branch {branch} {issue_message}. Please commit or ' + 'stash any changes unrelated to the updated story before ' + 'proceeding.', branch=branch, issue_message=issue_message) + ans = cli_helpers.Ask( + 'Should the script create a new branch automatically, reuse ' + 'existing one or exit?', answers=['create', 'reuse', 'exit'], + default='create') + if ans == 'create': + self._CreateBranch() + elif ans == 'reuse': + reuse_cl = issue is not None + elif ans == 'exit': + return + + # Live run. + live_out_file = self.LiveRun() + cli_helpers.Comment( + 'Please inspect the live run results above for any errors.') + ans = None + while ans != 'continue': + ans = cli_helpers.Ask( + 'Should I continue with recording, view metric results in a browser, ' + 'view stdout/stderr output or stop?', + ['continue', 'metrics', 'output', 'stop'], default='continue') + if ans == 'stop': + cli_helpers.Comment( + 'Please update the story class to resolve the observed issues and ' + 'then run this script again.') + return + elif ans == 'metrics': + _OpenBrowser('file://%s.results.html' % live_out_file) + elif ans == 'output': + _OpenEditor(live_out_file) + + # Record & replay. + action = 'record' + while action != 'continue': + if action == 'record': + self.RecordWpr() + if action in ['record', 'just-replay']: + replay_out_file = self.ReplayWpr() + cli_helpers.Comment( + 'Check that the console:error:all metrics above have low values ' + 'and are similar to the live run above.') + if action == 'diff': + diff_path = os.path.join(self.output_dir, 'live_replay.diff') + with open(diff_path, 'w') as diff_file: + subprocess.call([ + 'diff', '--color', self._FilterLogForDiff(live_out_file), + self._FilterLogForDiff(replay_out_file)], stdout=diff_file) + _OpenEditor(diff_path) + if action == 'stop': + return + action = cli_helpers.Ask( + 'Should I record and replay again, just replay, continue with ' + 'uploading CL, stop and exit, or would you prefer to see diff ' + 'between live/replay console logs?', + ['record', 'just-replay', 'continue', 'stop', 'diff'], + default='continue') + + # Upload WPR and create a WIP CL for the new story. + if not self.UploadWpr(): + return + while self.UploadCL(short_description=reuse_cl) != 0: + if not cli_helpers.Ask('Upload failed. Should I try again?'): + return + + # Gerrit needs some time to sync its backends, hence we sleep here for 5 + # seconds. Otherwise, pinpoint app may get an answer that the CL that we've + # just uploaded does not exist yet. + cli_helpers.Comment( + 'Waiting 20 seconds for the Gerrit backends to sync, so that Pinpoint ' + 'app can detect the newly-created CL.') + time.sleep(20) + + # Trigger pinpoint jobs. + configs_to_trigger = None + job_urls = [] + while True: + new_job_urls, configs_to_trigger = self.StartPinpointJobs( + configs_to_trigger) + job_urls.extend(new_job_urls) + if not configs_to_trigger or not cli_helpers.Ask( + 'Do you want to try triggering the failed configs again?'): + break + + if configs_to_trigger: + if not cli_helpers.Ask( + 'Some jobs failed to trigger. Do you still want to send created ' + 'CL for review?', default='no'): + return + + # Post a link to the triggered jobs, publish CL for review and open it. + _SendCLForReview( + 'Started the following Pinpoint jobs:\n%s' % + '\n'.join(' - %s' % url for url in job_urls)) + cli_helpers.Comment( + 'Posted a message with Pinpoint job URLs on the CL and sent it for ' + 'review. Opening the CL in a browser...') + _OpenBrowser(self._GetBranchIssueUrl()) + + # Hooray, you won! :-) + cli_helpers.Comment( + 'Thank you, you have successfully updated the recording for %s. Please ' + 'wait for LGTM and land the created CL.' % self.story) + def Main(argv): parser = argparse.ArgumentParser() @@ -351,15 +578,27 @@ '--binary', default=None, help='Path to the Chromium/Chrome binary relative to output directory. ' 'Defaults to default Chrome browser installed if not specified.') - parser.add_argument( - 'command', choices=[ - 'live', 'record', 'replay', 'upload', 'review', 'pinpoint'], - help='Mode in which to run this script.') + + subparsers = parser.add_subparsers( + title='Mode in which to run this script', dest='command') + subparsers.add_parser( + 'auto', help='interactive mode automating updating a recording') + subparsers.add_parser('live', help='run story on a live website') + subparsers.add_parser('record', help='record story from a live website') + subparsers.add_parser('replay', help='replay story from the recording') + subparsers.add_parser('upload', help='upload recording to the Google Storage') + subparsers.add_parser('review', help='create a CL with updated recording') + subparsers.add_parser( + 'pinpoint', help='trigger Pinpoint jobs to test the recording') args = parser.parse_args(argv) updater = WprUpdater(args) - if args.command =='live': + if args.command == 'auto': + _EnsureEditor() + luci_auth.CheckLoggedIn() + updater.AutoRun() + elif args.command =='live': updater.LiveRun() elif args.command == 'record': updater.RecordWpr()
diff --git a/tools/perf/cli_tools/update_wpr/update_wpr_unittest.py b/tools/perf/cli_tools/update_wpr/update_wpr_unittest.py index 934d7ed..65a82bf 100644 --- a/tools/perf/cli_tools/update_wpr/update_wpr_unittest.py +++ b/tools/perf/cli_tools/update_wpr/update_wpr_unittest.py
@@ -35,6 +35,7 @@ datetime.now.return_value.strftime.return_value = '<tstamp>' mock.patch('tempfile.mkdtemp', return_value='/tmp/dir').start() + mock.patch('random.randint', return_value=1234).start() mock.patch('core.cli_helpers.Fatal').start() mock.patch('core.cli_helpers.Error').start() mock.patch('core.cli_helpers.Step').start() @@ -47,6 +48,7 @@ mock.patch(WPR_UPDATER + 'RECORD_WPR', '.../record_wpr').start() mock.patch('os.path.join', lambda *parts: '/'.join(parts)).start() mock.patch('os.path.exists', return_value=True).start() + mock.patch('time.sleep').start() self.wpr_updater = update_wpr.WprUpdater(argparse.Namespace( story='<story>', device_id=None, repeat=1, binary=None, bug_id=None, @@ -58,13 +60,13 @@ def testMain(self): wpr_updater_cls = mock.patch(WPR_UPDATER + 'WprUpdater').start() update_wpr.Main([ - 'live', '-s', 'foo:bar:story:2019', '-d', 'H2345234FC33', '--binary', '<binary>', '-b', '1234', '-r', 'test_user1@chromium.org', '-r', 'test_user2@chromium.org', + 'live', ]) self.assertListEqual(wpr_updater_cls.mock_calls, [ mock.call(argparse.Namespace( @@ -90,6 +92,83 @@ self.wpr_updater.Cleanup() rmtree.assert_called_once_with('/tmp/dir', ignore_errors=True) + def testGetBranchName(self): + self._check_output.return_value = 'master' + self.assertEqual(update_wpr._GetBranchName(), 'master') + self._check_output.assert_called_once_with( + ['git', 'rev-parse', '--abbrev-ref', 'HEAD']) + + def testCreateBranch(self): + self.wpr_updater._CreateBranch() + self._check_call.assert_called_once_with( + ['git', 'new-branch', 'update-wpr--story--1234']) + + def testSendCLForReview(self): + update_wpr._SendCLForReview('comment') + self._check_call.assert_called_once_with( + ['git', 'cl', 'comments', '--publish', '--add-comment', 'comment']) + + @mock.patch('os.dup') + @mock.patch('os.close') + @mock.patch('os.dup2') + @mock.patch('webbrowser.open') + def testOpenBrowser(self, webbrowser_open, os_dup2, os_close, os_dup): + del os_dup2, os_close, os_dup # unused + update_wpr._OpenBrowser('<url>') + webbrowser_open.assert_called_once_with('<url>') + + def testAutoRun(self): + # Mock low-level methods tested above. + mock.patch(WPR_UPDATER + '_GetBranchName', return_value='HEAD').start() + mock.patch( + WPR_UPDATER + 'WprUpdater._GetBranchIssueUrl', + return_value='<issue-url>').start() + mock.patch(WPR_UPDATER + 'WprUpdater._CreateBranch').start() + send_cl_for_review = mock.patch(WPR_UPDATER + '_SendCLForReview').start() + open_browser = mock.patch(WPR_UPDATER + '_OpenBrowser').start() + + # Mock high-level methods tested below. + live_run = mock.patch(WPR_UPDATER + 'WprUpdater.LiveRun').start() + record_wpr = mock.patch(WPR_UPDATER + 'WprUpdater.RecordWpr').start() + replay_wpr = mock.patch(WPR_UPDATER + 'WprUpdater.ReplayWpr').start() + upload_wpr = mock.patch( + WPR_UPDATER + 'WprUpdater.UploadWpr', return_value=True).start() + upload_cl = mock.patch( + WPR_UPDATER + 'WprUpdater.UploadCL', return_value=0).start() + start_pinpoint_jobs = mock.patch( + WPR_UPDATER + 'WprUpdater.StartPinpointJobs', + return_value=(['<url1>', '<url2>', '<url3>'], [])).start() + + # Mock user interaction. + mock.patch('core.cli_helpers.Ask', side_effect=[ + True, # Should script create a new branch automatically? + 'continue', # Should I continue with recording, ...? + 'continue', # Should I record and replay again, ...? + ]).start() + + self.wpr_updater.AutoRun() + + # Run once to make sure story works. + live_run.assert_called_once_with() + # Run again to create a recording. + record_wpr.assert_called_once_with() + # Replay to verify the recording. + replay_wpr.assert_called_once_with() + # Upload the recording. + upload_wpr.assert_called_once_with() + # Upload the CL. + upload_cl.assert_called_once_with(short_description=False) + # Start pinpoint jobs to verify recording works on the bots. + start_pinpoint_jobs.assert_called_once_with(None) + # Send CL for review with a comment listing triggered Pinpoint jobs. + send_cl_for_review.assert_called_once_with( + 'Started the following Pinpoint jobs:\n' + ' - <url1>\n' + ' - <url2>\n' + ' - <url3>') + # Open the CL in browser, + open_browser.assert_called_once_with('<issue-url>') + def testLiveRun(self): run_benchmark = mock.patch( WPR_UPDATER + 'WprUpdater._RunSystemHealthMemoryBenchmark',
diff --git a/tools/perf/core/cli_helpers.py b/tools/perf/core/cli_helpers.py index 54d2cdd..b184c51 100644 --- a/tools/perf/core/cli_helpers.py +++ b/tools/perf/core/cli_helpers.py
@@ -137,6 +137,15 @@ ', '.join(choices[:-1]), choices[-1])) +def Prompt(question, accept_empty=False): + while True: + print(Colored(question, color='cyan')) + answer = raw_input().strip() + if answer or accept_empty: + return answer + Error('Please enter non-empty answer') + + def CheckLog(command, log_path, env=None): """Executes a command and writes its stdout to a specified log file.
diff --git a/tools/perf/core/cli_helpers_unittest.py b/tools/perf/core/cli_helpers_unittest.py index 36a07dc6..61a041fb 100644 --- a/tools/perf/core/cli_helpers_unittest.py +++ b/tools/perf/core/cli_helpers_unittest.py
@@ -11,6 +11,8 @@ from telemetry import decorators +# https://crbug.com/938487 +@decorators.Disabled('all') class CLIHelpersTest(unittest.TestCase): def testUnsupportedColor(self): with self.assertRaises(AssertionError): @@ -50,8 +52,6 @@ @mock.patch('__builtin__.print') @mock.patch('__builtin__.raw_input') - # https://crbug.com/938575. - @decorators.Disabled('chromeos') def testAskAgainOnInvalidAnswer(self, raw_input_mock, print_mock): raw_input_mock.side_effect = ['foobar', 'y'] self.assertTrue(cli_helpers.Ask('Ready?')) @@ -63,8 +63,6 @@ @mock.patch('__builtin__.print') @mock.patch('__builtin__.raw_input') - # https://crbug.com/938575. - @decorators.Disabled('chromeos') def testAskWithCustomAnswersAndDefault(self, raw_input_mock, print_mock): raw_input_mock.side_effect = [''] self.assertFalse( @@ -74,8 +72,6 @@ @mock.patch('__builtin__.print') @mock.patch('__builtin__.raw_input') - # https://crbug.com/938575. - @decorators.Disabled('chromeos') def testAskNoDefaultCustomAnswersAsList(self, raw_input_mock, print_mock): raw_input_mock.side_effect = ['', 'FoO'] self.assertEqual(cli_helpers.Ask('Ready?', ['foo', 'bar']), 'foo') @@ -85,8 +81,6 @@ mock.call('\033[96mReady? [foo/bar] \033[0m', end=' ') ]) - # https://crbug.com/937654. - @decorators.Disabled('android', 'chromeos') def testAskWithInvalidDefaultAnswer(self): with self.assertRaises(ValueError): cli_helpers.Ask('Ready?', ['foo', 'bar'], 'baz') @@ -158,6 +152,16 @@ with self.assertRaises(ValueError): cli_helpers.Run('cmd with args') + @mock.patch('__builtin__.print') + @mock.patch('__builtin__.raw_input') + def testPrompt(self, raw_input_mock, print_mock): + raw_input_mock.side_effect = ['', '42'] + self.assertEqual(cli_helpers.Prompt( + 'What is the ultimate meaning of life, universe and everything?'), '42') + self.assertEqual(raw_input_mock.call_count, 2) + self.assertEqual(print_mock.call_count, 3) + + if __name__ == "__main__": unittest.main()
diff --git a/ui/file_manager/integration_tests/file_manager/background.js b/ui/file_manager/integration_tests/file_manager/background.js index c635458b..1fc3e3e 100644 --- a/ui/file_manager/integration_tests/file_manager/background.js +++ b/ui/file_manager/integration_tests/file_manager/background.js
@@ -452,3 +452,20 @@ await remoteCall.waitForElement( appId, `.tree-item[label="${directoryName}"]`); } + +/** + * Expands a tree item by clicking on its expand icon. + * + * @param {string} appId Files app windowId. + * @param {string} treeItem Query to the tree item that should be expanded. + * @return {Promise} Promise fulfilled on success. + */ +async function expandTreeItem(appId, treeItem) { + const expandIcon = treeItem + '> .tree-row[has-children=true] > .expand-icon'; + await remoteCall.waitForElement(appId, expandIcon); + chrome.test.assertTrue(await remoteCall.callRemoteTestUtil( + 'fakeMouseClick', appId, [expandIcon])); + + const expandedSubtree = treeItem + '> .tree-children[expanded]'; + await remoteCall.waitForElement(appId, expandedSubtree); +}
diff --git a/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js b/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js index ef5fabb..74d58b1 100644 --- a/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js +++ b/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js
@@ -204,6 +204,7 @@ 'focus failed: #directory-tree'); // Right click desired item in the directory tree. + await remoteCall.waitForElement(appId, treeItemQuery); chrome.test.assertTrue( !!await remoteCall.callRemoteTestUtil( 'fakeMouseRightClick', appId, [treeItemQuery]), @@ -598,4 +599,169 @@ await checkContextMenu(appId, query, menus, true /* rootMenu */); }; +/** + * Tests context menu for MyFiles, Downloads and sub-folder. + */ +testcase.dirContextMenuMyFiles = async () => { + const myFilesMenus = [ + ['#share-with-linux', true], + ]; + const downloadsMenus = [ + ['#share-with-linux', true], + ['#new-folder', true], + ]; + const photosMenus = [ + ['#cut', true], + ['#copy', true], + ['#paste-into-folder', false], + ['#share-with-linux', true], + ['#rename', true], + ['#delete', true], + ['#new-folder', true], + ]; + const myFilesQuery = '#directory-tree [entry-label="My files"]'; + const downloadsQuery = '#directory-tree [entry-label="Downloads"]'; + const photosQuery = + '#directory-tree [full-path-for-testing="/Downloads/photos"]'; + + // Open Files app on local Downloads. + const appId = await setupAndWaitUntilReady( + RootPath.DOWNLOADS, [ENTRIES.beautiful, ENTRIES.photos], []); + + // Check the context menu is on desired state for MyFiles. + await checkContextMenu( + appId, myFilesQuery, myFilesMenus, true /* rootMenu */); + + // Check the context menu for MyFiles>Downloads. + await checkContextMenu( + appId, downloadsQuery, downloadsMenus, false /* rootMenu */); + + // Expand Downloads to display photos folder. + await expandTreeItem(appId, downloadsQuery); + + // Check the context menu for MyFiles>Downloads>photos. + await checkContextMenu(appId, photosQuery, photosMenus, false /* rootMenu */); +}; + +/** + * Tests context menu for Crostini real root. + * TODO(lucmult): Check menus for a crostini folder. + */ +testcase.dirContextMenuCrostini = async () => { + const linuxMenus = [ + ['#new-folder', true], + ]; + const linuxQuery = '#directory-tree [entry-label="Linux files"]'; + + // Open Files app on local Downloads. + const appId = await setupAndWaitUntilReady( + RootPath.DOWNLOADS, [ENTRIES.beautiful], []); + + // Select Crostini, because the first right click doesn't show any context + // menu, just actually mounts crostini converting the tree item from fake to + // real root. + chrome.test.assertTrue( + !!await remoteCall.callRemoteTestUtil( + 'fakeMouseClick', appId, [linuxQuery]), + 'fakeMouseClick failed'); + + // Wait for the real root to appear. + await remoteCall.waitForElement( + appId, + '#directory-tree ' + + '[dir-type="SubDirectoryItem"][entry-label="Linux files"]'); + + // Check the context menu for Linux files. + await checkContextMenu(appId, linuxQuery, linuxMenus, false /* rootMenu */); +}; + +/** + * Tests context menu for ARC++/Play files root. + * TODO(lucmult): Check menus for a Play folder. + */ +testcase.dirContextMenuPlayFiles = async () => { + const playFilesMenus = [ + ['#share-with-linux', true], + ['#new-folder', false], + ]; + const playFilesQuery = '#directory-tree [entry-label="Play files"]'; + + // Open Files app on local Downloads. + const appId = await setupAndWaitUntilReady( + RootPath.DOWNLOADS, [ENTRIES.beautiful], []); + + // Check the context menu for Play files. + await checkContextMenu( + appId, playFilesQuery, playFilesMenus, false /* rootMenu */); +}; + +/** + * Tests context menu for USB root (single and multiple partitions). + * TODO(lucmult): Check menus for a USB folder. + */ +testcase.dirContextMenuUsbs = async () => { + const singleUsbMenus = [ + ['#unmount', true], + ['#format', true], + ['#rename', false], + ['#share-with-linux', true], + ]; + const partitionsRootMenus = [ + ['#unmount', true], + ['#format', false], + ['#share-with-linux', true], + ]; + const partition1Menus = [ + ['#share-with-linux', true], + ['#rename', false], + ['#new-folder', true], + ]; + + const singleUsbQuery = '#directory-tree [entry-label="fake-usb"]'; + const partitionsRootQuery = '#directory-tree [entry-label="Drive Label"]'; + const partition1Query = '#directory-tree [entry-label="partition-1"]'; + + // Mount removable volumes. + await sendTestMessage({name: 'mountUsbWithPartitions'}); + await sendTestMessage({name: 'mountFakeUsb'}); + + // Open Files app on local Downloads. + const appId = + await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.beautiful], []); + + // Check the context menu for single partition USB. + await checkContextMenu( + appId, singleUsbQuery, singleUsbMenus, true /* rootMenu */); + + // Check the context menu for multiple partitions USB (root). + await checkContextMenu( + appId, partitionsRootQuery, partitionsRootMenus, true /* rootMenu */); + + // Check the context menu for multiple partitions USB (actual partition). + await checkContextMenu( + appId, partition1Query, partition1Menus, false /* rootMenu */); +}; + +/** + * Tests context menu for FSP root. + * TODO(lucmult): Check menus for a FSP. + */ +testcase.dirContextMenuFsp = async () => { + const fspMenus = [ + ['#unmount', true], + ]; + const fspQuery = '#directory-tree [entry-label="Test (1)"]'; + + // Install a FSP. + const manifest = 'manifest_source_file.json'; + await sendTestMessage({name: 'launchProviderExtension', manifest: manifest}); + + // Open Files app on local Downloads. + const appId = + await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.beautiful], []); + + // Check the context menu for FSP. + await checkContextMenu(appId, fspQuery, fspMenus, true /* rootMenu */); +}; + })();
diff --git a/ui/file_manager/integration_tests/file_manager/folder_shortcuts.js b/ui/file_manager/integration_tests/file_manager/folder_shortcuts.js index 9e19d9d..e50a59f 100644 --- a/ui/file_manager/integration_tests/file_manager/folder_shortcuts.js +++ b/ui/file_manager/integration_tests/file_manager/folder_shortcuts.js
@@ -72,35 +72,16 @@ }; /** - * Expands a directory tree item by clicking on its expand icon. - * - * @param {string} appId Files app windowId. - * @param {Object} directory Directory whose tree item should be expanded. - * @return {Promise} Promise fulfilled on success. - */ -async function expandTreeItem(appId, directory) { - const expandIcon = - directory.treeItem + '> .tree-row[has-children=true] > .expand-icon'; - await remoteCall.waitForElement(appId, expandIcon); - chrome.test.assertTrue(await remoteCall.callRemoteTestUtil( - 'fakeMouseClick', appId, [expandIcon])); - - - const expandedSubtree = directory.treeItem + '> .tree-children[expanded]'; - await remoteCall.waitForElement(appId, expandedSubtree); -} - -/** * Expands whole directory tree under DIRECTORY.Drive. * * @param {string} appId Files app windowId. * @return {Promise} Promise fulfilled on success. */ async function expandDirectoryTree(appId) { - await expandTreeItem(appId, DIRECTORY.Drive); - await expandTreeItem(appId, DIRECTORY.A); - await expandTreeItem(appId, DIRECTORY.B); - await expandTreeItem(appId, DIRECTORY.D); + await expandTreeItem(appId, DIRECTORY.Drive.treeItem); + await expandTreeItem(appId, DIRECTORY.A.treeItem); + await expandTreeItem(appId, DIRECTORY.B.treeItem); + await expandTreeItem(appId, DIRECTORY.D.treeItem); } /**
diff --git a/ui/gfx/image/image.cc b/ui/gfx/image/image.cc index 8e2b0d9..d7237707 100644 --- a/ui/gfx/image/image.cc +++ b/ui/gfx/image/image.cc
@@ -148,11 +148,8 @@ class ImageRepSkia : public ImageRep { public: - // Takes ownership of |image|. - explicit ImageRepSkia(ImageSkia* image) - : ImageRep(Image::kImageRepSkia), - image_(image) { - } + explicit ImageRepSkia(std::unique_ptr<ImageSkia> image) + : ImageRep(Image::kImageRepSkia), image_(std::move(image)) {} ~ImageRepSkia() override {} @@ -345,8 +342,8 @@ Image::Image(const ImageSkia& image) { if (!image.isNull()) { storage_ = new internal::ImageStorage(Image::kImageRepSkia); - AddRepresentation( - std::make_unique<internal::ImageRepSkia>(new ImageSkia(image))); + AddRepresentation(std::make_unique<internal::ImageRepSkia>( + std::make_unique<ImageSkia>(image))); } } @@ -425,16 +422,16 @@ const internal::ImageRepCocoaTouch* native_rep = GetRepresentation(kImageRepCocoaTouch, true) ->AsImageRepCocoaTouch(); - scoped_rep.reset(new internal::ImageRepSkia( - new ImageSkia(ImageSkiaFromUIImage(native_rep->image())))); + scoped_rep.reset(new internal::ImageRepSkia(std::make_unique<ImageSkia>( + ImageSkiaFromUIImage(native_rep->image())))); break; } #elif defined(OS_MACOSX) case kImageRepCocoa: { const internal::ImageRepCocoa* native_rep = GetRepresentation(kImageRepCocoa, true)->AsImageRepCocoa(); - scoped_rep.reset(new internal::ImageRepSkia( - new ImageSkia(ImageSkiaFromNSImage(native_rep->image())))); + scoped_rep.reset(new internal::ImageRepSkia(std::make_unique<ImageSkia>( + ImageSkiaFromNSImage(native_rep->image())))); break; } #endif
diff --git a/ui/gfx/image/image_generic.cc b/ui/gfx/image/image_generic.cc index ad77df1..9d90008 100644 --- a/ui/gfx/image/image_generic.cc +++ b/ui/gfx/image/image_generic.cc
@@ -4,6 +4,7 @@ #include "ui/gfx/image/image_platform.h" +#include <memory> #include <set> #include <utility> @@ -16,12 +17,11 @@ namespace { // Returns a 16x16 red image to visually show error in decoding PNG. -// Caller takes ownership of returned ImageSkia. -ImageSkia* GetErrorImageSkia() { +std::unique_ptr<ImageSkia> GetErrorImageSkia() { SkBitmap bitmap; bitmap.allocN32Pixels(16, 16); bitmap.eraseARGB(0xff, 0xff, 0, 0); - return new ImageSkia(ImageSkiaRep(bitmap, 1.0f)); + return std::make_unique<ImageSkia>(ImageSkiaRep(bitmap, 1.0f)); } class PNGImageSource : public ImageSkiaSource { @@ -90,7 +90,8 @@ } // namespace -ImageSkia* ImageSkiaFromPNG(const std::vector<ImagePNGRep>& image_png_reps) { +std::unique_ptr<ImageSkia> ImageSkiaFromPNG( + const std::vector<ImagePNGRep>& image_png_reps) { if (image_png_reps.empty()) return GetErrorImageSkia(); std::unique_ptr<PNGImageSource> image_source(new PNGImageSource); @@ -103,7 +104,7 @@ DCHECK(!size.IsEmpty()); if (size.IsEmpty()) return GetErrorImageSkia(); - return new ImageSkia(std::move(image_source), size); + return std::make_unique<ImageSkia>(std::move(image_source), size); } scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
diff --git a/ui/gfx/image/image_ios.mm b/ui/gfx/image/image_ios.mm index 4b1c67c..1272728 100644 --- a/ui/gfx/image/image_ios.mm +++ b/ui/gfx/image/image_ios.mm
@@ -109,11 +109,11 @@ return Get1xPNGBytesFromUIImage(image); } -ImageSkia* ImageSkiaFromPNG( +std::unique_ptr<ImageSkia> ImageSkiaFromPNG( const std::vector<gfx::ImagePNGRep>& image_png_reps) { // iOS does not expose libpng, so conversion from PNG to ImageSkia must go // through UIImage. - gfx::ImageSkia* image_skia = new gfx::ImageSkia(); + auto image_skia = std::make_unique<gfx::ImageSkia>(); for (size_t i = 0; i < image_png_reps.size(); ++i) { base::scoped_nsobject<UIImage> uiimage( CreateUIImageFromImagePNGRep(image_png_reps[i]));
diff --git a/ui/gfx/image/image_platform.h b/ui/gfx/image/image_platform.h index 117d2624e..6eeebe3 100644 --- a/ui/gfx/image/image_platform.h +++ b/ui/gfx/image/image_platform.h
@@ -11,6 +11,7 @@ #ifndef UI_GFX_IMAGE_IMAGE_PLATFORM_H_ #define UI_GFX_IMAGE_IMAGE_PLATFORM_H_ +#include <memory> #include <vector> #include "base/memory/ref_counted.h" @@ -45,7 +46,8 @@ gfx::Size NSImageSize(NSImage* image); #endif // defined(OS_MACOSX) -ImageSkia* ImageSkiaFromPNG(const std::vector<ImagePNGRep>& image_png_reps); +std::unique_ptr<ImageSkia> ImageSkiaFromPNG( + const std::vector<ImagePNGRep>& image_png_reps); scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia( const ImageSkia* image_skia);
diff --git a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc index acf10353..175f0b6 100644 --- a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc +++ b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
@@ -103,6 +103,12 @@ frame->presentation_callback = std::move(presentation_callback); unsubmitted_frames_.push_back(std::make_unique<PendingFrame>()); + if (!use_egl_fence_sync_) { + frame->ready = true; + SubmitFrame(); + return; + } + // TODO: the following should be replaced by a per surface flush as it gets // implemented in GL drivers. EGLSyncKHR fence = InsertFence(has_implicit_external_sync_); @@ -156,6 +162,10 @@ return config_; } +void GbmSurfacelessWayland::SetRelyOnImplicitSync() { + use_egl_fence_sync_ = false; +} + GbmSurfacelessWayland::~GbmSurfacelessWayland() { surface_factory_->UnregisterSurface(widget_); }
diff --git a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h index 89be735..6870debb 100644 --- a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h +++ b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h
@@ -53,6 +53,7 @@ SwapCompletionCallback completion_callback, PresentationCallback presentation_callback) override; EGLConfig GetConfig() override; + void SetRelyOnImplicitSync() override; private: ~GbmSurfacelessWayland() override; @@ -95,6 +96,7 @@ std::unique_ptr<PendingFrame> submitted_frame_; bool has_implicit_external_sync_; bool last_swap_buffers_result_ = true; + bool use_egl_fence_sync_ = true; base::WeakPtrFactory<GbmSurfacelessWayland> weak_factory_;
diff --git a/ui/views/controls/label_perftest.cc b/ui/views/controls/label_perftest.cc index bd0094d..e8b5c59 100644 --- a/ui/views/controls/label_perftest.cc +++ b/ui/views/controls/label_perftest.cc
@@ -5,7 +5,7 @@ #include "ui/views/controls/label.h" #include "base/strings/utf_string_conversions.h" -#include "cc/base/lap_timer.h" +#include "base/timer/lap_timer.h" #include "testing/perf/perf_test.h" #include "ui/views/test/views_test_base.h" @@ -28,7 +28,7 @@ // The time limit is unused. Use kLaps for the check interval so the time is // only measured once. - cc::LapTimer timer(kWarmupLaps, base::TimeDelta(), kLaps); + base::LapTimer timer(kWarmupLaps, base::TimeDelta(), kLaps); for (int i = 0; i < kLaps + kWarmupLaps; ++i) { label.SetText(i % 2 == 0 ? string1 : string2); label.GetPreferredSize();