diff --git a/DEPS b/DEPS index a86196f..d6cdcdb4 100644 --- a/DEPS +++ b/DEPS
@@ -44,7 +44,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'c637865d5cb133882ef8c9b7eec4a6dca22dc4d5', + 'v8_revision': 'd2c38959a71552b4e39e4d9ee3a7cae2c84e5843', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other.
diff --git a/base/logging.h b/base/logging.h index b1075a4..8e448aba 100644 --- a/base/logging.h +++ b/base/logging.h
@@ -496,9 +496,60 @@ std::string* message_; }; -// Crashes in the fastest, simplest possible way with no attempt at logging. +// Crashes in the fastest possible way with no attempt at logging. +// There are different constraints to satisfy here, see http://crbug.com/664209 +// for more context: +// - The trap instructions, and hence the PC value at crash time, have to be +// distinct and not get folded into the same opcode by the compiler. +// On Linux/Android this is tricky because GCC still folds identical +// asm volatile blocks. The workaround is generating distinct opcodes for +// each CHECK using the __COUNTER__ macro. +// - The debug info for the trap instruction has to be attributed to the source +// line that has the CHECK(), to make crash reports actionable. This rules +// out the ability of using a inline function, at least as long as clang +// doesn't support attribute(artificial). +// - Failed CHECKs should produce a signal that is distinguishable from an +// invalid memory access, to improve the actionability of crash reports. +// - The compiler should treat the CHECK as no-return instructions, so that the +// trap code can be efficiently packed in the prologue of the function and +// doesn't interfere with the main execution flow. +// - When debugging, developers shouldn't be able to accidentally step over a +// CHECK. This is achieved by putting opcodes that will cause a non +// continuable exception after the actual trap instruction. +// - Don't cause too much binary bloat. #if defined(COMPILER_GCC) -#define IMMEDIATE_CRASH() __builtin_trap() + +#if defined(ARCH_CPU_X86_FAMILY) && !defined(OS_NACL) +// int 3 will generate a SIGTRAP. +#define TRAP_SEQUENCE() \ + asm volatile( \ + "int3; ud2; push %0;" ::"i"(static_cast<unsigned char>(__COUNTER__))) + +#elif defined(ARCH_CPU_ARMEL) && !defined(OS_NACL) +// bkpt will generate a SIGBUS when running on armv7 and a SIGTRAP when running +// as a 32 bit userspace app on arm64. There doesn't seem to be any way to +// cause a SIGTRAP from userspace without using a syscall (which would be a +// problem for sandboxing). +#define TRAP_SEQUENCE() \ + asm volatile("bkpt #0; udf %0;" ::"i"(__COUNTER__ % 256)) + +#elif defined(ARCH_CPU_ARM64) && !defined(OS_NACL) +// This will always generate a SIGTRAP on arm64. +#define TRAP_SEQUENCE() \ + asm volatile("brk #0; hlt %0;" ::"i"(__COUNTER__ % 65536)) + +#else +// Crash report accuracy will not be guaranteed on other architectures, but at +// least this will crash as expected. +#define TRAP_SEQUENCE() __builtin_trap() +#endif // ARCH_CPU_* + +#define IMMEDIATE_CRASH() \ + ({ \ + TRAP_SEQUENCE(); \ + __builtin_unreachable(); \ + }) + #elif defined(COMPILER_MSVC) // Clang is cleverer about coalescing int3s, so we need to add a unique-ish
diff --git a/base/logging_unittest.cc b/base/logging_unittest.cc index 9fe718c..ac920515 100644 --- a/base/logging_unittest.cc +++ b/base/logging_unittest.cc
@@ -9,6 +9,16 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#if defined(OS_POSIX) +#include <signal.h> +#include <unistd.h> +#include "base/posix/eintr_wrapper.h" +#endif // OS_POSIX + +#if defined(OS_LINUX) || defined(OS_ANDROID) +#include <ucontext.h> +#endif + #if defined(OS_WIN) #include <excpt.h> #include <windows.h> @@ -246,7 +256,102 @@ EXPECT_NE(addr1, addr3); EXPECT_NE(addr2, addr3); } -#endif // OFFICIAL_BUILD && OS_WIN + +#elif defined(OS_POSIX) && !defined(OS_NACL) && \ + (defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY)) + +int g_child_crash_pipe; + +void CheckCrashTestSighandler(int, siginfo_t* info, void* context_ptr) { + // Conversely to what clearly stated in "man 2 sigaction", some Linux kernels + // do NOT populate the |info->si_addr| in the case of a SIGTRAP. Hence we + // need the arch-specific boilerplate below, which is inspired by breakpad. + // At the same time, on OSX, ucontext.h is deprecated but si_addr works fine. + uintptr_t crash_addr = 0; +#if defined(OS_MACOSX) + crash_addr = reinterpret_cast<uintptr_t>(info->si_addr); +#else // OS_POSIX && !OS_MACOSX + struct ucontext* context = reinterpret_cast<struct ucontext*>(context_ptr); +#if defined(ARCH_CPU_X86) + crash_addr = static_cast<uintptr_t>(context->uc_mcontext.gregs[REG_EIP]); +#elif defined(ARCH_CPU_X86_64) + crash_addr = static_cast<uintptr_t>(context->uc_mcontext.gregs[REG_RIP]); +#elif defined(ARCH_CPU_ARMEL) + crash_addr = static_cast<uintptr_t>(context->uc_mcontext.arm_pc); +#elif defined(ARCH_CPU_ARM64) + crash_addr = static_cast<uintptr_t>(context->uc_mcontext.pc); +#endif // ARCH_* +#endif // OS_POSIX && !OS_MACOSX + HANDLE_EINTR(write(g_child_crash_pipe, &crash_addr, sizeof(uintptr_t))); + _exit(0); +} + +// CHECK causes a direct crash (without jumping to another function) only in +// official builds. Unfortunately, continuous test coverage on official builds +// is lower. DO_CHECK here falls back on a home-brewed implementation in +// non-official builds, to catch regressions earlier in the CQ. +#if defined(OFFICIAL_BUILD) +#define DO_CHECK CHECK +#else +#define DO_CHECK(cond) \ + if (!(cond)) \ + IMMEDIATE_CRASH() +#endif + +void CrashChildMain(int death_location) { + struct sigaction act = {}; + act.sa_sigaction = CheckCrashTestSighandler; + act.sa_flags = SA_SIGINFO; + ASSERT_EQ(0, sigaction(SIGTRAP, &act, NULL)); + ASSERT_EQ(0, sigaction(SIGBUS, &act, NULL)); + ASSERT_EQ(0, sigaction(SIGILL, &act, NULL)); + DO_CHECK(death_location != 1); + DO_CHECK(death_location != 2); + printf("\n"); + DO_CHECK(death_location != 3); + + // Should never reach this point. + const uintptr_t failed = 0; + HANDLE_EINTR(write(g_child_crash_pipe, &failed, sizeof(uintptr_t))); +}; + +void SpawnChildAndCrash(int death_location, uintptr_t* child_crash_addr) { + int pipefd[2]; + ASSERT_EQ(0, pipe(pipefd)); + + int pid = fork(); + ASSERT_GE(pid, 0); + + if (pid == 0) { // child process. + close(pipefd[0]); // Close reader (parent) end. + g_child_crash_pipe = pipefd[1]; + CrashChildMain(death_location); + FAIL() << "The child process was supposed to crash. It didn't."; + } + + close(pipefd[1]); // Close writer (child) end. + DCHECK(child_crash_addr); + int res = HANDLE_EINTR(read(pipefd[0], child_crash_addr, sizeof(uintptr_t))); + ASSERT_EQ(static_cast<int>(sizeof(uintptr_t)), res); +} + +TEST_F(LoggingTest, CheckCausesDistinctBreakpoints) { + uintptr_t child_crash_addr_1 = 0; + uintptr_t child_crash_addr_2 = 0; + uintptr_t child_crash_addr_3 = 0; + + SpawnChildAndCrash(1, &child_crash_addr_1); + SpawnChildAndCrash(2, &child_crash_addr_2); + SpawnChildAndCrash(3, &child_crash_addr_3); + + ASSERT_NE(0u, child_crash_addr_1); + ASSERT_NE(0u, child_crash_addr_2); + ASSERT_NE(0u, child_crash_addr_3); + ASSERT_NE(child_crash_addr_1, child_crash_addr_2); + ASSERT_NE(child_crash_addr_1, child_crash_addr_3); + ASSERT_NE(child_crash_addr_2, child_crash_addr_3); +} +#endif // OS_POSIX TEST_F(LoggingTest, DebugLoggingReleaseBehavior) { #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAAccountChangeListener.java b/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAAccountChangeListener.java index a9fc25986..12bc7c1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAAccountChangeListener.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAAccountChangeListener.java
@@ -57,6 +57,17 @@ return sInstance; } + /** + * Returns whether the permission {@link ACCOUNT_UPDATE_BROADCAST_PERMISSION} is granted by the + * system. + */ + static boolean holdsAccountUpdatePermission() { + Context context = ContextUtils.getApplicationContext(); + int result = ApiCompatibilityUtils.checkPermission( + context, ACCOUNT_UPDATE_BROADCAST_PERMISSION, Process.myPid(), Process.myUid()); + return result == PackageManager.PERMISSION_GRANTED; + } + private GSAAccountChangeListener(Context context) { Context applicationContext = context.getApplicationContext(); BroadcastReceiver accountChangeReceiver = new BroadcastReceiver() { @@ -123,12 +134,12 @@ // is not the same one as GSA's, then the broadcasts will never arrive. // Query the package manager to know whether the permission was granted, and // only switch to the broadcast mechanism if that's the case. - if (ApiCompatibilityUtils.checkPermission(context, - ACCOUNT_UPDATE_BROADCAST_PERMISSION, Process.myPid(), - Process.myUid()) - == PackageManager.PERMISSION_GRANTED) { - notifyGsaBroadcastsAccountChanges(); - } + // + // Note that this is technically not required, since Chrome tells GSA whether + // it holds the permission when connecting to it in GSAServiceClient, but this + // extra bit of paranoia protects from old versions of GSA that don't check + // what Chrome sends. + if (holdsAccountUpdatePermission()) notifyGsaBroadcastsAccountChanges(); } // If GSA doesn't support the broadcast, we connect several times to the service per
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAServiceClient.java b/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAServiceClient.java index 6983bca..34ad75aa7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAServiceClient.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAServiceClient.java
@@ -49,6 +49,8 @@ public static final String KEY_GSA_STATE = "ssb_service:ssb_state"; public static final String KEY_GSA_CONTEXT = "ssb_service:ssb_context"; public static final String KEY_GSA_PACKAGE_NAME = "ssb_service:ssb_package_name"; + public static final String KEY_GSA_SUPPORTS_BROADCAST = + "ssb_service:chrome_holds_account_update_permission"; @VisibleForTesting static final int INVALID_PSS = -1; @@ -241,9 +243,11 @@ null, REQUEST_REGISTER_CLIENT); registerClientMessage.replyTo = mMessenger; Bundle b = mGsaHelper.getBundleForRegisteringGSAClient(mContext); + if (b == null) b = new Bundle(); + b.putString(KEY_GSA_PACKAGE_NAME, mContext.getPackageName()); + b.putBoolean(KEY_GSA_SUPPORTS_BROADCAST, + GSAAccountChangeListener.holdsAccountUpdatePermission()); registerClientMessage.setData(b); - registerClientMessage.getData().putString( - KEY_GSA_PACKAGE_NAME, mContext.getPackageName()); mService.send(registerClientMessage); // Send prepare overlay message if there is a pending GSA context. } catch (RemoteException e) {
diff --git a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc index 04f44b5..32e04b8 100644 --- a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc +++ b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
@@ -24,6 +24,7 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host.h" #include "net/base/load_flags.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_fetcher.h" #include "net/url_request/url_request_context_getter.h" #include "url/gurl.h" @@ -251,7 +252,31 @@ for (Observer& observer : observers_) observer.OnHunspellDictionaryDownloadBegin(language_); - fetcher_ = net::URLFetcher::Create(url, net::URLFetcher::GET, this); + net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("spellcheck_hunspell_dictionary", R"( + semantics { + sender: "Spellcheck Dictionary Downloader" + description: + "When user selects a new language for spell checking in Google " + "Chrome, a new dictionary is downloaded for it." + trigger: "User selects a new language for spell checking." + data: + "The spell checking language identifier. No user identifier is " + "sent." + destination: GOOGLE_OWNED_SERVICE + } + policy { + cookies_allowed: false + setting: + "You can prevent downloading dictionaries by not selecting 'Use " + "this language for spell checking.' in Chrome's settings under " + "Lanugagues -> 'Language and input settings...'." + policy_exception_justification: + "Not implemented, considered not useful." + })"); + + fetcher_ = net::URLFetcher::Create(url, net::URLFetcher::GET, this, + traffic_annotation); data_use_measurement::DataUseUserData::AttachToFetcher( fetcher_.get(), data_use_measurement::DataUseUserData::SPELL_CHECKER); fetcher_->SetRequestContext(request_context_getter_);
diff --git a/chrome/browser/ui/search/local_ntp_browsertest.cc b/chrome/browser/ui/search/local_ntp_browsertest.cc index c80828b..5eb8f0df 100644 --- a/chrome/browser/ui/search/local_ntp_browsertest.cc +++ b/chrome/browser/ui/search/local_ntp_browsertest.cc
@@ -6,6 +6,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/search/search.h" +#include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/search/instant_test_utils.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/pref_names.h" @@ -20,6 +21,7 @@ #include "content/public/browser/notification_service.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" +#include "content/public/test/test_navigation_observer.h" #include "content/public/test/test_utils.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "ui/base/resource/resource_bundle.h" @@ -32,6 +34,8 @@ public: LocalNTPTest() {} + GURL other_url() { return https_test_server().GetURL("/simple.html"); } + protected: void SetUpInProcessBrowserTestFixture() override { ASSERT_TRUE(https_test_server().Start()); @@ -62,6 +66,63 @@ EXPECT_TRUE(success); } +IN_PROC_BROWSER_TEST_F(LocalNTPTest, EmbeddedSearchAPIOnlyAvailableOnNTP) { + ASSERT_NO_FATAL_FAILURE(SetupInstant(browser())); + FocusOmnibox(); + + // Open an NTP. + ui_test_utils::NavigateToURLWithDisposition( + browser(), ntp_url(), WindowOpenDisposition::NEW_FOREGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB | + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); + content::WebContents* active_tab = + browser()->tab_strip_model()->GetActiveWebContents(); + ASSERT_TRUE(search::IsInstantNTP(active_tab)); + // Check that the embeddedSearch API is available. + bool result = false; + ASSERT_TRUE( + GetBoolFromJS(active_tab, "!!window.chrome.embeddedSearch", &result)); + EXPECT_TRUE(result); + + // Navigate somewhere else in the same tab. + ui_test_utils::NavigateToURLWithDisposition( + browser(), other_url(), WindowOpenDisposition::CURRENT_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); + ASSERT_FALSE(search::IsInstantNTP(active_tab)); + // Now the embeddedSearch API should have gone away. + ASSERT_TRUE( + GetBoolFromJS(active_tab, "!!window.chrome.embeddedSearch", &result)); + EXPECT_FALSE(result); + + // Navigate back to the NTP. + content::TestNavigationObserver back_observer(active_tab); + chrome::GoBack(browser(), WindowOpenDisposition::CURRENT_TAB); + back_observer.Wait(); + // The API should be back. + ASSERT_TRUE( + GetBoolFromJS(active_tab, "!!window.chrome.embeddedSearch", &result)); + EXPECT_TRUE(result); + + // Navigate forward to the non-NTP page. + content::TestNavigationObserver fwd_observer(active_tab); + chrome::GoForward(browser(), WindowOpenDisposition::CURRENT_TAB); + fwd_observer.Wait(); + // The API should be gone. + ASSERT_TRUE( + GetBoolFromJS(active_tab, "!!window.chrome.embeddedSearch", &result)); + EXPECT_FALSE(result); + + // Navigate to a new NTP instance. + ui_test_utils::NavigateToURLWithDisposition( + browser(), ntp_url(), WindowOpenDisposition::CURRENT_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); + ASSERT_TRUE(search::IsInstantNTP(active_tab)); + // Now the API should be available again. + ASSERT_TRUE( + GetBoolFromJS(active_tab, "!!window.chrome.embeddedSearch", &result)); + EXPECT_TRUE(result); +} + IN_PROC_BROWSER_TEST_F(LocalNTPTest, FakeboxRedirectsToOmnibox) { ASSERT_NO_FATAL_FAILURE(SetupInstant(browser())); FocusOmnibox();
diff --git a/components/ntp_snippets/remote/remote_suggestions_fetcher.cc b/components/ntp_snippets/remote/remote_suggestions_fetcher.cc index eb423601..211ffa8 100644 --- a/components/ntp_snippets/remote/remote_suggestions_fetcher.cc +++ b/components/ntp_snippets/remote/remote_suggestions_fetcher.cc
@@ -272,8 +272,7 @@ request_throttler_active_suggestions_consumer_( pref_service, RequestThrottler::RequestType:: - CONTENT_SUGGESTION_FETCHER_ACTIVE_SUGGESTIONS_CONSUMER), - weak_ptr_factory_(this) {} + CONTENT_SUGGESTION_FETCHER_ACTIVE_SUGGESTIONS_CONSUMER) {} RemoteSuggestionsFetcher::~RemoteSuggestionsFetcher() { if (waiting_for_refresh_token_) {
diff --git a/components/ntp_snippets/remote/remote_suggestions_fetcher.h b/components/ntp_snippets/remote/remote_suggestions_fetcher.h index a5f27c1..dc023dc7 100644 --- a/components/ntp_snippets/remote/remote_suggestions_fetcher.h +++ b/components/ntp_snippets/remote/remote_suggestions_fetcher.h
@@ -12,7 +12,6 @@ #include <vector> #include "base/callback.h" -#include "base/memory/weak_ptr.h" #include "base/optional.h" #include "base/time/clock.h" #include "base/time/tick_clock.h" @@ -209,8 +208,6 @@ std::string last_status_; std::string last_fetch_json_; - base::WeakPtrFactory<RemoteSuggestionsFetcher> weak_ptr_factory_; - DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsFetcher); };
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc index 629fc51..1f1b6e1 100644 --- a/content/browser/service_worker/embedded_worker_instance.cc +++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -866,10 +866,8 @@ void EmbeddedWorkerInstance::AddMessageToConsole( blink::WebConsoleMessage::Level level, const std::string& message) { - if (status_ != EmbeddedWorkerStatus::RUNNING && - status_ != EmbeddedWorkerStatus::STARTING) { + if (process_id() == ChildProcessHost::kInvalidUniqueID) return; - } DCHECK(client_.is_bound()); client_->AddMessageToConsole(level, message); }
diff --git a/content/browser/service_worker/embedded_worker_instance_unittest.cc b/content/browser/service_worker/embedded_worker_instance_unittest.cc index 55398ed9..f276f7cf 100644 --- a/content/browser/service_worker/embedded_worker_instance_unittest.cc +++ b/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -746,4 +746,75 @@ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[2].status); } +class StoreMessageInstanceClient + : public EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient { + public: + explicit StoreMessageInstanceClient( + base::WeakPtr<EmbeddedWorkerTestHelper> helper) + : EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient(helper) {} + + const std::vector<std::pair<blink::WebConsoleMessage::Level, std::string>>& + message() { + return messages_; + } + + private: + void AddMessageToConsole(blink::WebConsoleMessage::Level level, + const std::string& message) override { + messages_.push_back(std::make_pair(level, message)); + } + + std::vector<std::pair<blink::WebConsoleMessage::Level, std::string>> + messages_; +}; + +TEST_F(EmbeddedWorkerInstanceTest, AddMessageToConsole) { + const int64_t version_id = 55L; + const GURL pattern("http://example.com/"); + const GURL url("http://example.com/worker.js"); + std::unique_ptr<StoreMessageInstanceClient> instance_client = + base::MakeUnique<StoreMessageInstanceClient>(helper_->AsWeakPtr()); + StoreMessageInstanceClient* instance_client_rawptr = instance_client.get(); + helper_->RegisterMockInstanceClient(std::move(instance_client)); + ASSERT_EQ(mock_instance_clients()->size(), 1UL); + + std::unique_ptr<EmbeddedWorkerInstance> worker = + embedded_worker_registry()->CreateWorker(); + helper_->SimulateAddProcessToPattern(pattern, + helper_->mock_render_process_id()); + worker->AddListener(this); + + // Attempt to start the worker and immediate AddMessageToConsole should not + // cause a crash. + std::pair<blink::WebConsoleMessage::Level, std::string> test_message = + std::make_pair(blink::WebConsoleMessage::LevelVerbose, ""); + std::unique_ptr<EmbeddedWorkerStartParams> params = + CreateStartParams(version_id, pattern, url); + worker->Start(std::move(params), CreateEventDispatcher(), + base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); + worker->AddMessageToConsole(test_message.first, test_message.second); + base::RunLoop().RunUntilIdle(); + + // Messages sent before sending StartWorker message won't be dispatched. + ASSERT_EQ(0UL, instance_client_rawptr->message().size()); + ASSERT_EQ(3UL, events_.size()); + EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type); + EXPECT_EQ(START_WORKER_MESSAGE_SENT, events_[1].type); + EXPECT_EQ(STARTED, events_[2].type); + EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status()); + + worker->AddMessageToConsole(test_message.first, test_message.second); + base::RunLoop().RunUntilIdle(); + + // Messages sent after sending StartWorker message should be reached to + // the renderer. + ASSERT_EQ(1UL, instance_client_rawptr->message().size()); + EXPECT_EQ(test_message, instance_client_rawptr->message()[0]); + + // Ensure the worker is stopped. + worker->Stop(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status()); +} + } // namespace content
diff --git a/content/browser/service_worker/embedded_worker_registry.cc b/content/browser/service_worker/embedded_worker_registry.cc index fbc629d..88a24dd2 100644 --- a/content/browser/service_worker/embedded_worker_registry.cc +++ b/content/browser/service_worker/embedded_worker_registry.cc
@@ -11,6 +11,7 @@ #include "content/browser/service_worker/embedded_worker_instance.h" #include "content/browser/service_worker/service_worker_context_core.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" +#include "content/browser/service_worker/service_worker_dispatcher_host.h" #include "content/common/service_worker/embedded_worker_messages.h" #include "content/public/browser/browser_thread.h" #include "ipc/ipc_message.h" @@ -32,7 +33,6 @@ new EmbeddedWorkerRegistry( context, old_registry->next_embedded_worker_id_); - registry->process_sender_map_.swap(old_registry->process_sender_map_); return registry; } @@ -179,14 +179,7 @@ line_number, source_url); } -void EmbeddedWorkerRegistry::AddChildProcessSender(int process_id, - IPC::Sender* sender) { - process_sender_map_[process_id] = sender; - DCHECK(!base::ContainsKey(worker_process_map_, process_id)); -} - -void EmbeddedWorkerRegistry::RemoveChildProcessSender(int process_id) { - process_sender_map_.erase(process_id); +void EmbeddedWorkerRegistry::RemoveProcess(int process_id) { std::map<int, std::set<int> >::iterator found = worker_process_map_.find(process_id); if (found != worker_process_map_.end()) { @@ -196,10 +189,13 @@ ++it) { int embedded_worker_id = *it; DCHECK(base::ContainsKey(worker_map_, embedded_worker_id)); - // Somehow the worker thread has lost contact with the browser process. - // The renderer may have been killed. Set the worker's status to STOPPED - // so a new thread can be created for this version. Use OnDetached rather - // than OnStopped so UMA doesn't record it as a normal stoppage. + // RemoveProcess is typically called after the running workers on the + // process have been stopped, so if there is a running worker at this + // point somehow the worker thread has lost contact with the browser + // process. + // Set the worker's status to STOPPED so a new thread can be created for + // this version. Use OnDetached rather than OnStopped so UMA doesn't + // record it as a normal stoppage. worker_map_[embedded_worker_id]->OnDetached(); } worker_process_map_.erase(found); @@ -236,10 +232,6 @@ void EmbeddedWorkerRegistry::BindWorkerToProcess(int process_id, int embedded_worker_id) { - // The ServiceWorkerDispatcherHost is supposed to be created when the process - // is created, and keep an entry in process_sender_map_ for its whole - // lifetime. - DCHECK(base::ContainsKey(process_sender_map_, process_id)); DCHECK(GetWorker(embedded_worker_id)); DCHECK_EQ(GetWorker(embedded_worker_id)->process_id(), process_id); DCHECK( @@ -254,10 +246,10 @@ std::unique_ptr<IPC::Message> message(message_ptr); if (!context_) return SERVICE_WORKER_ERROR_ABORT; - ProcessToSenderMap::iterator found = process_sender_map_.find(process_id); - if (found == process_sender_map_.end()) + IPC::Sender* sender = context_->GetDispatcherHost(process_id); + if (!sender) return SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND; - if (!found->second->Send(message.release())) + if (!sender->Send(message.release())) return SERVICE_WORKER_ERROR_IPC_FAILED; return SERVICE_WORKER_OK; }
diff --git a/content/browser/service_worker/embedded_worker_registry.h b/content/browser/service_worker/embedded_worker_registry.h index 8561ce4..75b7666 100644 --- a/content/browser/service_worker/embedded_worker_registry.h +++ b/content/browser/service_worker/embedded_worker_registry.h
@@ -10,7 +10,6 @@ #include <set> #include <vector> -#include "base/callback_forward.h" #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -23,7 +22,6 @@ namespace IPC { class Message; -class Sender; } namespace content { @@ -39,8 +37,6 @@ class CONTENT_EXPORT EmbeddedWorkerRegistry : public NON_EXPORTED_BASE(base::RefCounted<EmbeddedWorkerRegistry>) { public: - typedef base::Callback<void(ServiceWorkerStatusCode)> StatusCallback; - static scoped_refptr<EmbeddedWorkerRegistry> Create( const base::WeakPtr<ServiceWorkerContextCore>& contxet); @@ -88,9 +84,13 @@ int line_number, const GURL& source_url); - // Keeps a map from process_id to sender information. - void AddChildProcessSender(int process_id, IPC::Sender* sender); - void RemoveChildProcessSender(int process_id); + // Removes information about the service workers running on the process and + // calls ServiceWorkerVersion::OnDetached() on each. Called when the process + // is terminated. Under normal operation, the workers should already have + // been stopped before the process is terminated, in which case this function + // does nothing. But in some cases the process can be terminated unexpectedly + // or the workers can fail to stop cleanly. + void RemoveProcess(int process_id); // Returns an embedded worker instance for given |embedded_worker_id|. EmbeddedWorkerInstance* GetWorker(int embedded_worker_id); @@ -107,7 +107,6 @@ RemoveWorkerInSharedProcess); using WorkerInstanceMap = std::map<int, EmbeddedWorkerInstance*>; - using ProcessToSenderMap = std::map<int, IPC::Sender*>; EmbeddedWorkerRegistry( const base::WeakPtr<ServiceWorkerContextCore>& context, @@ -136,7 +135,6 @@ base::WeakPtr<ServiceWorkerContextCore> context_; WorkerInstanceMap worker_map_; - ProcessToSenderMap process_sender_map_; // Map from process_id to embedded_worker_id. // This map only contains starting and running workers.
diff --git a/content/browser/service_worker/embedded_worker_test_helper.cc b/content/browser/service_worker/embedded_worker_test_helper.cc index 3c027df..c379c3a 100644 --- a/content/browser/service_worker/embedded_worker_test_helper.cc +++ b/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -20,6 +20,7 @@ #include "content/browser/service_worker/embedded_worker_status.h" #include "content/browser/service_worker/service_worker_context_core.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" +#include "content/browser/service_worker/service_worker_dispatcher_host.h" #include "content/common/service_worker/embedded_worker_messages.h" #include "content/common/service_worker/embedded_worker_start_params.h" #include "content/common/service_worker/service_worker_messages.h" @@ -36,6 +37,29 @@ namespace content { +namespace { + +class MockServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost { + public: + MockServiceWorkerDispatcherHost(int process_id, + ResourceContext* resource_context, + IPC::Sender* sender) + : ServiceWorkerDispatcherHost(process_id, resource_context), + sender_(sender) {} + + bool Send(IPC::Message* message) override { return sender_->Send(message); } + + protected: + ~MockServiceWorkerDispatcherHost() override {} + + private: + IPC::Sender* sender_; + + DISALLOW_COPY_AND_ASSIGN(MockServiceWorkerDispatcherHost); +}; + +} // namespace + EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient:: MockEmbeddedWorkerInstanceClient( base::WeakPtr<EmbeddedWorkerTestHelper> helper) @@ -219,7 +243,14 @@ base::ThreadTaskRunnerHandle::Get(), nullptr, nullptr); wrapper_->process_manager()->SetProcessIdForTest(mock_render_process_id()); wrapper_->process_manager()->SetNewProcessIdForTest(new_render_process_id()); - registry()->AddChildProcessSender(mock_render_process_id_, this); + + scoped_refptr<ServiceWorkerDispatcherHost> dispatcher_host( + new MockServiceWorkerDispatcherHost( + mock_render_process_id_, browser_context_->GetResourceContext(), + this)); + wrapper_->context()->AddDispatcherHost(mock_render_process_id_, + dispatcher_host.get()); + dispatcher_hosts_[mock_render_process_id_] = std::move(dispatcher_host); // Setup process level interface registry. render_process_interface_registry_ = @@ -235,7 +266,13 @@ void EmbeddedWorkerTestHelper::SimulateAddProcessToPattern(const GURL& pattern, int process_id) { - registry()->AddChildProcessSender(process_id, this); + if (!context()->GetDispatcherHost(process_id)) { + scoped_refptr<ServiceWorkerDispatcherHost> dispatcher_host( + new MockServiceWorkerDispatcherHost( + process_id, browser_context_->GetResourceContext(), this)); + wrapper_->context()->AddDispatcherHost(process_id, dispatcher_host.get()); + dispatcher_hosts_[process_id] = std::move(dispatcher_host); + } wrapper_->process_manager()->AddProcessReferenceToPattern(pattern, process_id); }
diff --git a/content/browser/service_worker/embedded_worker_test_helper.h b/content/browser/service_worker/embedded_worker_test_helper.h index 96dacef..9a8af65 100644 --- a/content/browser/service_worker/embedded_worker_test_helper.h +++ b/content/browser/service_worker/embedded_worker_test_helper.h
@@ -40,6 +40,7 @@ class MockRenderProcessHost; class ServiceWorkerContextCore; class ServiceWorkerContextWrapper; +class ServiceWorkerDispatcherHost; class TestBrowserContext; struct EmbeddedWorkerStartParams; struct PlatformNotificationData; @@ -297,6 +298,9 @@ int mock_render_process_id_; int new_mock_render_process_id_; + std::map<int /* process_id */, scoped_refptr<ServiceWorkerDispatcherHost>> + dispatcher_hosts_; + std::unique_ptr<service_manager::InterfaceRegistry> render_process_interface_registry_; std::unique_ptr<service_manager::InterfaceRegistry>
diff --git a/content/browser/service_worker/foreign_fetch_request_handler_unittest.cc b/content/browser/service_worker/foreign_fetch_request_handler_unittest.cc index 5727b00..1045db1 100644 --- a/content/browser/service_worker/foreign_fetch_request_handler_unittest.cc +++ b/content/browser/service_worker/foreign_fetch_request_handler_unittest.cc
@@ -68,27 +68,19 @@ const int64_t kRegistrationId = 0; const int64_t kVersionId = 0; helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath())); + + // Create a registration for the worker which has foreign fetch event + // handler. registration_ = new ServiceWorkerRegistration(kScope, kRegistrationId, context()->AsWeakPtr()); version_ = new ServiceWorkerVersion(registration_.get(), kResource1, kVersionId, context()->AsWeakPtr()); - version_->set_foreign_fetch_scopes({kScope}); - // An empty host. - std::unique_ptr<ServiceWorkerProviderHost> host( - new ServiceWorkerProviderHost( - helper_->mock_render_process_id(), MSG_ROUTING_NONE, - kMockProviderId, SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - context()->AsWeakPtr(), nullptr)); - host->SetDocumentUrl(GURL("https://host/scope/")); - provider_host_ = host->AsWeakPtr(); - context()->AddProviderHost(std::move(host)); - context()->storage()->LazyInitialize(base::Bind(&EmptyCallback)); base::RunLoop().RunUntilIdle(); + // Persist the registration data. std::vector<ServiceWorkerDatabase::ResourceRecord> records; records.push_back( ServiceWorkerDatabase::ResourceRecord(10, version_->script_url(), 100)); @@ -162,17 +154,30 @@ return ForeignFetchRequestHandler::GetHandler(request_.get()); } - void CreateServiceWorkerTypeProviderHost() { - std::unique_ptr<ServiceWorkerProviderHost> host( - new ServiceWorkerProviderHost( - helper_->mock_render_process_id(), MSG_ROUTING_NONE, - kMockProviderId, SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, - ServiceWorkerProviderHost::FrameSecurityLevel::UNINITIALIZED, - context()->AsWeakPtr(), nullptr)); + void CreateWindowTypeProviderHost() { + std::unique_ptr<ServiceWorkerProviderHost> host = + CreateProviderHostForWindow( + helper_->mock_render_process_id(), kMockProviderId, + true /* is_parent_frame_secure */, helper_->context()->AsWeakPtr()); + EXPECT_FALSE( + context()->GetProviderHost(host->process_id(), host->provider_id())); + host->SetDocumentUrl(GURL("https://host/scope/")); provider_host_ = host->AsWeakPtr(); - context()->RemoveProviderHost(host->process_id(), host->provider_id()); + context()->AddProviderHost(std::move(host)); + } + + void CreateServiceWorkerTypeProviderHost() { + std::unique_ptr<ServiceWorkerProviderHost> host = + CreateProviderHostForServiceWorkerContext( + helper_->mock_render_process_id(), kMockProviderId, + true /* is_parent_frame_secure */, helper_->context()->AsWeakPtr()); + EXPECT_FALSE( + context()->GetProviderHost(host->process_id(), host->provider_id())); + provider_host_ = host->AsWeakPtr(); context()->AddProviderHost(std::move(host)); + // Create another worker whose requests will be intercepted by the foreign + // fetch event handler. scoped_refptr<ServiceWorkerRegistration> registration = new ServiceWorkerRegistration(GURL("https://host/scope"), 1L, context()->AsWeakPtr()); @@ -236,6 +241,7 @@ }; TEST_F(ForeignFetchRequestHandlerTest, CheckOriginTrialToken_NoToken) { + CreateWindowTypeProviderHost(); EXPECT_TRUE(CheckOriginTrialToken(version())); std::unique_ptr<net::HttpResponseInfo> http_info( CreateTestHttpResponseInfo()); @@ -244,6 +250,7 @@ } TEST_F(ForeignFetchRequestHandlerTest, CheckOriginTrialToken_ValidToken) { + CreateWindowTypeProviderHost(); EXPECT_TRUE(CheckOriginTrialToken(version())); std::unique_ptr<net::HttpResponseInfo> http_info( CreateTestHttpResponseInfo()); @@ -263,6 +270,7 @@ } TEST_F(ForeignFetchRequestHandlerTest, CheckOriginTrialToken_InvalidToken) { + CreateWindowTypeProviderHost(); EXPECT_TRUE(CheckOriginTrialToken(version())); std::unique_ptr<net::HttpResponseInfo> http_info( CreateTestHttpResponseInfo()); @@ -281,6 +289,7 @@ } TEST_F(ForeignFetchRequestHandlerTest, CheckOriginTrialToken_ExpiredToken) { + CreateWindowTypeProviderHost(); EXPECT_TRUE(CheckOriginTrialToken(version())); std::unique_ptr<net::HttpResponseInfo> http_info( CreateTestHttpResponseInfo()); @@ -299,11 +308,13 @@ } TEST_F(ForeignFetchRequestHandlerTest, InitializeHandler_Success) { + CreateWindowTypeProviderHost(); EXPECT_TRUE(InitializeHandler(kValidUrl, RESOURCE_TYPE_IMAGE, nullptr /* initiator */)); } TEST_F(ForeignFetchRequestHandlerTest, InitializeHandler_WrongResourceType) { + CreateWindowTypeProviderHost(); EXPECT_FALSE(InitializeHandler(kValidUrl, RESOURCE_TYPE_MAIN_FRAME, nullptr /* initiator */)); EXPECT_FALSE(InitializeHandler(kValidUrl, RESOURCE_TYPE_SUB_FRAME, @@ -317,23 +328,30 @@ } TEST_F(ForeignFetchRequestHandlerTest, InitializeHandler_SameOriginRequest) { + CreateWindowTypeProviderHost(); EXPECT_FALSE(InitializeHandler(kValidUrl, RESOURCE_TYPE_IMAGE, kValidUrl /* initiator */)); } TEST_F(ForeignFetchRequestHandlerTest, InitializeHandler_NoRegisteredHandlers) { + CreateWindowTypeProviderHost(); EXPECT_FALSE(InitializeHandler("https://invalid.example.com/foo", RESOURCE_TYPE_IMAGE, nullptr /* initiator */)); } -TEST_F(ForeignFetchRequestHandlerTest, InitializeHandler_TimeoutBehavior) { +TEST_F(ForeignFetchRequestHandlerTest, + InitializeHandler_TimeoutBehaviorForWindow) { + CreateWindowTypeProviderHost(); ForeignFetchRequestHandler* handler = InitializeHandler("https://valid.example.com/foo", RESOURCE_TYPE_IMAGE, nullptr /* initiator */); ASSERT_TRUE(handler); EXPECT_EQ(base::nullopt, timeout_for_request(handler)); +} +TEST_F(ForeignFetchRequestHandlerTest, + InitializeHandler_TimeoutBehaviorForServiceWorker) { CreateServiceWorkerTypeProviderHost(); ServiceWorkerVersion* version = provider_host()->running_hosted_version(); std::unique_ptr<net::HttpResponseInfo> http_info( @@ -360,10 +378,12 @@ EXPECT_EQ(base::TimeDelta::FromSeconds(6), remaining_time); // Make sure new request only gets remaining timeout. - handler = InitializeHandler("https://valid.example.com/foo", - RESOURCE_TYPE_IMAGE, nullptr /* initiator */); + ForeignFetchRequestHandler* handler = + InitializeHandler("https://valid.example.com/foo", RESOURCE_TYPE_IMAGE, + nullptr /* initiator */); ASSERT_TRUE(handler); - EXPECT_EQ(remaining_time, timeout_for_request(handler)); + ASSERT_TRUE(timeout_for_request(handler).has_value()); + EXPECT_EQ(remaining_time, timeout_for_request(handler).value()); } } // namespace content
diff --git a/content/browser/service_worker/link_header_support_unittest.cc b/content/browser/service_worker/link_header_support_unittest.cc index ba66b30d..869ea41 100644 --- a/content/browser/service_worker/link_header_support_unittest.cc +++ b/content/browser/service_worker/link_header_support_unittest.cc
@@ -65,16 +65,6 @@ void SetUp() override { helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath())); - - // An empty host. - std::unique_ptr<ServiceWorkerProviderHost> host( - new ServiceWorkerProviderHost( - render_process_id(), MSG_ROUTING_NONE, kMockProviderId, - SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::UNINITIALIZED, - context()->AsWeakPtr(), nullptr)); - provider_host_ = host->AsWeakPtr(); - context()->AddProviderHost(std::move(host)); } void TearDown() override { helper_.reset(); } @@ -86,15 +76,38 @@ ServiceWorkerProviderHost* provider_host() { return provider_host_.get(); } int render_process_id() const { return helper_->mock_render_process_id(); } - void CreateServiceWorkerProviderHost() { - std::unique_ptr<ServiceWorkerProviderHost> host( - new ServiceWorkerProviderHost( - render_process_id(), MSG_ROUTING_NONE, kMockProviderId, - SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, - ServiceWorkerProviderHost::FrameSecurityLevel::UNINITIALIZED, - context()->AsWeakPtr(), nullptr)); + void CreateDocumentProviderHost() { + // An empty host. + std::unique_ptr<ServiceWorkerProviderHost> host = + CreateProviderHostForWindow(render_process_id(), kMockProviderId, + true /* is_parent_frame_secure */, + context()->AsWeakPtr()); provider_host_ = host->AsWeakPtr(); - context()->RemoveProviderHost(host->process_id(), host->provider_id()); + EXPECT_FALSE( + context()->GetProviderHost(host->process_id(), host->provider_id())); + context()->AddProviderHost(std::move(host)); + } + + void CreateInsecureDocumentProviderHost() { + // An empty host. + std::unique_ptr<ServiceWorkerProviderHost> host = + CreateProviderHostForWindow(render_process_id(), kMockProviderId, + false /* is_parent_frame_secure */, + context()->AsWeakPtr()); + provider_host_ = host->AsWeakPtr(); + EXPECT_FALSE( + context()->GetProviderHost(host->process_id(), host->provider_id())); + context()->AddProviderHost(std::move(host)); + } + + void CreateServiceWorkerProviderHost() { + std::unique_ptr<ServiceWorkerProviderHost> host = + CreateProviderHostForServiceWorkerContext( + render_process_id(), kMockProviderId, + true /* is_parent_frame_secure */, context()->AsWeakPtr()); + provider_host_ = host->AsWeakPtr(); + EXPECT_FALSE( + context()->GetProviderHost(host->process_id(), host->provider_id())); context()->AddProviderHost(std::move(host)); scoped_refptr<ServiceWorkerRegistration> registration = @@ -157,6 +170,7 @@ }; TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_Basic) { + CreateDocumentProviderHost(); ProcessLinkHeaderForRequest( CreateSubresourceRequest(GURL("https://example.com/foo/bar/")).get(), "<../foo.js>; rel=serviceworker", context_wrapper()); @@ -170,6 +184,7 @@ } TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeWithFragment) { + CreateDocumentProviderHost(); ProcessLinkHeaderForRequest( CreateSubresourceRequest(GURL("https://example.com/foo/bar/")).get(), "<../bar.js>; rel=serviceworker; scope=\"scope#ref\"", context_wrapper()); @@ -184,6 +199,7 @@ } TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeAbsoluteUrl) { + CreateDocumentProviderHost(); ProcessLinkHeaderForRequest( CreateSubresourceRequest(GURL("https://example.com/foo/bar/")).get(), "<bar.js>; rel=serviceworker; " @@ -200,6 +216,7 @@ } TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeDifferentOrigin) { + CreateDocumentProviderHost(); ProcessLinkHeaderForRequest( CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(), "<bar.js>; rel=serviceworker; scope=\"https://google.com/scope\"", @@ -211,6 +228,7 @@ } TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeUrlEncodedSlash) { + CreateDocumentProviderHost(); ProcessLinkHeaderForRequest( CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(), "<bar.js>; rel=serviceworker; scope=\"./foo%2Fbar\"", context_wrapper()); @@ -222,6 +240,7 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScriptUrlEncodedSlash) { + CreateDocumentProviderHost(); ProcessLinkHeaderForRequest( CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(), "<foo%2Fbar.js>; rel=serviceworker", context_wrapper()); @@ -232,6 +251,7 @@ } TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScriptAbsoluteUrl) { + CreateDocumentProviderHost(); ProcessLinkHeaderForRequest( CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(), "<https://example.com/bar.js>; rel=serviceworker; scope=foo", @@ -247,6 +267,7 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScriptDifferentOrigin) { + CreateDocumentProviderHost(); ProcessLinkHeaderForRequest( CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(), "<https://google.com/bar.js>; rel=serviceworker; scope=foo", @@ -258,6 +279,7 @@ } TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_MultipleWorkers) { + CreateDocumentProviderHost(); ProcessLinkHeaderForRequest( CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(), "<bar.js>; rel=serviceworker; scope=foo, <baz.js>; " @@ -277,6 +299,7 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ValidAndInvalidValues) { + CreateDocumentProviderHost(); ProcessLinkHeaderForRequest( CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(), "<https://google.com/bar.js>; rel=serviceworker; scope=foo, <baz.js>; " @@ -292,6 +315,7 @@ } TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_InsecureContext) { + CreateDocumentProviderHost(); std::unique_ptr<net::URLRequest> request = CreateSubresourceRequest(GURL("https://example.com/foo/bar/")); ResourceRequestInfoImpl::ForRequest(request.get()) @@ -306,13 +330,13 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_NavigationFromInsecureContextToSecureContext) { + CreateDocumentProviderHost(); std::unique_ptr<net::URLRequest> request = CreateRequest( GURL("https://example.com/foo/bar/"), RESOURCE_TYPE_MAIN_FRAME); ResourceRequestInfoImpl::ForRequest(request.get()) ->set_initiated_in_secure_context_for_testing(false); provider_host()->SetDocumentUrl(GURL("https://example.com/foo/bar/")); - provider_host()->set_parent_frame_secure(true); ProcessLinkHeaderForRequest(request.get(), "<../foo.js>; rel=serviceworker", context_wrapper()); @@ -327,8 +351,8 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_NavigationToInsecureContext) { + CreateDocumentProviderHost(); provider_host()->SetDocumentUrl(GURL("http://example.com/foo/bar/")); - provider_host()->set_parent_frame_secure(true); ProcessLinkHeaderForRequest(CreateRequest(GURL("http://example.com/foo/bar/"), RESOURCE_TYPE_MAIN_FRAME) .get(), @@ -342,8 +366,8 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_NavigationToInsecureHttpsContext) { + CreateInsecureDocumentProviderHost(); provider_host()->SetDocumentUrl(GURL("https://example.com/foo/bar/")); - provider_host()->set_parent_frame_secure(false); ProcessLinkHeaderForRequest( CreateRequest(GURL("https://example.com/foo/bar/"), RESOURCE_TYPE_MAIN_FRAME) @@ -371,12 +395,10 @@ InstallServiceWorker_FromWorkerWithControllees) { CreateServiceWorkerProviderHost(); - std::unique_ptr<ServiceWorkerProviderHost> controllee( - new ServiceWorkerProviderHost( - render_process_id(), MSG_ROUTING_NONE, kMockProviderId, - SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::UNINITIALIZED, - context()->AsWeakPtr(), nullptr)); + std::unique_ptr<ServiceWorkerProviderHost> controllee = + CreateProviderHostForWindow(render_process_id(), kMockProviderId, + true /* is_parent_frame_secure */, + context()->AsWeakPtr()); provider_host()->running_hosted_version()->AddControllee(controllee.get()); ProcessLinkHeaderForRequest(
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc index 3460d4e..1fdc638 100644 --- a/content/browser/service_worker/service_worker_browsertest.cc +++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -598,13 +598,11 @@ void AddControlleeOnIOThread() { ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); - std::unique_ptr<ServiceWorkerProviderHost> host( - new ServiceWorkerProviderHost( - 33 /* dummy render process id */, - MSG_ROUTING_NONE /* render_frame_id */, 1 /* dummy provider_id */, - SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - wrapper()->context()->AsWeakPtr(), NULL)); + std::unique_ptr<ServiceWorkerProviderHost> host = + CreateProviderHostForWindow(33 /* dummy render process id */, + 1 /* dummy provider_id */, + true /* is_parent_frame_secure */, + wrapper()->context()->AsWeakPtr()); host->SetDocumentUrl( embedded_test_server()->GetURL("/service_worker/host")); host->AssociateRegistration(registration_.get(),
diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc index 55d93d4..a0bbc66 100644 --- a/content/browser/service_worker/service_worker_context_core.cc +++ b/content/browser/service_worker/service_worker_context_core.cc
@@ -24,6 +24,7 @@ #include "content/browser/service_worker/service_worker_context_observer.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/service_worker/service_worker_database_task_manager.h" +#include "content/browser/service_worker/service_worker_dispatcher_host.h" #include "content/browser/service_worker/service_worker_info.h" #include "content/browser/service_worker/service_worker_job_coordinator.h" #include "content/browser/service_worker/service_worker_process_manager.h" @@ -220,8 +221,8 @@ base::ObserverListThreadSafe<ServiceWorkerContextObserver>* observer_list, ServiceWorkerContextWrapper* wrapper) : wrapper_(wrapper), - providers_(new ProcessToProviderMap), - provider_by_uuid_(new ProviderByClientUUIDMap), + providers_(base::MakeUnique<ProcessToProviderMap>()), + provider_by_uuid_(base::MakeUnique<ProviderByClientUUIDMap>()), force_update_on_page_load_(false), next_handle_id_(0), next_registration_handle_id_(0), @@ -241,6 +242,7 @@ ServiceWorkerContextCore* old_context, ServiceWorkerContextWrapper* wrapper) : wrapper_(wrapper), + dispatcher_hosts_(std::move(old_context->dispatcher_hosts_)), providers_(old_context->providers_.release()), provider_by_uuid_(old_context->provider_by_uuid_.release()), next_handle_id_(old_context->next_handle_id_), @@ -268,12 +270,26 @@ weak_factory_.InvalidateWeakPtrs(); } -ServiceWorkerProviderHost* ServiceWorkerContextCore::GetProviderHost( - int process_id, int provider_id) { - ProviderMap* map = GetProviderMapForProcess(process_id); - if (!map) - return NULL; - return map->Lookup(provider_id); +void ServiceWorkerContextCore::AddDispatcherHost( + int process_id, + content::ServiceWorkerDispatcherHost* dispatcher_host) { + DCHECK(dispatcher_hosts_.find(process_id) == dispatcher_hosts_.end()); + dispatcher_hosts_[process_id] = dispatcher_host; +} + +ServiceWorkerDispatcherHost* ServiceWorkerContextCore::GetDispatcherHost( + int process_id) { + auto it = dispatcher_hosts_.find(process_id); + if (it == dispatcher_hosts_.end()) + return nullptr; + return it->second; +} + +void ServiceWorkerContextCore::RemoveDispatcherHost(int process_id) { + DCHECK(dispatcher_hosts_.find(process_id) != dispatcher_hosts_.end()); + RemoveAllProviderHostsForProcess(process_id); + embedded_worker_registry_->RemoveProcess(process_id); + dispatcher_hosts_.erase(process_id); } void ServiceWorkerContextCore::AddProviderHost( @@ -288,6 +304,15 @@ map->AddWithID(std::move(host), provider_id); } +ServiceWorkerProviderHost* ServiceWorkerContextCore::GetProviderHost( + int process_id, + int provider_id) { + ProviderMap* map = GetProviderMapForProcess(process_id); + if (!map) + return nullptr; + return map->Lookup(provider_id); +} + void ServiceWorkerContextCore::RemoveProviderHost( int process_id, int provider_id) { ProviderMap* map = GetProviderMapForProcess(process_id); @@ -505,7 +530,7 @@ ServiceWorkerRegistration* ServiceWorkerContextCore::GetLiveRegistration( int64_t id) { RegistrationsMap::iterator it = live_registrations_.find(id); - return (it != live_registrations_.end()) ? it->second : NULL; + return (it != live_registrations_.end()) ? it->second : nullptr; } void ServiceWorkerContextCore::AddLiveRegistration( @@ -527,7 +552,7 @@ ServiceWorkerVersion* ServiceWorkerContextCore::GetLiveVersion(int64_t id) { VersionMap::iterator it = live_versions_.find(id); - return (it != live_versions_.end()) ? it->second : NULL; + return (it != live_versions_.end()) ? it->second : nullptr; } // PlzNavigate @@ -636,14 +661,7 @@ ProviderMap* map = GetProviderMapForProcess(process_id); ServiceWorkerProviderHost* transferee = map->Lookup(provider_id); std::unique_ptr<ServiceWorkerProviderHost> replacement = - base::MakeUnique<ServiceWorkerProviderHost>( - process_id, transferee->frame_id(), provider_id, - transferee->provider_type(), - transferee->is_parent_frame_secure() - ? ServiceWorkerProviderHost::FrameSecurityLevel::SECURE - : ServiceWorkerProviderHost::FrameSecurityLevel::INSECURE, - AsWeakPtr(), transferee->dispatcher_host()); - transferee->PrepareForCrossSiteTransfer(); + transferee->PrepareForCrossSiteTransfer(); return map->Replace(provider_id, std::move(replacement)); }
diff --git a/content/browser/service_worker/service_worker_context_core.h b/content/browser/service_worker/service_worker_context_core.h index 4832b8c4..bb1fc899 100644 --- a/content/browser/service_worker/service_worker_context_core.h +++ b/content/browser/service_worker/service_worker_context_core.h
@@ -44,6 +44,7 @@ class ServiceWorkerContextObserver; class ServiceWorkerContextWrapper; class ServiceWorkerDatabaseTaskManager; +class ServiceWorkerDispatcherHost; class ServiceWorkerJobCoordinator; class ServiceWorkerNavigationHandleCore; class ServiceWorkerProviderHost; @@ -154,10 +155,17 @@ return job_coordinator_.get(); } + // Maintains DispatcherHosts to exchange service worker related messages + // through them. The DispatcherHosts are not owned by this class. + void AddDispatcherHost(int process_id, + ServiceWorkerDispatcherHost* dispatcher_host); + ServiceWorkerDispatcherHost* GetDispatcherHost(int process_id); + void RemoveDispatcherHost(int process_id); + // The context class owns the set of ProviderHosts. - ServiceWorkerProviderHost* GetProviderHost(int process_id, int provider_id); void AddProviderHost( std::unique_ptr<ServiceWorkerProviderHost> provider_host); + ServiceWorkerProviderHost* GetProviderHost(int process_id, int provider_id); void RemoveProviderHost(int process_id, int provider_id); void RemoveAllProviderHostsForProcess(int process_id); std::unique_ptr<ProviderHostIterator> GetProviderHostIterator(); @@ -342,6 +350,8 @@ // because the Wrapper::Shutdown call that hops threads to destroy |this| uses // Bind() to hold a reference to |wrapper_| until |this| is fully destroyed. ServiceWorkerContextWrapper* wrapper_; + std::map<int /* process_id */, ServiceWorkerDispatcherHost*> + dispatcher_hosts_; std::unique_ptr<ProcessToProviderMap> providers_; std::unique_ptr<ProviderByClientUUIDMap> provider_by_uuid_; std::unique_ptr<ServiceWorkerStorage> storage_;
diff --git a/content/browser/service_worker/service_worker_context_request_handler_unittest.cc b/content/browser/service_worker/service_worker_context_request_handler_unittest.cc index c6ed19f..cae7d7e 100644 --- a/content/browser/service_worker/service_worker_context_request_handler_unittest.cc +++ b/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
@@ -87,13 +87,10 @@ ServiceWorkerContextCore* context() const { return helper_->context(); } void SetUpProvider() { - std::unique_ptr<ServiceWorkerProviderHost> host( - new ServiceWorkerProviderHost( - helper_->mock_render_process_id(), - MSG_ROUTING_NONE /* render_frame_id */, 1 /* provider_id */, - SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - context()->AsWeakPtr(), nullptr)); + std::unique_ptr<ServiceWorkerProviderHost> host = + CreateProviderHostForServiceWorkerContext( + helper_->mock_render_process_id(), 1 /* provider_id */, + true /* is_parent_frame_secure */, context()->AsWeakPtr()); provider_host_ = host->AsWeakPtr(); context()->AddProviderHost(std::move(host)); provider_host_->running_hosted_version_ = version_;
diff --git a/content/browser/service_worker/service_worker_context_unittest.cc b/content/browser/service_worker/service_worker_context_unittest.cc index 761edd79..1a49d8b 100644 --- a/content/browser/service_worker/service_worker_context_unittest.cc +++ b/content/browser/service_worker/service_worker_context_unittest.cc
@@ -586,41 +586,41 @@ int provider_id = 1; // Host1 (provider_id=1): process_id=1, origin1. - ServiceWorkerProviderHost* host1(new ServiceWorkerProviderHost( - kRenderProcessId1, MSG_ROUTING_NONE, provider_id++, - SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - context()->AsWeakPtr(), nullptr)); + std::unique_ptr<ServiceWorkerProviderHost> host1 = + CreateProviderHostForWindow(kRenderProcessId1, provider_id++, + true /* is_parent_frame_secure */, + context()->AsWeakPtr()); host1->SetDocumentUrl(kOrigin1); // Host2 (provider_id=2): process_id=2, origin2. - ServiceWorkerProviderHost* host2(new ServiceWorkerProviderHost( - kRenderProcessId2, MSG_ROUTING_NONE, provider_id++, - SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - context()->AsWeakPtr(), nullptr)); + std::unique_ptr<ServiceWorkerProviderHost> host2 = + CreateProviderHostForWindow(kRenderProcessId2, provider_id++, + true /* is_parent_frame_secure */, + context()->AsWeakPtr()); host2->SetDocumentUrl(kOrigin2); // Host3 (provider_id=3): process_id=2, origin1. - ServiceWorkerProviderHost* host3(new ServiceWorkerProviderHost( - kRenderProcessId2, MSG_ROUTING_NONE, provider_id++, - SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - context()->AsWeakPtr(), nullptr)); + std::unique_ptr<ServiceWorkerProviderHost> host3 = + CreateProviderHostForWindow(kRenderProcessId2, provider_id++, + true /* is_parent_frame_secure */, + context()->AsWeakPtr()); host3->SetDocumentUrl(kOrigin1); // Host4 (provider_id=4): process_id=2, origin2, for ServiceWorker. - ServiceWorkerProviderHost* host4(new ServiceWorkerProviderHost( - kRenderProcessId2, MSG_ROUTING_NONE, provider_id++, - SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - context()->AsWeakPtr(), nullptr)); + std::unique_ptr<ServiceWorkerProviderHost> host4 = + CreateProviderHostForServiceWorkerContext( + kRenderProcessId2, provider_id++, true /* is_parent_frame_secure */, + context()->AsWeakPtr()); host4->SetDocumentUrl(kOrigin2); - context()->AddProviderHost(base::WrapUnique(host1)); - context()->AddProviderHost(base::WrapUnique(host2)); - context()->AddProviderHost(base::WrapUnique(host3)); - context()->AddProviderHost(base::WrapUnique(host4)); + ServiceWorkerProviderHost* host1_raw = host1.get(); + ServiceWorkerProviderHost* host2_raw = host2.get(); + ServiceWorkerProviderHost* host3_raw = host3.get(); + ServiceWorkerProviderHost* host4_raw = host4.get(); + context()->AddProviderHost(std::move(host1)); + context()->AddProviderHost(std::move(host2)); + context()->AddProviderHost(std::move(host3)); + context()->AddProviderHost(std::move(host4)); // Iterate over all provider hosts. std::set<ServiceWorkerProviderHost*> results; @@ -629,10 +629,10 @@ results.insert(it->GetProviderHost()); } EXPECT_EQ(4u, results.size()); - EXPECT_TRUE(ContainsKey(results, host1)); - EXPECT_TRUE(ContainsKey(results, host2)); - EXPECT_TRUE(ContainsKey(results, host3)); - EXPECT_TRUE(ContainsKey(results, host4)); + EXPECT_TRUE(ContainsKey(results, host1_raw)); + EXPECT_TRUE(ContainsKey(results, host2_raw)); + EXPECT_TRUE(ContainsKey(results, host3_raw)); + EXPECT_TRUE(ContainsKey(results, host4_raw)); // Iterate over the client provider hosts that belong to kOrigin1. results.clear(); @@ -641,8 +641,8 @@ results.insert(it->GetProviderHost()); } EXPECT_EQ(2u, results.size()); - EXPECT_TRUE(ContainsKey(results, host1)); - EXPECT_TRUE(ContainsKey(results, host3)); + EXPECT_TRUE(ContainsKey(results, host1_raw)); + EXPECT_TRUE(ContainsKey(results, host3_raw)); // Iterate over the provider hosts that belong to kOrigin2. // (This should not include host4 as it's not for controllee.) @@ -652,7 +652,7 @@ results.insert(it->GetProviderHost()); } EXPECT_EQ(1u, results.size()); - EXPECT_TRUE(ContainsKey(results, host2)); + EXPECT_TRUE(ContainsKey(results, host2_raw)); context()->RemoveProviderHost(kRenderProcessId1, 1); context()->RemoveProviderHost(kRenderProcessId2, 2);
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc index 249e254..560416b 100644 --- a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc +++ b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
@@ -125,12 +125,10 @@ EmbeddedWorkerTestHelper::CreateHttpResponseInfo()); // An empty host. - std::unique_ptr<ServiceWorkerProviderHost> host( - new ServiceWorkerProviderHost( - helper_->mock_render_process_id(), MSG_ROUTING_NONE, - kMockProviderId, SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - context()->AsWeakPtr(), NULL)); + std::unique_ptr<ServiceWorkerProviderHost> host = + CreateProviderHostForWindow( + helper_->mock_render_process_id(), kMockProviderId, + true /* is_parent_frame_secure */, helper_->context()->AsWeakPtr()); provider_host_ = host->AsWeakPtr(); context()->AddProviderHost(std::move(host));
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc index 96f7899..1fb1130 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host.cc +++ b/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -119,11 +119,8 @@ } ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() { - if (GetContext()) { - GetContext()->RemoveAllProviderHostsForProcess(render_process_id_); - GetContext()->embedded_worker_registry()->RemoveChildProcessSender( - render_process_id_); - } + if (GetContext()) + GetContext()->RemoveDispatcherHost(render_process_id_); } void ServiceWorkerDispatcherHost::Init( @@ -138,8 +135,7 @@ context_wrapper_ = context_wrapper; if (!GetContext()) return; - GetContext()->embedded_worker_registry()->AddChildProcessSender( - render_process_id_, this); + GetContext()->AddDispatcherHost(render_process_id_, this); } void ServiceWorkerDispatcherHost::OnFilterAdded(IPC::Channel* channel) { @@ -156,11 +152,8 @@ void ServiceWorkerDispatcherHost::OnFilterRemoved() { // Don't wait until the destructor to teardown since a new dispatcher host // for this process might be created before then. - if (GetContext()) { - GetContext()->RemoveAllProviderHostsForProcess(render_process_id_); - GetContext()->embedded_worker_registry()->RemoveChildProcessSender( - render_process_id_); - } + if (GetContext()) + GetContext()->RemoveDispatcherHost(render_process_id_); context_wrapper_ = nullptr; channel_ready_ = false; } @@ -185,12 +178,6 @@ OnGetRegistrations) IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistrationForReady, OnGetRegistrationForReady) - IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderCreated, - OnProviderCreated) - IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed, - OnProviderDestroyed) - IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetVersionId, - OnSetHostedVersionId) IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToWorker, OnPostMessageToWorker) IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerReadyForInspection, @@ -1004,10 +991,7 @@ } void ServiceWorkerDispatcherHost::OnProviderCreated( - int provider_id, - int route_id, - ServiceWorkerProviderType provider_type, - bool is_parent_frame_secure) { + ServiceWorkerProviderHostInfo info) { // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed. tracked_objects::ScopedTracker tracking_profile( FROM_HERE_WITH_EXPLICIT_FUNCTION( @@ -1016,19 +1000,19 @@ "ServiceWorkerDispatcherHost::OnProviderCreated"); if (!GetContext()) return; - if (GetContext()->GetProviderHost(render_process_id_, provider_id)) { + if (GetContext()->GetProviderHost(render_process_id_, info.provider_id)) { bad_message::ReceivedBadMessage(this, bad_message::SWDH_PROVIDER_CREATED_NO_HOST); return; } - std::unique_ptr<ServiceWorkerProviderHost> provider_host; if (IsBrowserSideNavigationEnabled() && - ServiceWorkerUtils::IsBrowserAssignedProviderId(provider_id)) { + ServiceWorkerUtils::IsBrowserAssignedProviderId(info.provider_id)) { + std::unique_ptr<ServiceWorkerProviderHost> provider_host; // PlzNavigate // Retrieve the provider host previously created for navigation requests. ServiceWorkerNavigationHandleCore* navigation_handle_core = - GetContext()->GetNavigationHandleCore(provider_id); + GetContext()->GetNavigationHandleCore(info.provider_id); if (navigation_handle_core != nullptr) provider_host = navigation_handle_core->RetrievePreCreatedHost(); @@ -1036,25 +1020,19 @@ // Just return as the navigation will be stopped in the renderer as well. if (provider_host == nullptr) return; - DCHECK_EQ(SERVICE_WORKER_PROVIDER_FOR_WINDOW, provider_type); - provider_host->CompleteNavigationInitialized(render_process_id_, route_id, - this); + DCHECK_EQ(SERVICE_WORKER_PROVIDER_FOR_WINDOW, info.type); + provider_host->CompleteNavigationInitialized(render_process_id_, + info.route_id, this); + GetContext()->AddProviderHost(std::move(provider_host)); } else { - if (ServiceWorkerUtils::IsBrowserAssignedProviderId(provider_id)) { + if (ServiceWorkerUtils::IsBrowserAssignedProviderId(info.provider_id)) { bad_message::ReceivedBadMessage( this, bad_message::SWDH_PROVIDER_CREATED_NO_HOST); return; } - ServiceWorkerProviderHost::FrameSecurityLevel parent_frame_security_level = - is_parent_frame_secure - ? ServiceWorkerProviderHost::FrameSecurityLevel::SECURE - : ServiceWorkerProviderHost::FrameSecurityLevel::INSECURE; - provider_host = std::unique_ptr<ServiceWorkerProviderHost>( - new ServiceWorkerProviderHost( - render_process_id_, route_id, provider_id, provider_type, - parent_frame_security_level, GetContext()->AsWeakPtr(), this)); + GetContext()->AddProviderHost(ServiceWorkerProviderHost::Create( + render_process_id_, std::move(info), GetContext()->AsWeakPtr(), this)); } - GetContext()->AddProviderHost(std::move(provider_host)); } void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.h b/content/browser/service_worker/service_worker_dispatcher_host.h index e33a7e8..cfa7045 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host.h +++ b/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -88,6 +88,10 @@ friend class base::DeleteHelper<ServiceWorkerDispatcherHost>; friend class ServiceWorkerDispatcherHostTest; friend class TestingServiceWorkerDispatcherHost; + FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDispatcherHostTest, + ProviderCreatedAndDestroyed); + FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDispatcherHostTest, + CleanupOnRendererCrash); using StatusCallback = base::Callback<void(ServiceWorkerStatusCode status)>; enum class ProviderStatus { OK, NO_CONTEXT, DEAD_HOST, NO_HOST, NO_URL }; @@ -97,10 +101,7 @@ void AddMojoBinding(mojo::ScopedInterfaceEndpointHandle handle); // mojom::ServiceWorkerDispatcherHost implementation - void OnProviderCreated(int provider_id, - int route_id, - ServiceWorkerProviderType provider_type, - bool is_parent_frame_secure) override; + void OnProviderCreated(ServiceWorkerProviderHostInfo info) override; void OnProviderDestroyed(int provider_id) override; void OnSetHostedVersionId(int provider_id, int64_t version_id,
diff --git a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc index 46bcb77..0c3fdb6 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc +++ b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
@@ -118,9 +118,11 @@ void Initialize(std::unique_ptr<EmbeddedWorkerTestHelper> helper) { helper_.reset(helper.release()); + // Replace the default dispatcher host. + int process_id = helper_->mock_render_process_id(); + context()->RemoveDispatcherHost(process_id); dispatcher_host_ = new TestingServiceWorkerDispatcherHost( - helper_->mock_render_process_id(), context_wrapper(), - &resource_context_, helper_.get()); + process_id, context_wrapper(), &resource_context_, helper_.get()); } void SetUpRegistration(const GURL& scope, const GURL& script_url) { @@ -154,16 +156,16 @@ void SendSetHostedVersionId(int provider_id, int64_t version_id, int embedded_worker_id) { - dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_SetVersionId( - provider_id, version_id, embedded_worker_id)); + dispatcher_host_->OnSetHostedVersionId(provider_id, version_id, + embedded_worker_id); } void SendProviderCreated(ServiceWorkerProviderType type, const GURL& pattern) { const int64_t kProviderId = 99; - dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated( - kProviderId, MSG_ROUTING_NONE, type, - true /* is_parent_frame_secure */)); + ServiceWorkerProviderHostInfo info(kProviderId, MSG_ROUTING_NONE, type, + true /* is_parent_frame_secure */); + dispatcher_host_->OnProviderCreated(std::move(info)); helper_->SimulateAddProcessToPattern(pattern, helper_->mock_render_process_id()); provider_host_ = context()->GetProviderHost( @@ -244,12 +246,11 @@ sender_provider_host, callback); } - ServiceWorkerProviderHost* CreateServiceWorkerProviderHost(int provider_id) { - return new ServiceWorkerProviderHost( - helper_->mock_render_process_id(), kRenderFrameId, provider_id, - SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - context()->AsWeakPtr(), dispatcher_host_.get()); + std::unique_ptr<ServiceWorkerProviderHost> CreateServiceWorkerProviderHost( + int provider_id) { + return CreateProviderHostWithDispatcherHost( + helper_->mock_render_process_id(), provider_id, context()->AsWeakPtr(), + kRenderFrameId, dispatcher_host_.get()); } TestBrowserThreadBundle browser_thread_bundle_; @@ -508,34 +509,32 @@ const int kProviderId = 1001; int process_id = helper_->mock_render_process_id(); - dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated( + dispatcher_host_->OnProviderCreated(ServiceWorkerProviderHostInfo( kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_WINDOW, true /* is_parent_frame_secure */)); EXPECT_TRUE(context()->GetProviderHost(process_id, kProviderId)); // Two with the same ID should be seen as a bad message. - dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated( + dispatcher_host_->OnProviderCreated(ServiceWorkerProviderHostInfo( kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_WINDOW, true /* is_parent_frame_secure */)); EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_); - dispatcher_host_->OnMessageReceived( - ServiceWorkerHostMsg_ProviderDestroyed(kProviderId)); + dispatcher_host_->OnProviderDestroyed(kProviderId); EXPECT_FALSE(context()->GetProviderHost(process_id, kProviderId)); // Destroying an ID that does not exist warrants a bad message. - dispatcher_host_->OnMessageReceived( - ServiceWorkerHostMsg_ProviderDestroyed(kProviderId)); + dispatcher_host_->OnProviderDestroyed(kProviderId); EXPECT_EQ(2, dispatcher_host_->bad_messages_received_count_); // Deletion of the dispatcher_host should cause providers for that // process to get deleted as well. - dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated( + dispatcher_host_->OnProviderCreated(ServiceWorkerProviderHostInfo( kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_WINDOW, true /* is_parent_frame_secure */)); EXPECT_TRUE(context()->GetProviderHost(process_id, kProviderId)); EXPECT_TRUE(dispatcher_host_->HasOneRef()); - dispatcher_host_ = NULL; + dispatcher_host_ = nullptr; EXPECT_FALSE(context()->GetProviderHost(process_id, kProviderId)); } @@ -667,7 +666,7 @@ // To show the new dispatcher can operate, simulate provider creation. Since // the old dispatcher cleaned up the old provider host, the new one won't // complain. - new_dispatcher_host->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated( + new_dispatcher_host->OnProviderCreated(ServiceWorkerProviderHostInfo( provider_id, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_WINDOW, true /* is_parent_frame_secure */)); EXPECT_EQ(0, new_dispatcher_host->bad_messages_received_count_);
diff --git a/content/browser/service_worker/service_worker_handle_unittest.cc b/content/browser/service_worker/service_worker_handle_unittest.cc index 1b6e7832..24d01a17 100644 --- a/content/browser/service_worker/service_worker_handle_unittest.cc +++ b/content/browser/service_worker/service_worker_handle_unittest.cc
@@ -76,6 +76,7 @@ void SetUp() override { helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath())); + helper_->context()->RemoveDispatcherHost(helper_->mock_render_process_id()); dispatcher_host_ = new TestingServiceWorkerDispatcherHost( helper_->mock_render_process_id(), helper_->context_wrapper(), &resource_context_, helper_.get()); @@ -110,12 +111,10 @@ base::RunLoop().RunUntilIdle(); ASSERT_EQ(SERVICE_WORKER_OK, status); - provider_host_.reset(new ServiceWorkerProviderHost( - helper_->mock_render_process_id(), kRenderFrameId, 1, - SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - helper_->context()->AsWeakPtr(), dispatcher_host_.get())); - + provider_host_ = CreateProviderHostWithDispatcherHost( + helper_->mock_render_process_id(), 1 /* provider_id */, + helper_->context()->AsWeakPtr(), kRenderFrameId, + dispatcher_host_.get()); helper_->SimulateAddProcessToPattern(pattern, helper_->mock_render_process_id()); }
diff --git a/content/browser/service_worker/service_worker_job_unittest.cc b/content/browser/service_worker/service_worker_job_unittest.cc index 96c014a..0d235ec 100644 --- a/content/browser/service_worker/service_worker_job_unittest.cc +++ b/content/browser/service_worker/service_worker_job_unittest.cc
@@ -199,13 +199,10 @@ std::unique_ptr<ServiceWorkerProviderHost> ServiceWorkerJobTest::CreateControllee() { - return std::unique_ptr<ServiceWorkerProviderHost>( - new ServiceWorkerProviderHost( - 33 /* dummy render_process id */, - MSG_ROUTING_NONE /* render_frame_id */, 1 /* dummy provider_id */, - SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - helper_->context()->AsWeakPtr(), NULL)); + std::unique_ptr<ServiceWorkerProviderHost> host = CreateProviderHostForWindow( + 33 /* dummy render process id */, 1 /* dummy provider_id */, + true /* is_parent_frame_secure */, helper_->context()->AsWeakPtr()); + return host; } TEST_F(ServiceWorkerJobTest, SameDocumentSameRegistration) {
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc index f15022e..40a0037 100644 --- a/content/browser/service_worker/service_worker_provider_host.cc +++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -90,22 +90,31 @@ CHECK(IsBrowserSideNavigationEnabled()); // Generate a new browser-assigned id for the host. int provider_id = g_next_navigation_provider_id--; - auto host = base::MakeUnique<ServiceWorkerProviderHost>( + auto host = base::WrapUnique(new ServiceWorkerProviderHost( ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE, provider_id, - SERVICE_WORKER_PROVIDER_FOR_WINDOW, - are_ancestors_secure ? FrameSecurityLevel::SECURE - : FrameSecurityLevel::INSECURE, - context, nullptr); + SERVICE_WORKER_PROVIDER_FOR_WINDOW, are_ancestors_secure, context, + nullptr)); host->web_contents_getter_ = web_contents_getter; return host; } +// static +std::unique_ptr<ServiceWorkerProviderHost> ServiceWorkerProviderHost::Create( + int process_id, + ServiceWorkerProviderHostInfo info, + base::WeakPtr<ServiceWorkerContextCore> context, + ServiceWorkerDispatcherHost* dispatcher_host) { + return base::WrapUnique(new ServiceWorkerProviderHost( + process_id, info.route_id, info.provider_id, info.type, + info.is_parent_frame_secure, context, dispatcher_host)); +} + ServiceWorkerProviderHost::ServiceWorkerProviderHost( int render_process_id, int route_id, int provider_id, ServiceWorkerProviderType provider_type, - FrameSecurityLevel parent_frame_security_level, + bool is_parent_frame_secure, base::WeakPtr<ServiceWorkerContextCore> context, ServiceWorkerDispatcherHost* dispatcher_host) : client_uuid_(base::GenerateGUID()), @@ -114,7 +123,7 @@ render_thread_id_(kDocumentMainThreadId), provider_id_(provider_id), provider_type_(provider_type), - parent_frame_security_level_(parent_frame_security_level), + is_parent_frame_secure_(is_parent_frame_secure), context_(context), dispatcher_host_(dispatcher_host), allow_association_(true) { @@ -490,12 +499,18 @@ return true; } -void ServiceWorkerProviderHost::PrepareForCrossSiteTransfer() { +std::unique_ptr<ServiceWorkerProviderHost> +ServiceWorkerProviderHost::PrepareForCrossSiteTransfer() { DCHECK_NE(ChildProcessHost::kInvalidUniqueID, render_process_id_); DCHECK_NE(MSG_ROUTING_NONE, route_id_); DCHECK_EQ(kDocumentMainThreadId, render_thread_id_); DCHECK_NE(SERVICE_WORKER_PROVIDER_UNKNOWN, provider_type_); + std::unique_ptr<ServiceWorkerProviderHost> new_provider_host = + base::WrapUnique(new ServiceWorkerProviderHost( + process_id(), frame_id(), provider_id(), provider_type(), + is_parent_frame_secure(), context_, dispatcher_host())); + for (const GURL& pattern : associated_patterns_) DecreaseProcessReference(pattern); @@ -515,6 +530,7 @@ provider_id_ = kInvalidServiceWorkerProviderId; provider_type_ = SERVICE_WORKER_PROVIDER_UNKNOWN; dispatcher_host_ = nullptr; + return new_provider_host; } void ServiceWorkerProviderHost::CompleteCrossSiteTransfer(
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h index e42c5a46..585bc59 100644 --- a/content/browser/service_worker/service_worker_provider_host.h +++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -20,6 +20,7 @@ #include "base/memory/weak_ptr.h" #include "content/browser/service_worker/service_worker_registration.h" #include "content/common/content_export.h" +#include "content/common/service_worker/service_worker_provider_host_info.h" #include "content/common/service_worker/service_worker_types.h" #include "content/public/common/request_context_frame_type.h" #include "content/public/common/request_context_type.h" @@ -72,22 +73,15 @@ bool are_ancestors_secure, const WebContentsGetter& web_contents_getter); - enum class FrameSecurityLevel { UNINITIALIZED, INSECURE, SECURE }; + // Used to create a ServiceWorkerProviderHost when the renderer-side provider + // is created. This ProviderHost will be created for the process specified by + // |process_id|. + static std::unique_ptr<ServiceWorkerProviderHost> Create( + int process_id, + ServiceWorkerProviderHostInfo info, + base::WeakPtr<ServiceWorkerContextCore> context, + ServiceWorkerDispatcherHost* dispatcher_host); - // When this provider host is for a Service Worker context, |route_id| is - // MSG_ROUTING_NONE. When this provider host is for a Document, - // |route_id| is the frame ID of the Document. When this provider host is for - // a Shared Worker, |route_id| is the Shared Worker route ID. - // |provider_type| gives additional information whether the provider is - // created for controller (ServiceWorker) or controllee (Document or - // SharedWorker). - ServiceWorkerProviderHost(int render_process_id, - int route_id, - int provider_id, - ServiceWorkerProviderType provider_type, - FrameSecurityLevel parent_frame_security_level, - base::WeakPtr<ServiceWorkerContextCore> context, - ServiceWorkerDispatcherHost* dispatcher_host); virtual ~ServiceWorkerProviderHost(); const std::string& client_uuid() const { return client_uuid_; } @@ -99,15 +93,7 @@ return web_contents_getter_; } - bool is_parent_frame_secure() const { - return parent_frame_security_level_ == FrameSecurityLevel::SECURE; - } - void set_parent_frame_secure(bool is_parent_frame_secure) { - CHECK_EQ(parent_frame_security_level_, FrameSecurityLevel::UNINITIALIZED); - parent_frame_security_level_ = is_parent_frame_secure - ? FrameSecurityLevel::SECURE - : FrameSecurityLevel::INSECURE; - } + bool is_parent_frame_secure() const { return is_parent_frame_secure_; } // Returns whether this provider host is secure enough to have a service // worker controller. @@ -252,7 +238,7 @@ bool GetRegistrationForReady(const GetRegistrationForReadyCallback& callback); // Methods to support cross site navigations. - void PrepareForCrossSiteTransfer(); + std::unique_ptr<ServiceWorkerProviderHost> PrepareForCrossSiteTransfer(); void CompleteCrossSiteTransfer( int new_process_id, int new_frame_id, @@ -329,6 +315,14 @@ ~OneShotGetReadyCallback(); }; + ServiceWorkerProviderHost(int render_process_id, + int route_id, + int provider_id, + ServiceWorkerProviderType provider_type, + bool is_parent_frame_secure, + base::WeakPtr<ServiceWorkerContextCore> context, + ServiceWorkerDispatcherHost* dispatcher_host); + // ServiceWorkerRegistration::Listener overrides. void OnVersionAttributesChanged( ServiceWorkerRegistration* registration, @@ -388,7 +382,7 @@ WebContentsGetter web_contents_getter_; ServiceWorkerProviderType provider_type_; - FrameSecurityLevel parent_frame_security_level_; + const bool is_parent_frame_secure_; GURL document_url_; GURL topmost_frame_url_;
diff --git a/content/browser/service_worker/service_worker_provider_host_unittest.cc b/content/browser/service_worker/service_worker_provider_host_unittest.cc index 36381aff..ce0560b 100644 --- a/content/browser/service_worker/service_worker_provider_host_unittest.cc +++ b/content/browser/service_worker/service_worker_provider_host_unittest.cc
@@ -4,6 +4,9 @@ #include "content/browser/service_worker/service_worker_provider_host.h" +#include <memory> +#include <utility> + #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/memory/weak_ptr.h" @@ -36,7 +39,8 @@ class ServiceWorkerProviderHostTest : public testing::Test { protected: ServiceWorkerProviderHostTest() - : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) { + : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), + next_provider_id_(1) { SetContentClient(&test_content_client_); } ~ServiceWorkerProviderHostTest() override {} @@ -55,26 +59,6 @@ GURL("https://www.example.com/example"), 2L, context_->AsWeakPtr()); registration3_ = new ServiceWorkerRegistration( GURL("https://other.example.com/"), 3L, context_->AsWeakPtr()); - - // Prepare provider hosts (for the same process). - std::unique_ptr<ServiceWorkerProviderHost> host1( - new ServiceWorkerProviderHost( - helper_->mock_render_process_id(), MSG_ROUTING_NONE, - 1 /* provider_id */, SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - context_->AsWeakPtr(), NULL)); - host1->SetDocumentUrl(GURL("https://www.example.com/example1.html")); - std::unique_ptr<ServiceWorkerProviderHost> host2( - new ServiceWorkerProviderHost( - helper_->mock_render_process_id(), MSG_ROUTING_NONE, - 2 /* provider_id */, SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - context_->AsWeakPtr(), NULL)); - host2->SetDocumentUrl(GURL("https://www.example.com/example2.html")); - provider_host1_ = host1->AsWeakPtr(); - provider_host2_ = host2->AsWeakPtr(); - context_->AddProviderHost(base::WrapUnique(host1.release())); - context_->AddProviderHost(base::WrapUnique(host2.release())); } void TearDown() override { @@ -90,24 +74,52 @@ return context_->process_manager()->PatternHasProcessToRun(pattern); } + ServiceWorkerProviderHost* CreateProviderHost(const GURL& document_url) { + std::unique_ptr<ServiceWorkerProviderHost> host = + CreateProviderHostForWindow( + helper_->mock_render_process_id(), next_provider_id_++, + true /* is_parent_frame_secure */, helper_->context()->AsWeakPtr()); + ServiceWorkerProviderHost* host_raw = host.get(); + host->SetDocumentUrl(document_url); + context_->AddProviderHost(std::move(host)); + return host_raw; + } + + ServiceWorkerProviderHost* CreateProviderHostWithInsecureParentFrame( + const GURL& document_url) { + std::unique_ptr<ServiceWorkerProviderHost> host = + CreateProviderHostForWindow(helper_->mock_render_process_id(), + next_provider_id_++, + false /* is_parent_frame_secure */, + helper_->context()->AsWeakPtr()); + ServiceWorkerProviderHost* host_raw = host.get(); + host->SetDocumentUrl(document_url); + context_->AddProviderHost(std::move(host)); + return host_raw; + } + TestBrowserThreadBundle thread_bundle_; std::unique_ptr<EmbeddedWorkerTestHelper> helper_; ServiceWorkerContextCore* context_; scoped_refptr<ServiceWorkerRegistration> registration1_; scoped_refptr<ServiceWorkerRegistration> registration2_; scoped_refptr<ServiceWorkerRegistration> registration3_; - base::WeakPtr<ServiceWorkerProviderHost> provider_host1_; - base::WeakPtr<ServiceWorkerProviderHost> provider_host2_; GURL script_url_; ServiceWorkerTestContentClient test_content_client_; TestContentBrowserClient test_content_browser_client_; ContentBrowserClient* old_content_browser_client_; + int next_provider_id_; private: DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderHostTest); }; TEST_F(ServiceWorkerProviderHostTest, PotentialRegistration_ProcessStatus) { + ServiceWorkerProviderHost* provider_host1 = + CreateProviderHost(GURL("https://www.example.com/example1.html")); + ServiceWorkerProviderHost* provider_host2 = + CreateProviderHost(GURL("https://www.example.com/example2.html")); + // Matching registrations have already been set by SetDocumentUrl. ASSERT_TRUE(PatternHasProcessToRun(registration1_->pattern())); @@ -115,93 +127,101 @@ ASSERT_TRUE(PatternHasProcessToRun(registration2_->pattern())); // Adding the same registration twice has no effect. - provider_host1_->AddMatchingRegistration(registration1_.get()); + provider_host1->AddMatchingRegistration(registration1_.get()); ASSERT_TRUE(PatternHasProcessToRun(registration1_->pattern())); // Removing a matching registration will decrease the process refs for its // pattern. - provider_host1_->RemoveMatchingRegistration(registration1_.get()); + provider_host1->RemoveMatchingRegistration(registration1_.get()); ASSERT_TRUE(PatternHasProcessToRun(registration1_->pattern())); - provider_host2_->RemoveMatchingRegistration(registration1_.get()); + provider_host2->RemoveMatchingRegistration(registration1_.get()); ASSERT_FALSE(PatternHasProcessToRun(registration1_->pattern())); // Matching registration will be removed when moving out of scope ASSERT_TRUE(PatternHasProcessToRun(registration2_->pattern())); // host1,2 ASSERT_FALSE(PatternHasProcessToRun(registration3_->pattern())); // no host - provider_host1_->SetDocumentUrl(GURL("https://other.example.com/")); + provider_host1->SetDocumentUrl(GURL("https://other.example.com/")); ASSERT_TRUE(PatternHasProcessToRun(registration2_->pattern())); // host2 ASSERT_TRUE(PatternHasProcessToRun(registration3_->pattern())); // host1 - provider_host2_->SetDocumentUrl(GURL("https://other.example.com/")); + provider_host2->SetDocumentUrl(GURL("https://other.example.com/")); ASSERT_FALSE(PatternHasProcessToRun(registration2_->pattern())); // no host ASSERT_TRUE(PatternHasProcessToRun(registration3_->pattern())); // host1,2 } TEST_F(ServiceWorkerProviderHostTest, AssociatedRegistration_ProcessStatus) { + ServiceWorkerProviderHost* provider_host1 = + CreateProviderHost(GURL("https://www.example.com/example1.html")); + // Associating the registration will also increase the process refs for // the registration's pattern. - provider_host1_->AssociateRegistration(registration1_.get(), - false /* notify_controllerchange */); + provider_host1->AssociateRegistration(registration1_.get(), + false /* notify_controllerchange */); ASSERT_TRUE(PatternHasProcessToRun(registration1_->pattern())); // Disassociating the registration shouldn't affect the process refs for // the registration's pattern. - provider_host1_->DisassociateRegistration(); + provider_host1->DisassociateRegistration(); ASSERT_TRUE(PatternHasProcessToRun(registration1_->pattern())); } TEST_F(ServiceWorkerProviderHostTest, MatchRegistration) { + ServiceWorkerProviderHost* provider_host1 = + CreateProviderHost(GURL("https://www.example.com/example1.html")); + // Match registration should return the longest matching one. - ASSERT_EQ(registration2_, provider_host1_->MatchRegistration()); - provider_host1_->RemoveMatchingRegistration(registration2_.get()); - ASSERT_EQ(registration1_, provider_host1_->MatchRegistration()); + ASSERT_EQ(registration2_, provider_host1->MatchRegistration()); + provider_host1->RemoveMatchingRegistration(registration2_.get()); + ASSERT_EQ(registration1_, provider_host1->MatchRegistration()); // Should return nullptr after removing all matching registrations. - provider_host1_->RemoveMatchingRegistration(registration1_.get()); - ASSERT_EQ(nullptr, provider_host1_->MatchRegistration()); + provider_host1->RemoveMatchingRegistration(registration1_.get()); + ASSERT_EQ(nullptr, provider_host1->MatchRegistration()); // SetDocumentUrl sets all of matching registrations - provider_host1_->SetDocumentUrl(GURL("https://www.example.com/example1")); - ASSERT_EQ(registration2_, provider_host1_->MatchRegistration()); - provider_host1_->RemoveMatchingRegistration(registration2_.get()); - ASSERT_EQ(registration1_, provider_host1_->MatchRegistration()); + provider_host1->SetDocumentUrl(GURL("https://www.example.com/example1")); + ASSERT_EQ(registration2_, provider_host1->MatchRegistration()); + provider_host1->RemoveMatchingRegistration(registration2_.get()); + ASSERT_EQ(registration1_, provider_host1->MatchRegistration()); // SetDocumentUrl with another origin also updates matching registrations - provider_host1_->SetDocumentUrl(GURL("https://other.example.com/example")); - ASSERT_EQ(registration3_, provider_host1_->MatchRegistration()); - provider_host1_->RemoveMatchingRegistration(registration3_.get()); - ASSERT_EQ(nullptr, provider_host1_->MatchRegistration()); + provider_host1->SetDocumentUrl(GURL("https://other.example.com/example")); + ASSERT_EQ(registration3_, provider_host1->MatchRegistration()); + provider_host1->RemoveMatchingRegistration(registration3_.get()); + ASSERT_EQ(nullptr, provider_host1->MatchRegistration()); } TEST_F(ServiceWorkerProviderHostTest, ContextSecurity) { - using FrameSecurityLevel = ServiceWorkerProviderHost::FrameSecurityLevel; + ServiceWorkerProviderHost* provider_host_secure_parent = + CreateProviderHost(GURL("https://www.example.com/example1.html")); + ServiceWorkerProviderHost* provider_host_insecure_parent = + CreateProviderHostWithInsecureParentFrame( + GURL("https://www.example.com/example1.html")); // Insecure document URL. - provider_host1_->SetDocumentUrl(GURL("http://host")); - provider_host1_->parent_frame_security_level_ = FrameSecurityLevel::SECURE; - EXPECT_FALSE(provider_host1_->IsContextSecureForServiceWorker()); + provider_host_secure_parent->SetDocumentUrl(GURL("http://host")); + EXPECT_FALSE(provider_host_secure_parent->IsContextSecureForServiceWorker()); // Insecure parent frame. - provider_host1_->SetDocumentUrl(GURL("https://host")); - provider_host1_->parent_frame_security_level_ = FrameSecurityLevel::INSECURE; - EXPECT_FALSE(provider_host1_->IsContextSecureForServiceWorker()); + provider_host_insecure_parent->SetDocumentUrl(GURL("https://host")); + EXPECT_FALSE( + provider_host_insecure_parent->IsContextSecureForServiceWorker()); // Secure URL and parent frame. - provider_host1_->SetDocumentUrl(GURL("https://host")); - provider_host1_->parent_frame_security_level_ = FrameSecurityLevel::SECURE; - EXPECT_TRUE(provider_host1_->IsContextSecureForServiceWorker()); + provider_host_secure_parent->SetDocumentUrl(GURL("https://host")); + EXPECT_TRUE(provider_host_secure_parent->IsContextSecureForServiceWorker()); // Exceptional service worker scheme. GURL url(std::string(kServiceWorkerScheme) + "://host"); EXPECT_TRUE(url.is_valid()); - provider_host1_->SetDocumentUrl(url); - provider_host1_->parent_frame_security_level_ = FrameSecurityLevel::SECURE; EXPECT_FALSE(IsOriginSecure(url)); EXPECT_TRUE(OriginCanAccessServiceWorkers(url)); - EXPECT_TRUE(provider_host1_->IsContextSecureForServiceWorker()); + provider_host_secure_parent->SetDocumentUrl(url); + EXPECT_TRUE(provider_host_secure_parent->IsContextSecureForServiceWorker()); // Exceptional service worker scheme with insecure parent frame. - provider_host1_->parent_frame_security_level_ = FrameSecurityLevel::INSECURE; - EXPECT_FALSE(provider_host1_->IsContextSecureForServiceWorker()); + provider_host_insecure_parent->SetDocumentUrl(url); + EXPECT_FALSE( + provider_host_insecure_parent->IsContextSecureForServiceWorker()); } } // namespace content
diff --git a/content/browser/service_worker/service_worker_registration_unittest.cc b/content/browser/service_worker/service_worker_registration_unittest.cc index 9e87cab..6e1b444 100644 --- a/content/browser/service_worker/service_worker_registration_unittest.cc +++ b/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -256,12 +256,9 @@ ASSERT_EQ(SERVICE_WORKER_OK, status); // Give the active version a controllee. - host_.reset(new ServiceWorkerProviderHost( - 33 /* dummy render process id */, - MSG_ROUTING_NONE /* render_frame_id */, 1 /* dummy provider_id */, - SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - context()->AsWeakPtr(), nullptr)); + host_ = CreateProviderHostForWindow( + 33 /* dummy render process id */, 1 /* dummy provider_id */, + true /* is_parent_frame_secure */, context()->AsWeakPtr()); version_1->AddControllee(host_.get()); // Give the active version an in-flight request.
diff --git a/content/browser/service_worker/service_worker_request_handler_unittest.cc b/content/browser/service_worker/service_worker_request_handler_unittest.cc index cdac7ba..93f795b 100644 --- a/content/browser/service_worker/service_worker_request_handler_unittest.cc +++ b/content/browser/service_worker/service_worker_request_handler_unittest.cc
@@ -42,15 +42,12 @@ helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath())); // An empty host. - std::unique_ptr<ServiceWorkerProviderHost> host( - new ServiceWorkerProviderHost( - helper_->mock_render_process_id(), MSG_ROUTING_NONE, - kMockProviderId, SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - context()->AsWeakPtr(), nullptr)); + std::unique_ptr<ServiceWorkerProviderHost> host = + CreateProviderHostForWindow( + helper_->mock_render_process_id(), kMockProviderId, + true /* is_parent_frame_secure */, context()->AsWeakPtr()); provider_host_ = host->AsWeakPtr(); context()->AddProviderHost(std::move(host)); - } void TearDown() override {
diff --git a/content/browser/service_worker/service_worker_storage_unittest.cc b/content/browser/service_worker/service_worker_storage_unittest.cc index 51e0cb6..4f8dfb48 100644 --- a/content/browser/service_worker/service_worker_storage_unittest.cc +++ b/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -1346,11 +1346,9 @@ registration_->SetActiveVersion(registration_->waiting_version()); storage()->UpdateToActiveState( registration_.get(), base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); - std::unique_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost( - 33 /* dummy render process id */, MSG_ROUTING_NONE, - 1 /* dummy provider_id */, SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - context()->AsWeakPtr(), NULL)); + std::unique_ptr<ServiceWorkerProviderHost> host = CreateProviderHostForWindow( + 33 /* dummy render process id */, 1 /* dummy provider_id */, + true /* is_parent_frame_secure */, context()->AsWeakPtr()); registration_->active_version()->AddControllee(host.get()); bool was_called = false; @@ -1398,11 +1396,9 @@ registration_->SetWaitingVersion(NULL); storage()->UpdateToActiveState( registration_.get(), base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); - std::unique_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost( - 33 /* dummy render process id */, MSG_ROUTING_NONE, - 1 /* dummy provider_id */, SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - context()->AsWeakPtr(), NULL)); + std::unique_ptr<ServiceWorkerProviderHost> host = CreateProviderHostForWindow( + 33 /* dummy render process id */, 1 /* dummy provider_id */, + true /* is_parent_frame_secure */, context()->AsWeakPtr()); registration_->active_version()->AddControllee(host.get()); bool was_called = false; @@ -1558,11 +1554,9 @@ registration_->SetActiveVersion(registration_->waiting_version()); storage()->UpdateToActiveState( registration_.get(), base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); - std::unique_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost( - 33 /* dummy render process id */, MSG_ROUTING_NONE, - 1 /* dummy provider_id */, SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - context()->AsWeakPtr(), NULL)); + std::unique_ptr<ServiceWorkerProviderHost> host = CreateProviderHostForWindow( + 33 /* dummy render process id */, 1 /* dummy provider_id */, + true /* is_parent_frame_secure */, helper_->context()->AsWeakPtr()); registration_->active_version()->AddControllee(host.get()); bool was_called = false;
diff --git a/content/browser/service_worker/service_worker_test_utils.cc b/content/browser/service_worker/service_worker_test_utils.cc new file mode 100644 index 0000000..e843910 --- /dev/null +++ b/content/browser/service_worker/service_worker_test_utils.cc
@@ -0,0 +1,50 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/service_worker/service_worker_test_utils.h" + +#include <utility> + +#include "content/browser/service_worker/service_worker_provider_host.h" + +namespace content { + +std::unique_ptr<ServiceWorkerProviderHost> CreateProviderHostForWindow( + int process_id, + int provider_id, + bool is_parent_frame_secure, + base::WeakPtr<ServiceWorkerContextCore> context) { + ServiceWorkerProviderHostInfo info(provider_id, MSG_ROUTING_NONE, + SERVICE_WORKER_PROVIDER_FOR_WINDOW, + is_parent_frame_secure); + return ServiceWorkerProviderHost::Create(process_id, std::move(info), + std::move(context), nullptr); +} + +std::unique_ptr<ServiceWorkerProviderHost> +CreateProviderHostForServiceWorkerContext( + int process_id, + int provider_id, + bool is_parent_frame_secure, + base::WeakPtr<ServiceWorkerContextCore> context) { + ServiceWorkerProviderHostInfo info(provider_id, MSG_ROUTING_NONE, + SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, + is_parent_frame_secure); + return ServiceWorkerProviderHost::Create(process_id, std::move(info), + std::move(context), nullptr); +} + +std::unique_ptr<ServiceWorkerProviderHost> CreateProviderHostWithDispatcherHost( + int process_id, + int provider_id, + base::WeakPtr<ServiceWorkerContextCore> context, + int route_id, + ServiceWorkerDispatcherHost* dispatcher_host) { + ServiceWorkerProviderHostInfo info(provider_id, route_id, + SERVICE_WORKER_PROVIDER_FOR_WINDOW, true); + return ServiceWorkerProviderHost::Create(process_id, std::move(info), + std::move(context), dispatcher_host); +} + +} // namespace content
diff --git a/content/browser/service_worker/service_worker_test_utils.h b/content/browser/service_worker/service_worker_test_utils.h index 467eaf03..279faf3 100644 --- a/content/browser/service_worker/service_worker_test_utils.h +++ b/content/browser/service_worker/service_worker_test_utils.h
@@ -5,15 +5,22 @@ #ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_TEST_UTILS_H_ #define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_TEST_UTILS_H_ +#include <memory> + #include "base/bind.h" #include "base/callback.h" #include "base/command_line.h" +#include "base/memory/weak_ptr.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/content_switches.h" #include "testing/gtest/include/gtest/gtest.h" namespace content { +class ServiceWorkerContextCore; +class ServiceWorkerDispatcherHost; +class ServiceWorkerProviderHost; + template <typename Arg> void ReceiveResult(BrowserThread::ID run_quit_thread, const base::Closure& quit, @@ -39,6 +46,26 @@ return base::Bind(&ReceiveResult<Arg>, id, quit, out); } +std::unique_ptr<ServiceWorkerProviderHost> CreateProviderHostForWindow( + int process_id, + int provider_id, + bool is_parent_frame_secure, + base::WeakPtr<ServiceWorkerContextCore> context); + +std::unique_ptr<ServiceWorkerProviderHost> +CreateProviderHostForServiceWorkerContext( + int process_id, + int provider_id, + bool is_parent_frame_secure, + base::WeakPtr<ServiceWorkerContextCore> context); + +std::unique_ptr<ServiceWorkerProviderHost> CreateProviderHostWithDispatcherHost( + int process_id, + int provider_id, + base::WeakPtr<ServiceWorkerContextCore> context, + int route_id, + ServiceWorkerDispatcherHost* dispatcher_host); + } // namespace content #endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_TEST_UTILS_H_
diff --git a/content/browser/service_worker/service_worker_url_request_job_unittest.cc b/content/browser/service_worker/service_worker_url_request_job_unittest.cc index 74d61e7..f9c23d4 100644 --- a/content/browser/service_worker/service_worker_url_request_job_unittest.cc +++ b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
@@ -195,12 +195,10 @@ version_->SetMainScriptHttpResponseInfo(http_info); } - std::unique_ptr<ServiceWorkerProviderHost> provider_host( - new ServiceWorkerProviderHost( - helper_->mock_render_process_id(), MSG_ROUTING_NONE, kProviderID, - SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - helper_->context()->AsWeakPtr(), nullptr)); + std::unique_ptr<ServiceWorkerProviderHost> provider_host = + CreateProviderHostForWindow( + helper_->mock_render_process_id(), kProviderID, + true /* is_parent_frame_secure */, helper_->context()->AsWeakPtr()); provider_host_ = provider_host->AsWeakPtr(); provider_host->SetDocumentUrl(GURL("https://example.com/")); registration_->SetActiveVersion(version_);
diff --git a/content/browser/service_worker/service_worker_version_unittest.cc b/content/browser/service_worker/service_worker_version_unittest.cc index 7558a4c5..6f4c737 100644 --- a/content/browser/service_worker/service_worker_version_unittest.cc +++ b/content/browser/service_worker/service_worker_version_unittest.cc
@@ -655,11 +655,9 @@ // Adding a controllee resets the idle time. version_->idle_time_ -= kOneSecond; idle_time = version_->idle_time_; - std::unique_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost( - 33 /* dummy render process id */, MSG_ROUTING_NONE /* render_frame_id */, - 1 /* dummy provider_id */, SERVICE_WORKER_PROVIDER_FOR_WINDOW, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - helper_->context()->AsWeakPtr(), NULL)); + std::unique_ptr<ServiceWorkerProviderHost> host = CreateProviderHostForWindow( + 33 /* dummy render process id */, 1 /* dummy provider_id */, + true /* is_parent_frame_secure */, helper_->context()->AsWeakPtr()); version_->AddControllee(host.get()); EXPECT_TRUE(version_->timeout_timer_.IsRunning()); EXPECT_LT(idle_time, version_->idle_time_); @@ -1130,10 +1128,7 @@ // Simulate renderer crash: do what // ServiceWorkerDispatcherHost::OnFilterRemoved does. - int process_id = helper_->mock_render_process_id(); - helper_->context()->RemoveAllProviderHostsForProcess(process_id); - helper_->context()->embedded_worker_registry()->RemoveChildProcessSender( - process_id); + helper_->context()->RemoveDispatcherHost(helper_->mock_render_process_id()); base::RunLoop().RunUntilIdle(); // Callback completed. @@ -1343,10 +1338,7 @@ // Simulate renderer crash: do what // ServiceWorkerDispatcherHost::OnFilterRemoved does. - int process_id = helper_->mock_render_process_id(); - helper_->context()->RemoveAllProviderHostsForProcess(process_id); - helper_->context()->embedded_worker_registry()->RemoveChildProcessSender( - process_id); + helper_->context()->RemoveDispatcherHost(helper_->mock_render_process_id()); base::RunLoop().RunUntilIdle(); // Callback completed.
diff --git a/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc b/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc index 494dee53..8fe5f13f3 100644 --- a/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc +++ b/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
@@ -290,12 +290,10 @@ int process_id, int provider_id, const scoped_refptr<ServiceWorkerVersion>& version) { - std::unique_ptr<ServiceWorkerProviderHost> host( - new ServiceWorkerProviderHost( - process_id, MSG_ROUTING_NONE, provider_id, - SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, - ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, - context()->AsWeakPtr(), nullptr)); + std::unique_ptr<ServiceWorkerProviderHost> host = + CreateProviderHostForServiceWorkerContext( + process_id, provider_id, true /* is_parent_frame_secure */, + context()->AsWeakPtr()); base::WeakPtr<ServiceWorkerProviderHost> provider_host = host->AsWeakPtr(); context()->AddProviderHost(std::move(host)); provider_host->running_hosted_version_ = version;
diff --git a/content/child/service_worker/service_worker_network_provider.cc b/content/child/service_worker/service_worker_network_provider.cc index 9e36b7d..555f509 100644 --- a/content/child/service_worker/service_worker_network_provider.cc +++ b/content/child/service_worker/service_worker_network_provider.cc
@@ -9,6 +9,7 @@ #include "content/child/service_worker/service_worker_provider_context.h" #include "content/common/navigation_params.h" #include "content/common/service_worker/service_worker_messages.h" +#include "content/common/service_worker/service_worker_provider_host_info.h" #include "content/common/service_worker/service_worker_utils.h" #include "content/public/common/browser_side_navigation_policy.h" #include "ipc/ipc_sync_channel.h" @@ -126,18 +127,14 @@ return; if (!ChildThreadImpl::current()) return; // May be null in some tests. + ServiceWorkerProviderHostInfo provider_info( + provider_id_, route_id, provider_type, is_parent_frame_secure); context_ = new ServiceWorkerProviderContext( provider_id_, provider_type, ChildThreadImpl::current()->thread_safe_sender()); - if (ServiceWorkerUtils::IsMojoForServiceWorkerEnabled()) { - ChildThreadImpl::current()->channel()->GetRemoteAssociatedInterface( - &dispatcher_host_); - dispatcher_host_->OnProviderCreated(provider_id_, route_id, provider_type, - is_parent_frame_secure); - } else { - ChildThreadImpl::current()->Send(new ServiceWorkerHostMsg_ProviderCreated( - provider_id_, route_id, provider_type, is_parent_frame_secure)); - } + ChildThreadImpl::current()->channel()->GetRemoteAssociatedInterface( + &dispatcher_host_); + dispatcher_host_->OnProviderCreated(std::move(provider_info)); } ServiceWorkerNetworkProvider::ServiceWorkerNetworkProvider( @@ -157,12 +154,7 @@ return; if (!ChildThreadImpl::current()) return; // May be null in some tests. - if (ServiceWorkerUtils::IsMojoForServiceWorkerEnabled()) { - dispatcher_host_->OnProviderDestroyed(provider_id()); - } else { - ChildThreadImpl::current()->Send( - new ServiceWorkerHostMsg_ProviderDestroyed(provider_id_)); - } + dispatcher_host_->OnProviderDestroyed(provider_id()); } void ServiceWorkerNetworkProvider::SetServiceWorkerVersionId( @@ -171,13 +163,8 @@ DCHECK_NE(kInvalidServiceWorkerProviderId, provider_id_); if (!ChildThreadImpl::current()) return; // May be null in some tests. - if (ServiceWorkerUtils::IsMojoForServiceWorkerEnabled()) { - dispatcher_host_->OnSetHostedVersionId(provider_id(), version_id, - embedded_worker_id); - } else { - ChildThreadImpl::current()->Send(new ServiceWorkerHostMsg_SetVersionId( - provider_id_, version_id, embedded_worker_id)); - } + dispatcher_host_->OnSetHostedVersionId(provider_id(), version_id, + embedded_worker_id); } bool ServiceWorkerNetworkProvider::IsControlledByServiceWorker() const {
diff --git a/content/child/service_worker/service_worker_network_provider.h b/content/child/service_worker/service_worker_network_provider.h index 099d80fd..c991aec 100644 --- a/content/child/service_worker/service_worker_network_provider.h +++ b/content/child/service_worker/service_worker_network_provider.h
@@ -15,7 +15,6 @@ #include "base/supports_user_data.h" #include "content/common/content_export.h" #include "content/common/service_worker/service_worker.mojom.h" -#include "content/common/service_worker/service_worker_types.h" namespace blink { class WebLocalFrame;
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index 6ccbdd5c..aef641f 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn
@@ -298,6 +298,8 @@ "service_worker/service_worker_client_info.cc", "service_worker/service_worker_client_info.h", "service_worker/service_worker_messages.h", + "service_worker/service_worker_provider_host_info.cc", + "service_worker/service_worker_provider_host_info.h", "service_worker/service_worker_status_code.cc", "service_worker/service_worker_status_code.h", "service_worker/service_worker_types.cc", @@ -582,6 +584,7 @@ "service_worker/embedded_worker.mojom", "service_worker/service_worker.mojom", "service_worker/service_worker_event_dispatcher.mojom", + "service_worker/service_worker_provider.mojom", "service_worker/service_worker_types.mojom", "storage_partition_service.mojom", "url_loader.mojom",
diff --git a/content/common/service_worker/OWNERS b/content/common/service_worker/OWNERS index f5a9a9f7..c19de06c 100644 --- a/content/common/service_worker/OWNERS +++ b/content/common/service_worker/OWNERS
@@ -11,6 +11,9 @@ per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS +per-file *_struct_traits*.*=set noparent +per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS + per-file *_type_converter*.*=set noparent per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS
diff --git a/content/common/service_worker/service_worker.mojom b/content/common/service_worker/service_worker.mojom index 840a3ef..cadade0 100644 --- a/content/common/service_worker/service_worker.mojom +++ b/content/common/service_worker/service_worker.mojom
@@ -4,18 +4,19 @@ module content.mojom; -import "content/common/service_worker/service_worker_types.mojom"; +import "content/common/service_worker/service_worker_provider.mojom"; // Per-process browser-side interface bound to ServiceWorkerDispatcherHost. // Each InterfacePtrs on the same render process will be bound to the same // ServiceWorkerDispatcherHost. interface ServiceWorkerDispatcherHost { - OnProviderCreated(int32 provider_id, - int32 route_id, - ServiceWorkerProviderType provider_type, - bool is_parent_frame_secure); + OnProviderCreated(ServiceWorkerProviderHostInfo provider_info); OnProviderDestroyed(int32 provider_id); - // Make relationship between the network provider and the service worker + + // Informs the browser that a service worker is starting up. |provider_id| + // identifies the ServiceWorkerProviderHost hosting the service + // worker. |version_id| identifies the ServiceWorkerVersion and + // |embedded_worker_id| identifies the EmbeddedWorkerInstance. OnSetHostedVersionId(int32 provider_id, int64 version_id, int32 embedded_worker_id);
diff --git a/content/common/service_worker/service_worker_messages.h b/content/common/service_worker/service_worker_messages.h index 9f5642f3..7cc0eee 100644 --- a/content/common/service_worker/service_worker_messages.h +++ b/content/common/service_worker/service_worker_messages.h
@@ -216,34 +216,6 @@ url::Origin /* source_origin */, std::vector<content::MessagePort> /* sent_message_ports */) -// Informs the browser of a new ServiceWorkerProvider in the child process, -// |provider_id| is unique within its child process. When this provider is -// created for a document, |route_id| is the frame ID of it. When this provider -// is created for a Shared Worker, |route_id| is the Shared Worker route ID. -// When this provider is created for a Service Worker, |route_id| is -// MSG_ROUTING_NONE. |provider_type| identifies whether this provider is for -// Service Worker controllees (documents and Shared Workers) or for controllers -// (Service Workers). -// -// |is_parent_frame_secure| is false if the provider is created for a -// document whose parent frame is not secure from the point of view of the -// document; that is, blink::WebFrame::canHaveSecureChild() returns false. -// This doesn't mean the document is necessarily an insecure context, -// because the document may have a URL whose scheme is granted an exception -// that allows bypassing the ancestor secure context check. See the -// comment in blink::Document::isSecureContextImpl for more details. -// If the provider is not created for a document, or the document does not have -// a parent frame, |is_parent_frame_secure| is true. -IPC_MESSAGE_CONTROL4(ServiceWorkerHostMsg_ProviderCreated, - int /* provider_id */, - int /* route_id */, - content::ServiceWorkerProviderType /* provider_type */, - bool /* is_parent_frame_secure */) - -// Informs the browser of a ServiceWorkerProvider being destroyed. -IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_ProviderDestroyed, - int /* provider_id */) - // Increments and decrements the ServiceWorker object's reference // counting in the browser side. The ServiceWorker object is created // with ref-count==1 initially. @@ -265,15 +237,6 @@ IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_TerminateWorker, int /* handle_id */) -// Informs the browser that a service worker is starting up in a provider. -// |provider_id| identifies the ServiceWorkerProviderHost hosting the service -// worker. |version_id| identifies the ServiceWorkerVersion and -// |embedded_worker_id| identifies the EmbeddedWorkerInstance. -IPC_MESSAGE_CONTROL3(ServiceWorkerHostMsg_SetVersionId, - int /* provider_id */, - int64_t /* version_id */, - int /* embedded_worker_id */) - // Informs the browser that event handling has finished. // Routed to the target ServiceWorkerVersion. IPC_MESSAGE_ROUTED4(ServiceWorkerHostMsg_InstallEventFinished,
diff --git a/content/common/service_worker/service_worker_provider.mojom b/content/common/service_worker/service_worker_provider.mojom new file mode 100644 index 0000000..6e512ed --- /dev/null +++ b/content/common/service_worker/service_worker_provider.mojom
@@ -0,0 +1,18 @@ +// 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. + +module content.mojom; + +import "content/common/service_worker/service_worker_types.mojom"; + +// A container object carried from the renderer to the browser process. +// This contains the params for the constructor of ServiceWorkerProviderHost. +// See also comments in +// content/common/service_worker/service_worker_provider_host_info.h. +struct ServiceWorkerProviderHostInfo { + int32 provider_id; + int32 route_id; + ServiceWorkerProviderType type; + bool is_parent_frame_secure; +}; \ No newline at end of file
diff --git a/content/common/service_worker/service_worker_provider.typemap b/content/common/service_worker/service_worker_provider.typemap new file mode 100644 index 0000000..757d4a7 --- /dev/null +++ b/content/common/service_worker/service_worker_provider.typemap
@@ -0,0 +1,12 @@ +# 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. + +mojom = "//content/common/service_worker/service_worker_provider.mojom" +public_headers = + [ "//content/common/service_worker/service_worker_provider_host_info.h" ] +traits_headers = [ "//content/common/service_worker/service_worker_provider_struct_traits.h" ] +sources = [ + "//content/common/service_worker/service_worker_provider_struct_traits.cc", +] +type_mappings = [ "content.mojom.ServiceWorkerProviderHostInfo=::content::ServiceWorkerProviderHostInfo[move_only]" ]
diff --git a/content/common/service_worker/service_worker_provider_host_info.cc b/content/common/service_worker/service_worker_provider_host_info.cc new file mode 100644 index 0000000..04a1887 --- /dev/null +++ b/content/common/service_worker/service_worker_provider_host_info.cc
@@ -0,0 +1,30 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/common/service_worker/service_worker_provider_host_info.h" + +namespace content { + +ServiceWorkerProviderHostInfo::ServiceWorkerProviderHostInfo() {} + +ServiceWorkerProviderHostInfo::ServiceWorkerProviderHostInfo( + ServiceWorkerProviderHostInfo&& other) + : provider_id(other.provider_id), + route_id(other.route_id), + type(other.type), + is_parent_frame_secure(other.is_parent_frame_secure) {} + +ServiceWorkerProviderHostInfo::ServiceWorkerProviderHostInfo( + int provider_id, + int route_id, + ServiceWorkerProviderType type, + bool is_parent_frame_secure) + : provider_id(provider_id), + route_id(route_id), + type(type), + is_parent_frame_secure(is_parent_frame_secure) {} + +ServiceWorkerProviderHostInfo::~ServiceWorkerProviderHostInfo() {} + +} // namespace content
diff --git a/content/common/service_worker/service_worker_provider_host_info.h b/content/common/service_worker/service_worker_provider_host_info.h new file mode 100644 index 0000000..106fb62 --- /dev/null +++ b/content/common/service_worker/service_worker_provider_host_info.h
@@ -0,0 +1,53 @@ +// 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 CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_HOST_INFO_H_ +#define CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_HOST_INFO_H_ + +#include "content/common/service_worker/service_worker_types.h" + +namespace content { + +struct CONTENT_EXPORT ServiceWorkerProviderHostInfo { + ServiceWorkerProviderHostInfo(); + ServiceWorkerProviderHostInfo(ServiceWorkerProviderHostInfo&& other); + ServiceWorkerProviderHostInfo(int provider_id, + int route_id, + ServiceWorkerProviderType type, + bool is_parent_frame_secure); + ~ServiceWorkerProviderHostInfo(); + + // This is unique within its child process except for PlzNavigate. When + // PlzNavigate is on, |provider_id| is managed on the browser process and it + // will be unique among all of providers. + int provider_id; + + // When this provider is created for a document, |route_id| is the frame ID of + // it. When this provider is created for a Shared Worker, |route_id| is the + // Shared Worker route ID. When this provider is created for a Service Worker, + // |route_id| is MSG_ROUTING_NONE. + int route_id; + + // This identifies whether this provider is for Service Worker controllees + // (documents and Shared Workers) or for controllers (Service Workers). + ServiceWorkerProviderType type; + + // |is_parent_frame_secure| is false if the provider is created for a document + // whose parent frame is not secure from the point of view of the document; + // that is, blink::WebFrame::canHaveSecureChild() returns false. This doesn't + // mean the document is necessarily an insecure context, because the document + // may have a URL whose scheme is granted an exception that allows bypassing + // the ancestor secure context check. See the comment in + // blink::Document::isSecureContextImpl for more details. If the provider is + // not created for a document, or the document does not have a parent frame, + // is_parent_frame_secure| is true. + bool is_parent_frame_secure; + + private: + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderHostInfo); +}; + +} // namespace content + +#endif // CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_HOST_INFO_H_
diff --git a/content/common/service_worker/service_worker_provider_struct_traits.cc b/content/common/service_worker/service_worker_provider_struct_traits.cc new file mode 100644 index 0000000..c4a4307 --- /dev/null +++ b/content/common/service_worker/service_worker_provider_struct_traits.cc
@@ -0,0 +1,22 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/common/service_worker/service_worker_provider_struct_traits.h" +#include "content/common/service_worker/service_worker_types_struct_traits.h" + +namespace mojo { + +bool StructTraits<content::mojom::ServiceWorkerProviderHostInfoDataView, + content::ServiceWorkerProviderHostInfo>:: + Read(content::mojom::ServiceWorkerProviderHostInfoDataView in, + content::ServiceWorkerProviderHostInfo* out) { + if (!in.ReadType(&out->type)) + return false; + out->provider_id = in.provider_id(); + out->route_id = in.route_id(); + out->is_parent_frame_secure = in.is_parent_frame_secure(); + return true; +} + +} // namespace mojo
diff --git a/content/common/service_worker/service_worker_provider_struct_traits.h b/content/common/service_worker/service_worker_provider_struct_traits.h new file mode 100644 index 0000000..e8cff44 --- /dev/null +++ b/content/common/service_worker/service_worker_provider_struct_traits.h
@@ -0,0 +1,40 @@ +// 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 CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_STRUCT_TRAITS_H_ +#define CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_STRUCT_TRAITS_H_ + +#include "content/common/service_worker/service_worker_provider.mojom.h" + +namespace mojo { + +template <> +struct StructTraits<content::mojom::ServiceWorkerProviderHostInfoDataView, + content::ServiceWorkerProviderHostInfo> { + static int32_t provider_id( + const content::ServiceWorkerProviderHostInfo& info) { + return info.provider_id; + } + + static int32_t route_id(const content::ServiceWorkerProviderHostInfo& info) { + return info.route_id; + } + + static content::ServiceWorkerProviderType type( + const content::ServiceWorkerProviderHostInfo& info) { + return info.type; + } + + static bool is_parent_frame_secure( + const content::ServiceWorkerProviderHostInfo& info) { + return info.is_parent_frame_secure; + } + + static bool Read(content::mojom::ServiceWorkerProviderHostInfoDataView in, + content::ServiceWorkerProviderHostInfo* out); +}; + +} // namespace mojo + +#endif // CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_STRUCT_TRAITS_H_
diff --git a/content/common/service_worker/service_worker_types.typemap b/content/common/service_worker/service_worker_types.typemap index 4ec79bbc..c4d4781 100644 --- a/content/common/service_worker/service_worker_types.typemap +++ b/content/common/service_worker/service_worker_types.typemap
@@ -5,8 +5,8 @@ mojom = "//content/common/service_worker/service_worker_types.mojom" public_headers = [ "//content/common/service_worker/service_worker_types.h" ] traits_headers = - [ "//content/common/service_worker/service_worker_types_traits.h" ] + [ "//content/common/service_worker/service_worker_types_struct_traits.h" ] sources = [ - "//content/common/service_worker/service_worker_types_traits.cc", + "//content/common/service_worker/service_worker_types_struct_traits.cc", ] type_mappings = [ "content.mojom.ServiceWorkerProviderType=::content::ServiceWorkerProviderType" ]
diff --git a/content/common/service_worker/service_worker_types_struct_traits.cc b/content/common/service_worker/service_worker_types_struct_traits.cc new file mode 100644 index 0000000..f88acbc --- /dev/null +++ b/content/common/service_worker/service_worker_types_struct_traits.cc
@@ -0,0 +1,24 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/common/service_worker/service_worker_types_struct_traits.h" + +namespace mojo { + +content::mojom::ServiceWorkerProviderType +EnumTraits<content::mojom::ServiceWorkerProviderType, + content::ServiceWorkerProviderType>:: + ToMojom(content::ServiceWorkerProviderType input) { + return static_cast<content::mojom::ServiceWorkerProviderType>(input); +} + +bool EnumTraits<content::mojom::ServiceWorkerProviderType, + content::ServiceWorkerProviderType>:: + FromMojom(content::mojom::ServiceWorkerProviderType input, + content::ServiceWorkerProviderType* out) { + *out = static_cast<content::ServiceWorkerProviderType>(input); + return true; +} + +} // namespace mojo
diff --git a/content/common/service_worker/service_worker_types_traits.h b/content/common/service_worker/service_worker_types_struct_traits.h similarity index 73% rename from content/common/service_worker/service_worker_types_traits.h rename to content/common/service_worker/service_worker_types_struct_traits.h index 18910a5..fb4670de5 100644 --- a/content/common/service_worker/service_worker_types_traits.h +++ b/content/common/service_worker/service_worker_types_struct_traits.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_TYPES_TRAITS_H_ -#define CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_TYPES_TRAITS_H_ +#ifndef CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_TYPES_STRUCT_TRAITS_H_ +#define CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_TYPES_STRUCT_TRAITS_H_ #include "content/common/service_worker/service_worker_types.mojom.h" @@ -21,4 +21,4 @@ } // namespace mojo -#endif // CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_TYPES_TRAITS_H_ +#endif // CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_TYPES_STRUCT_TRAITS_H_
diff --git a/content/common/service_worker/service_worker_types_traits.cc b/content/common/service_worker/service_worker_types_traits.cc deleted file mode 100644 index 1126308a..0000000 --- a/content/common/service_worker/service_worker_types_traits.cc +++ /dev/null
@@ -1,24 +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. - -#include "content/common/service_worker/service_worker_types_traits.h" - -namespace mojo { - -content::mojom::ServiceWorkerProviderType EnumTraits< - content::mojom::ServiceWorkerProviderType, - content::ServiceWorkerProviderType>::ToMojom( - content::ServiceWorkerProviderType input) { - return static_cast<content::mojom::ServiceWorkerProviderType>(input); -} - -bool EnumTraits<content::mojom::ServiceWorkerProviderType, - content::ServiceWorkerProviderType>::FromMojom( - content::mojom::ServiceWorkerProviderType input, - content::ServiceWorkerProviderType* out) { - *out = static_cast<content::ServiceWorkerProviderType>(input); - return true; -} - -} // namespace mojo
diff --git a/content/common/typemaps.gni b/content/common/typemaps.gni index 257c74c9..684e474 100644 --- a/content/common/typemaps.gni +++ b/content/common/typemaps.gni
@@ -7,6 +7,7 @@ "//content/common/media/media_devices.typemap", "//content/common/service_worker/embedded_worker.typemap", "//content/common/service_worker/service_worker_event_dispatcher.typemap", + "//content/common/service_worker/service_worker_provider.typemap", "//content/common/service_worker/service_worker_types.typemap", "//content/common/url_loader_status.typemap", "//content/common/url_request.typemap",
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index e7b7351..8d8206c 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -37,6 +37,7 @@ "../browser/media/session/mock_media_session_observer.h", "../browser/service_worker/embedded_worker_test_helper.cc", "../browser/service_worker/embedded_worker_test_helper.h", + "../browser/service_worker/service_worker_test_utils.cc", "../public/test/async_file_test_helper.cc", "../public/test/async_file_test_helper.h", "../public/test/background_sync_test_util.cc",
diff --git a/headless/README.md b/headless/README.md index 062106e..b16b69a5 100644 --- a/headless/README.md +++ b/headless/README.md
@@ -126,8 +126,11 @@ ## Resources and Documentation Mailing list: [headless-dev@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/headless-dev) + Bug tracker: [Proj=Headless](https://bugs.chromium.org/p/chromium/issues/list?can=2&q=Proj%3DHeadless) +[File a new bug](https://bugs.chromium.org/p/chromium/issues/entry?labels=Proj-Headless) + * [Runtime headless mode for Chrome](https://docs.google.com/document/d/1aIJUzQr3eougZQp90bp4mqGr5gY6hdUice8UPa-Ys90/edit#) * [Virtual Time in Blink](https://docs.google.com/document/d/1y9kdt_zezt7pbey6uzvt1dgklwc1ob_vy4nzo1zbqmo/edit#heading=h.tn3gd1y9ifml) * [Headless Chrome architecture](https://docs.google.com/document/d/11zIkKkLBocofGgoTeeyibB2TZ_k7nR78v7kNelCatUE/edit)
diff --git a/ios/chrome/app/chrome_app_startup_parameters.mm b/ios/chrome/app/chrome_app_startup_parameters.mm index f2384cf..74054b02 100644 --- a/ios/chrome/app/chrome_app_startup_parameters.mm +++ b/ios/chrome/app/chrome_app_startup_parameters.mm
@@ -257,6 +257,20 @@ secureSourceApp:secureSourceApp completeURL:url]; } + + if ([command + isEqualToString:base::SysUTF8ToNSString( + app_group::kChromeAppGroupFocusOmniboxCommand)]) { + ChromeAppStartupParameters* params = [[ChromeAppStartupParameters alloc] + initWithExternalURL:GURL(kChromeUINewTabURL) + xCallbackParameters:nil + declaredSourceApp:appId + secureSourceApp:secureSourceApp + completeURL:url]; + [params setLaunchFocusOmnibox:YES]; + return params; + } + if ([command isEqualToString:base::SysUTF8ToNSString( app_group::kChromeAppGroupOpenURLCommand)]) { if (!parameter || ![parameter isKindOfClass:[NSString class]])
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index fa2f5539..01120ac 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -259,12 +259,6 @@ // app. base::scoped_nsobject<AppStartupParameters> _startupParameters; - // Whether Voice Search should be started upon tab switcher dismissal. - BOOL _startVoiceSearchAfterTabSwitcherDismissal; - - // Whether the QR Scanner should be started upon tab switcher dismissal. - BOOL _startQRScannerAfterTabSwitcherDismissal; - // Navigation View controller for the settings. base::scoped_nsobject<SettingsNavigationController> _settingsNavigationController; @@ -372,6 +366,10 @@ // switcher dismissal. It can only be YES if the QR Scanner experiment is // enabled. @property(nonatomic, readwrite) BOOL startQRScannerAfterTabSwitcherDismissal; +// Whether the QR Scanner should be started upon tab switcher dismissal. +@property(nonatomic, readwrite) BOOL startVoiceSearchAfterTabSwitcherDismissal; +// Whether the omnibox should be focused upon tab switcher dismissal. +@property(nonatomic, readwrite) BOOL startFocusOmniboxAfterTabSwitcherDismissal; // Activates browsing and enables web views if |enabled| is YES. // Disables browsing and purges web views if |enabled| is NO. @@ -544,6 +542,12 @@ @synthesize window = _window; @synthesize isPresentingFirstRunUI = _isPresentingFirstRunUI; @synthesize isColdStart = _isColdStart; +@synthesize startVoiceSearchAfterTabSwitcherDismissal = + _startVoiceSearchAfterTabSwitcherDismissal; +@synthesize startQRScannerAfterTabSwitcherDismissal = + _startQRScannerAfterTabSwitcherDismissal; +@synthesize startFocusOmniboxAfterTabSwitcherDismissal = + _startFocusOmniboxAfterTabSwitcherDismissal; #pragma mark - Application lifecycle @@ -932,14 +936,6 @@ _settingsNavigationController.reset([settingsNavigationController retain]); } -- (BOOL)startQRScannerAfterTabSwitcherDismissal { - return _startQRScannerAfterTabSwitcherDismissal; -} - -- (void)setStartQRScannerAfterTabSwitcherDismissal:(BOOL)startQRScanner { - _startQRScannerAfterTabSwitcherDismissal = startQRScanner; -} - #pragma mark - StartupInformation implementation. - (FirstUserActionRecorder*)firstUserActionRecorder { @@ -1909,12 +1905,15 @@ // Start Voice Search or QR Scanner now that they can be presented from the // current BVC. - if (_startVoiceSearchAfterTabSwitcherDismissal) { - _startVoiceSearchAfterTabSwitcherDismissal = NO; + if (self.startVoiceSearchAfterTabSwitcherDismissal) { + self.startVoiceSearchAfterTabSwitcherDismissal = NO; [self.currentBVC startVoiceSearch]; - } else if ([self startQRScannerAfterTabSwitcherDismissal]) { - [self setStartQRScannerAfterTabSwitcherDismissal:NO]; + } else if (self.startQRScannerAfterTabSwitcherDismissal) { + self.startQRScannerAfterTabSwitcherDismissal = NO; [self.currentBVC showQRScanner]; + } else if (self.startFocusOmniboxAfterTabSwitcherDismissal) { + self.startFocusOmniboxAfterTabSwitcherDismissal = NO; + [self.currentBVC focusOmnibox]; } [_tabSwitcherController setDelegate:nil]; @@ -2291,8 +2290,8 @@ if (_tabSwitcherIsActive || _dismissingStackView) { // Since VoiceSearch is presented by the BVC, it must be started after the // Tab Switcher dismissal completes and the BVC's view is in the - // hiararchy. - _startVoiceSearchAfterTabSwitcherDismissal = YES; + // hierarchy. + self.startVoiceSearchAfterTabSwitcherDismissal = YES; } else { // When starting the application from the Notification center, // ApplicationWillResignActive is sent just after startup. @@ -2306,7 +2305,7 @@ if (_tabSwitcherIsActive || _dismissingStackView) { // QR Scanner is presented by the BVC, similarly to VoiceSearch. It must // also be started after the BVC's view is in the hierarchy. - [self setStartQRScannerAfterTabSwitcherDismissal:YES]; + self.startQRScannerAfterTabSwitcherDismissal = YES; } else { // Start the QR Scanner asynchronously to prevent the application from // dismissing the modal view if QR Scanner is started from the @@ -2315,6 +2314,14 @@ [self.currentBVC showQRScanner]; }); } + } else if ([_startupParameters launchFocusOmnibox]) { + if (_tabSwitcherIsActive || _dismissingStackView) { + self.startFocusOmniboxAfterTabSwitcherDismissal = YES; + } else { + dispatch_async(dispatch_get_main_queue(), ^{ + [self.currentBVC focusOmnibox]; + }); + } } if (_restoreHelper) {
diff --git a/ios/chrome/browser/app_startup_parameters.h b/ios/chrome/browser/app_startup_parameters.h index a020265..2d99fe5 100644 --- a/ios/chrome/browser/app_startup_parameters.h +++ b/ios/chrome/browser/app_startup_parameters.h
@@ -25,6 +25,8 @@ @property(nonatomic, readwrite, assign) BOOL launchVoiceSearch; // Boolean to track if the app should launch in incognito mode. @property(nonatomic, readwrite, assign) BOOL launchInIncognito; +// Boolean to track if the omnibox should be focused on startup. +@property(nonatomic, readwrite, assign) BOOL launchFocusOmnibox; // Boolean to track if a QR scanner is requested at startup. @property(nonatomic, readwrite, assign) BOOL launchQRScanner;
diff --git a/ios/chrome/browser/app_startup_parameters.mm b/ios/chrome/browser/app_startup_parameters.mm index 19c4381..0ae884d 100644 --- a/ios/chrome/browser/app_startup_parameters.mm +++ b/ios/chrome/browser/app_startup_parameters.mm
@@ -14,14 +14,13 @@ @implementation AppStartupParameters { GURL _externalURL; - BOOL _launchVoiceSearch; - BOOL _launchInIncognito; - BOOL _launchQRScanner; } @synthesize launchVoiceSearch = _launchVoiceSearch; @synthesize launchInIncognito = _launchInIncognito; @synthesize xCallbackParameters = _xCallbackParameters; +@synthesize launchFocusOmnibox = _launchFocusOmnibox; +@synthesize launchQRScanner = _launchQRScanner; - (const GURL&)externalURL { return _externalURL; @@ -48,19 +47,27 @@ } - (NSString*)description { - return [NSString stringWithFormat:@"ExternalURL: %s \nXCallbackParams: %@", - _externalURL.spec().c_str(), - _xCallbackParameters]; -} + NSMutableString* description = [NSMutableString + stringWithFormat:@"ExternalURL: %s \nXCallbackParams: %@", + _externalURL.spec().c_str(), _xCallbackParameters]; -#pragma mark Property implementation. + if (self.launchQRScanner) { + [description appendString:@", should launch QR scanner"]; + } -- (BOOL)launchQRScanner { - return _launchQRScanner; -} + if (self.launchInIncognito) { + [description appendString:@", should launch in incognito"]; + } -- (void)setLaunchQRScanner:(BOOL)launch { - _launchQRScanner = launch; + if (self.launchFocusOmnibox) { + [description appendString:@", should focus omnibox"]; + } + + if (self.launchVoiceSearch) { + [description appendString:@", should launch voice search"]; + } + + return description; } @end
diff --git a/ios/chrome/browser/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/content_suggestions/content_suggestions_coordinator.mm index e7ac5c6..ee85ec4 100644 --- a/ios/chrome/browser/content_suggestions/content_suggestions_coordinator.mm +++ b/ios/chrome/browser/content_suggestions/content_suggestions_coordinator.mm
@@ -93,9 +93,6 @@ - (void)openFirstPageOfReadingList { } -- (void)addEmptyItem { -} - - (void)openFaviconAtIndex:(NSInteger)index { }
diff --git a/ios/chrome/browser/content_suggestions/content_suggestions_mediator.mm b/ios/chrome/browser/content_suggestions/content_suggestions_mediator.mm index 242f0e64..6a6d4b1a 100644 --- a/ios/chrome/browser/content_suggestions/content_suggestions_mediator.mm +++ b/ios/chrome/browser/content_suggestions/content_suggestions_mediator.mm
@@ -14,7 +14,6 @@ #import "ios/chrome/browser/content_suggestions/content_suggestions_service_bridge_observer.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestion.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_data_sink.h" -#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_item.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_section_information.h" #include "ui/gfx/image/image.h"
diff --git a/ios/chrome/browser/favicon/favicon_service_factory.cc b/ios/chrome/browser/favicon/favicon_service_factory.cc index 0c72fd5..2732a769 100644 --- a/ios/chrome/browser/favicon/favicon_service_factory.cc +++ b/ios/chrome/browser/favicon/favicon_service_factory.cc
@@ -58,4 +58,8 @@ browser_state, ServiceAccessType::EXPLICIT_ACCESS)); } +bool FaviconServiceFactory::ServiceIsNULLWhileTesting() const { + return true; +} + } // namespace ios
diff --git a/ios/chrome/browser/favicon/favicon_service_factory.h b/ios/chrome/browser/favicon/favicon_service_factory.h index 8d81f8c..dc8661d 100644 --- a/ios/chrome/browser/favicon/favicon_service_factory.h +++ b/ios/chrome/browser/favicon/favicon_service_factory.h
@@ -43,6 +43,7 @@ // BrowserStateKeyedServiceFactory implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( web::BrowserState* context) const override; + bool ServiceIsNULLWhileTesting() const override; DISALLOW_COPY_AND_ASSIGN(FaviconServiceFactory); };
diff --git a/ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.cc b/ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.cc index 1125c07d..5d01fb2 100644 --- a/ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.cc +++ b/ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.cc
@@ -32,7 +32,9 @@ IOSChromeLargeIconServiceFactory::IOSChromeLargeIconServiceFactory() : BrowserStateKeyedServiceFactory( "LargeIconService", - BrowserStateDependencyManager::GetInstance()) {} + BrowserStateDependencyManager::GetInstance()) { + DependsOn(ios::FaviconServiceFactory::GetInstance()); +} IOSChromeLargeIconServiceFactory::~IOSChromeLargeIconServiceFactory() {} @@ -52,3 +54,7 @@ web::BrowserState* context) const { return GetBrowserStateOwnInstanceInIncognito(context); } + +bool IOSChromeLargeIconServiceFactory::ServiceIsNULLWhileTesting() const { + return true; +}
diff --git a/ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h b/ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h index d6883a7..071e3f1 100644 --- a/ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h +++ b/ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h
@@ -46,6 +46,7 @@ web::BrowserState* context) const override; web::BrowserState* GetBrowserStateToUse( web::BrowserState* context) const override; + bool ServiceIsNULLWhileTesting() const override; DISALLOW_COPY_AND_ASSIGN(IOSChromeLargeIconServiceFactory); };
diff --git a/ios/chrome/browser/ui/browser_view_controller.h b/ios/chrome/browser/ui/browser_view_controller.h index 2ee314f..4b004dd 100644 --- a/ios/chrome/browser/ui/browser_view_controller.h +++ b/ios/chrome/browser/ui/browser_view_controller.h
@@ -139,6 +139,9 @@ // Shows the QR scanner UI. - (void)showQRScanner; +// Focuses the omnibox. +- (void)focusOmnibox; + // Dismisses all presented views then calls |completion|. - (void)clearPresentedStateWithCompletion:(ProceduralBlock)completion;
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 394aefd..dedf5a9 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -133,8 +133,8 @@ #import "ios/chrome/browser/ui/print/print_controller.h" #import "ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller.h" #import "ios/chrome/browser/ui/reading_list/offline_page_native_content.h" +#import "ios/chrome/browser/ui/reading_list/reading_list_coordinator.h" #import "ios/chrome/browser/ui/reading_list/reading_list_menu_notifier.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_view_controller_builder.h" #include "ios/chrome/browser/ui/rtl_geometry.h" #import "ios/chrome/browser/ui/side_swipe/side_swipe_controller.h" #import "ios/chrome/browser/ui/stack_view/card_view.h" @@ -403,6 +403,9 @@ // Used to display the QR Scanner UI. Nil if not visible. base::scoped_nsobject<QRScannerViewController> _qrScannerViewController; + // Used to display the Reading List. + base::scoped_nsobject<ReadingListCoordinator> _readingListCoordinator; + // Used to display the Suggestions. base::scoped_nsobject<ContentSuggestionsCoordinator> _contentSuggestionsCoordinator; @@ -1281,7 +1284,9 @@ self.typingShield = nil; if (_voiceSearchController.get()) _voiceSearchController->SetDelegate(nil); + _contentSuggestionsCoordinator.reset(); _qrScannerViewController.reset(); + _readingListCoordinator.reset(); _toolbarController.reset(); _toolbarModelDelegate.reset(); _toolbarModelIOS.reset(); @@ -4228,10 +4233,12 @@ - (void)showReadingList { DCHECK(reading_list::switches::IsReadingListEnabled()); - UIViewController* vc = [ReadingListViewControllerBuilder - readingListViewControllerInBrowserState:self.browserState - loader:self]; - [self presentViewController:vc animated:YES completion:nil]; + _readingListCoordinator.reset([[ReadingListCoordinator alloc] + initWithBaseViewController:self + browserState:self.browserState + loader:self]); + + [_readingListCoordinator start]; } - (void)showQRScanner {
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn index 5e2ce300..e35648b 100644 --- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn +++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -20,14 +20,14 @@ "content_suggestions_favicon_internal_cell.mm", "content_suggestions_favicon_item.h", "content_suggestions_favicon_item.mm", - "content_suggestions_item.h", - "content_suggestions_item.mm", - "content_suggestions_item_actions.h", "content_suggestions_section_information.h", "content_suggestions_section_information.mm", "content_suggestions_stack_item.h", "content_suggestions_stack_item.mm", "content_suggestions_stack_item_actions.h", + "content_suggestions_text_item.h", + "content_suggestions_text_item.mm", + "content_suggestions_text_item_actions.h", "content_suggestions_view_controller.h", "content_suggestions_view_controller.mm", "expandable_item.h", @@ -52,8 +52,8 @@ "content_suggestions_article_item_unittest.mm", "content_suggestions_expandable_item_unittest.mm", "content_suggestions_favicon_item_unittest.mm", - "content_suggestions_item_unittest.mm", "content_suggestions_stack_item_unittest.mm", + "content_suggestions_text_item_unittest.mm", ] deps = [ ":content_suggestions",
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.h index dfa156e1..f1c79f6 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.h
@@ -28,13 +28,6 @@ @property(nonatomic, assign) ContentSuggestionsViewController* collectionViewController; -// Adds a text item with a |title| and a |subtitle| in the section numbered -// |section|. If |section| is greater than the current number of section, it -// will add a new section at the end. -- (void)addTextItem:(NSString*)title - subtitle:(NSString*)subtitle - toSection:(NSInteger)inputSection; - // Returns whether the section should use the default, non-card style. - (BOOL)shouldUseCustomStyleForSection:(NSInteger)section;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm index 84b07616..210b089 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm
@@ -15,9 +15,9 @@ #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_data_source.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_expandable_item.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_favicon_item.h" -#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_item.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_section_information.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_stack_item.h" +#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_text_item.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h" #include "url/gurl.h" @@ -126,42 +126,6 @@ #pragma mark - Public methods -- (void)addTextItem:(NSString*)title - subtitle:(NSString*)subtitle - toSection:(NSInteger)inputSection { - DCHECK(self.collectionViewController); - ContentSuggestionsItem* item = - [[ContentSuggestionsItem alloc] initWithType:ItemTypeText - title:title - subtitle:subtitle]; - NSInteger sectionIdentifier = kSectionIdentifierEnumZero + inputSection; - NSInteger sectionIndex = inputSection; - CollectionViewModel* model = - self.collectionViewController.collectionViewModel; - if ([model numberOfSections] <= inputSection) { - sectionIndex = [model numberOfSections]; - sectionIdentifier = kSectionIdentifierEnumZero + sectionIndex; - [self.collectionViewController.collectionView performBatchUpdates:^{ - [self.collectionViewController.collectionViewModel - addSectionWithIdentifier:sectionIdentifier]; - [self.collectionViewController.collectionView - insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]]; - } - completion:nil]; - } - NSInteger numberOfItemsInSection = - [model numberOfItemsInSection:sectionIndex]; - [self.collectionViewController.collectionViewModel addItem:item - toSectionWithIdentifier:sectionIdentifier]; - [self.collectionViewController.collectionView performBatchUpdates:^{ - [self.collectionViewController.collectionView - insertItemsAtIndexPaths:@[ [NSIndexPath - indexPathForRow:numberOfItemsInSection - inSection:sectionIndex] ]]; - } - completion:nil]; -} - - (BOOL)shouldUseCustomStyleForSection:(NSInteger)section { NSNumber* identifier = @([self.collectionViewController.collectionViewModel sectionIdentifierForSection:section]);
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h index 19eda28..7c11505 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h
@@ -11,8 +11,6 @@ // Commands protocol for the ContentSuggestionsViewController. @protocol ContentSuggestionsCommands -// Adds a new empty SuggestionItem. -- (void)addEmptyItem; // Opens the Reading List. - (void)openReadingList; // Opens the first page of the Reading List.
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_item.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_text_item.h similarity index 85% rename from ios/chrome/browser/ui/content_suggestions/content_suggestions_item.h rename to ios/chrome/browser/ui/content_suggestions/content_suggestions_text_item.h index 87b27e3..f2f8752 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_item.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_text_item.h
@@ -2,14 +2,14 @@ // 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_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_ITEM_H_ -#define IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_ITEM_H_ +#ifndef IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_TEXT_ITEM_H_ +#define IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_TEXT_ITEM_H_ #import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" #import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h" // Item for a suggestions item with a title and subtitle. -@interface ContentSuggestionsItem : CollectionViewItem +@interface ContentSuggestionsTextItem : CollectionViewItem // Init a suggestions item with a |title| and a |subtitle|. |type| is the type // of the item. @@ -21,11 +21,11 @@ @end // Corresponding cell for a suggestion item. -@interface ContentSuggestionsCell : MDCCollectionViewCell +@interface ContentSuggestionsTextCell : MDCCollectionViewCell @property(nonatomic, readonly, strong) UIButton* titleButton; @property(nonatomic, readonly, strong) UILabel* detailTextLabel; @end -#endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_ITEM_H_ +#endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_TEXT_ITEM_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_item.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_text_item.mm similarity index 88% rename from ios/chrome/browser/ui/content_suggestions/content_suggestions_item.mm rename to ios/chrome/browser/ui/content_suggestions/content_suggestions_text_item.mm index abc84257..96f6e678 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_item.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_text_item.mm
@@ -2,9 +2,9 @@ // 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/content_suggestions/content_suggestions_item.h" +#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_text_item.h" -#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_item_actions.h" +#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_text_item_actions.h" #import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" #import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" @@ -12,14 +12,14 @@ #error "This file requires ARC support." #endif -@interface ContentSuggestionsItem () +@interface ContentSuggestionsTextItem () @property(nonatomic, copy) NSString* title; @property(nonatomic, copy) NSString* subtitle; @end -@implementation ContentSuggestionsItem +@implementation ContentSuggestionsTextItem @synthesize title = _title; @synthesize subtitle = _subtitle; @@ -29,7 +29,7 @@ subtitle:(NSString*)subtitle { self = [super initWithType:type]; if (self) { - self.cellClass = [ContentSuggestionsCell class]; + self.cellClass = [ContentSuggestionsTextCell class]; _title = [title copy]; _subtitle = [subtitle copy]; } @@ -38,7 +38,7 @@ #pragma mark - CollectionViewItem -- (void)configureCell:(ContentSuggestionsCell*)cell { +- (void)configureCell:(ContentSuggestionsTextCell*)cell { [super configureCell:cell]; [cell.titleButton setTitle:self.title forState:UIControlStateNormal]; cell.detailTextLabel.text = self.subtitle; @@ -46,9 +46,9 @@ @end -#pragma mark - ContentSuggestionsCell +#pragma mark - ContentSuggestionsTextCell -@implementation ContentSuggestionsCell +@implementation ContentSuggestionsTextCell @synthesize titleButton = _titleButton; @synthesize detailTextLabel = _detailTextLabel; @@ -61,7 +61,7 @@ _titleButton.titleLabel.font = [fontLoader mediumFontOfSize:16]; _titleButton.titleLabel.textColor = [[MDCPalette greyPalette] tint900]; [_titleButton addTarget:nil - action:@selector(addNewItem:) + action:@selector(addNewTextItem:) forControlEvents:UIControlEventTouchUpInside]; _detailTextLabel = [[UILabel alloc] init];
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_item_actions.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_text_item_actions.h similarity index 76% rename from ios/chrome/browser/ui/content_suggestions/content_suggestions_item_actions.h rename to ios/chrome/browser/ui/content_suggestions/content_suggestions_text_item_actions.h index 0d1a80cd..64018d5 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_item_actions.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_text_item_actions.h
@@ -2,17 +2,17 @@ // 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_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_ITEM_ACTIONS_H_ -#define IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_ITEM_ACTIONS_H_ +#ifndef IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_TEXT_ITEM_ACTIONS_H_ +#define IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_TEXT_ITEM_ACTIONS_H_ // Protocol handling the actions sent in the responder chain by the suggestions // items. -@protocol SuggestionsItemActions +@protocol ContentSuggestionsTextItemActions // Sent through the responder chain when the button of a suggestion item is // pressed. -- (void)addNewItem:(id)sender; +- (void)addNewTextItem:(id)sender; @end -#endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_ITEM_ACTIONS_H_ +#endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_TEXT_ITEM_ACTIONS_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_item_unittest.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_text_item_unittest.mm similarity index 62% rename from ios/chrome/browser/ui/content_suggestions/content_suggestions_item_unittest.mm rename to ios/chrome/browser/ui/content_suggestions/content_suggestions_text_item_unittest.mm index dbac1dcb..296d2c9 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_item_unittest.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_text_item_unittest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_item.h" +#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_text_item.h" #include "testing/gtest/include/gtest/gtest.h" @@ -13,15 +13,15 @@ namespace { // Tests that configureCell: set all the fields of the cell. -TEST(ContentSuggestionsItemTest, CellIsConfigured) { +TEST(ContentSuggestionsTextItemTest, CellIsConfigured) { NSString* title = @"testTitle"; NSString* subtitle = @"testSubtitle"; - ContentSuggestionsItem* item = - [[ContentSuggestionsItem alloc] initWithType:0 - title:title - subtitle:subtitle]; - ContentSuggestionsCell* cell = [[[item cellClass] alloc] init]; - EXPECT_EQ([ContentSuggestionsCell class], [cell class]); + ContentSuggestionsTextItem* item = + [[ContentSuggestionsTextItem alloc] initWithType:0 + title:title + subtitle:subtitle]; + ContentSuggestionsTextCell* cell = [[[item cellClass] alloc] init]; + EXPECT_EQ([ContentSuggestionsTextCell class], [cell class]); [item configureCell:cell]; EXPECT_EQ(title, [cell.titleButton titleForState:UIControlStateNormal]);
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h index b078851e..e25bdb9 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h
@@ -30,13 +30,6 @@ @property(nonatomic, weak) id<ContentSuggestionsCommands> suggestionCommandHandler; -// Adds a text item with a |title| and a |subtitle| in the section numbered -// |section|. If |section| is greater than the current number of section, it -// will add a new section at the end. -- (void)addTextItem:(NSString*)title - subtitle:(NSString*)subtitle - toSection:(NSInteger)inputSection; - @end #endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_VIEW_CONTROLLER_H_
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 e6ff832..3fb509f 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
@@ -12,9 +12,9 @@ #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_article_item.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h" -#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_item_actions.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_stack_item.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_stack_item_actions.h" +#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_text_item_actions.h" #import "ios/chrome/browser/ui/content_suggestions/expandable_item.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -25,8 +25,7 @@ const NSTimeInterval kAnimationDuration = 0.35; } // namespace -@interface ContentSuggestionsViewController ()<SuggestionsItemActions, - SuggestionsStackItemActions> +@interface ContentSuggestionsViewController ()<SuggestionsStackItemActions> @property(nonatomic, strong) ContentSuggestionsCollectionUpdater* collectionUpdater; @@ -101,22 +100,6 @@ [self.suggestionCommandHandler openFaviconAtIndex:innerIndexPath.item]; } -#pragma mark - SuggestionsItemActions - -- (void)addNewItem:(id)sender { - [self.suggestionCommandHandler addEmptyItem]; -} - -#pragma mark - ContentSuggestionsCollectionUpdater forwarding - -- (void)addTextItem:(NSString*)title - subtitle:(NSString*)subtitle - toSection:(NSInteger)inputSection { - [self.collectionUpdater addTextItem:title - subtitle:subtitle - toSection:inputSection]; -} - #pragma mark - SuggestionsStackItemActions - (void)openReadingListFirstItem:(id)sender {
diff --git a/ios/chrome/browser/ui/reading_list/BUILD.gn b/ios/chrome/browser/ui/reading_list/BUILD.gn index fa75f37d..5927059 100644 --- a/ios/chrome/browser/ui/reading_list/BUILD.gn +++ b/ios/chrome/browser/ui/reading_list/BUILD.gn
@@ -39,6 +39,8 @@ "reading_list_collection_view_controller.mm", "reading_list_collection_view_item.h", "reading_list_collection_view_item.mm", + "reading_list_coordinator.h", + "reading_list_coordinator.mm", "reading_list_empty_collection_background.h", "reading_list_empty_collection_background.mm", "reading_list_menu_notification_delegate.h", @@ -50,8 +52,6 @@ "reading_list_toolbar.mm", "reading_list_view_controller.h", "reading_list_view_controller.mm", - "reading_list_view_controller_builder.h", - "reading_list_view_controller_builder.mm", ] deps = [ ":resources", @@ -97,7 +97,7 @@ sources = [ "offline_page_native_content_unittest.mm", "reading_list_collection_view_controller_unittest.mm", - "reading_list_view_controller_unittest.mm", + "reading_list_coordinator_unittest.mm", ] deps = [ ":reading_list",
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h index d4b201f..8f33301 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h +++ b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h
@@ -21,16 +21,17 @@ class ReadingListModel; @class TabModel; -// Delegate for the ReadingListCollectionViewController, managing the visibility -// of the -// toolbar, dismissing the Reading List View and opening elements. -@protocol ReadingListCollectionViewControllerDelegate<NSObject> +// Audience for the ReadingListCollectionViewController +@protocol ReadingListCollectionViewControllerAudience // Whether the collection has items. -- (void)readingListCollectionViewController: - (ReadingListCollectionViewController*) - readingListCollectionViewController - hasItems:(BOOL)hasItems; +- (void)readingListHasItems:(BOOL)hasItems; + +@end + +// Delegate for the ReadingListCollectionViewController, managing the visibility +// of the toolbar, dismissing the Reading List View and opening elements. +@protocol ReadingListCollectionViewControllerDelegate<NSObject> // Dismisses the Reading List View. - (void)dismissReadingListCollectionViewController: @@ -69,6 +70,9 @@ @property(nonatomic, weak) id<ReadingListCollectionViewControllerDelegate> delegate; +@property(nonatomic, weak) id<ReadingListCollectionViewControllerAudience> + audience; + @property(nonatomic, readonly) ReadingListModel* readingListModel; @property(nonatomic, readonly) favicon::LargeIconService* largeIconService; @property(nonatomic, readonly)
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm index 85237d7b..2ff56c1a 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm
@@ -175,12 +175,16 @@ @end @implementation ReadingListCollectionViewController + +@synthesize audience = _audience; +@synthesize delegate = _delegate; + @synthesize readingListModel = _readingListModel; @synthesize largeIconService = _largeIconService; @synthesize readingListDownloadService = _readingListDownloadService; @synthesize attributesProvider = _attributesProvider; -@synthesize delegate = _delegate; @synthesize shouldMonitorModel = _shouldMonitorModel; + #pragma mark lifecycle - (instancetype)initWithModel:(ReadingListModel*)model @@ -228,13 +232,11 @@ [_toolbar setState:toolbarState]; } -- (void)setDelegate:(id<ReadingListCollectionViewControllerDelegate>)delegate { - _delegate = delegate; - if (self.readingListModel->loaded()) - [delegate - readingListCollectionViewController:self - hasItems:(self.readingListModel->size() > - 0)]; +- (void)setAudience:(id<ReadingListCollectionViewControllerAudience>)audience { + _audience = audience; + if (self.readingListModel->loaded()) { + [audience readingListHasItems:(self.readingListModel->size() > 0)]; + } } #pragma mark - UIViewController @@ -412,7 +414,7 @@ self.collectionView.alwaysBounceVertical = YES; [self loadItems]; self.collectionView.backgroundView = nil; - [self.delegate readingListCollectionViewController:self hasItems:YES]; + [self.audience readingListHasItems:YES]; } } @@ -546,7 +548,7 @@ // The collection is empty, add background. self.collectionView.alwaysBounceVertical = NO; self.collectionView.backgroundView = _emptyCollectionBackground; - [self.delegate readingListCollectionViewController:self hasItems:NO]; + [self.audience readingListHasItems:NO]; } - (void)handleLongPress:(UILongPressGestureRecognizer*)gestureRecognizer {
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_coordinator.h b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.h new file mode 100644 index 0000000..1d6480b --- /dev/null +++ b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.h
@@ -0,0 +1,32 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_COORDINATOR_H_ +#define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_COORDINATOR_H_ + +#import "ios/chrome/browser/chrome_coordinator.h" +#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h" + +namespace ios { +class ChromeBrowserState; +} + +@protocol UrlLoader; + +// Coordinator for Reading List, displaying the Reading List when starting. +@interface ReadingListCoordinator + : ChromeCoordinator<ReadingListCollectionViewControllerDelegate> + +- (nullable instancetype) +initWithBaseViewController:(nullable UIViewController*)viewController + browserState:(nonnull ios::ChromeBrowserState*)browserState + loader:(nullable id<UrlLoader>)loader + NS_DESIGNATED_INITIALIZER; + +- (nullable instancetype)initWithBaseViewController: + (nullable UIViewController*)viewController NS_UNAVAILABLE; + +@end + +#endif // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm new file mode 100644 index 0000000..1958db5 --- /dev/null +++ b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm
@@ -0,0 +1,289 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/reading_list/reading_list_coordinator.h" + +#include "base/metrics/histogram_macros.h" +#include "base/metrics/user_metrics.h" +#include "base/metrics/user_metrics_action.h" +#include "components/reading_list/ios/reading_list_model.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" +#include "ios/chrome/browser/reading_list/offline_url_utils.h" +#include "ios/chrome/browser/reading_list/reading_list_download_service.h" +#include "ios/chrome/browser/reading_list/reading_list_download_service_factory.h" +#include "ios/chrome/browser/reading_list/reading_list_model_factory.h" +#import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h" +#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h" +#import "ios/chrome/browser/ui/reading_list/reading_list_toolbar.h" +#import "ios/chrome/browser/ui/reading_list/reading_list_view_controller.h" +#import "ios/chrome/browser/ui/url_loader.h" +#import "ios/chrome/browser/ui/util/pasteboard_util.h" +#include "ios/chrome/grit/ios_strings.h" +#include "ios/web/public/referrer.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/strings/grit/ui_strings.h" +#include "url/gurl.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +// Action chosen by the user in the context menu, for UMA report. +// These match tools/metrics/histograms/histograms.xml. +enum UMAContextMenuAction { + // The user opened the entry in a new tab. + NEW_TAB = 0, + // The user opened the entry in a new incognito tab. + NEW_INCOGNITO_TAB = 1, + // The user copied the url of the entry. + COPY_LINK = 2, + // The user chose to view the offline version of the entry. + VIEW_OFFLINE = 3, + // The user cancelled the context menu. + CANCEL = 4, + // Add new enum above ENUM_MAX. + ENUM_MAX +}; +} + +@interface ReadingListCoordinator () + +@property(nonatomic, assign) ios::ChromeBrowserState* browserState; +// Used to load the Reading List pages. +@property(nonatomic, weak) id<UrlLoader> URLLoader; +@property(nonatomic, strong) ReadingListViewController* containerViewController; +@property(nonatomic, strong) AlertCoordinator* alertCoordinator; + +// Opens |URL| in a new tab |incognito| or not. +- (void)openNewTabWithURL:(const GURL&)URL incognito:(BOOL)incognito; + +// Opens the offline url |offlineURL| of the entry saved in the reading list +// model with the |entryURL| url. +- (void)openOfflineURL:(const GURL&)offlineURL + correspondingEntryURL:(const GURL&)entryURL + fromReadingListCollectionViewController: + (ReadingListCollectionViewController*) + readingListCollectionViewController; + +@end + +@implementation ReadingListCoordinator + +@synthesize alertCoordinator = _alertCoordinator; +@synthesize containerViewController = _containerViewController; +@synthesize URLLoader = _URLLoader; +@synthesize browserState = _browserState; + +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browserState: + (ios::ChromeBrowserState*)browserState + loader:(id<UrlLoader>)loader { + self = [super initWithBaseViewController:viewController]; + if (self) { + _browserState = browserState; + _URLLoader = loader; + } + return self; +} + +#pragma mark - ChromeCoordinator + +- (void)start { + if (!self.containerViewController) { + ReadingListModel* model = + ReadingListModelFactory::GetInstance()->GetForBrowserState( + self.browserState); + favicon::LargeIconService* largeIconService = + IOSChromeLargeIconServiceFactory::GetForBrowserState(self.browserState); + ReadingListDownloadService* readingListDownloadService = + ReadingListDownloadServiceFactory::GetInstance()->GetForBrowserState( + self.browserState); + + ReadingListToolbar* toolbar = [[ReadingListToolbar alloc] init]; + ReadingListCollectionViewController* collectionViewController = + [[ReadingListCollectionViewController alloc] + initWithModel:model + largeIconService:largeIconService + readingListDownloadService:readingListDownloadService + toolbar:toolbar]; + collectionViewController.delegate = self; + + self.containerViewController = [[ReadingListViewController alloc] + initWithCollectionViewController:collectionViewController + toolbar:toolbar]; + self.containerViewController.delegate = self; + } + + [self.baseViewController presentViewController:self.containerViewController + animated:YES + completion:nil]; +} + +- (void)stop { + [self.containerViewController.presentingViewController + dismissViewControllerAnimated:YES + completion:nil]; + + self.containerViewController = nil; +} + +#pragma mark - ReadingListCollectionViewControllerDelegate + +- (void)dismissReadingListCollectionViewController: + (ReadingListCollectionViewController*)readingListCollectionViewController { + [readingListCollectionViewController willBeDismissed]; + [self stop]; +} + +- (void)readingListCollectionViewController: + (ReadingListCollectionViewController*) + readingListCollectionViewController + displayContextMenuForItem: + (ReadingListCollectionViewItem*)readingListItem + atPoint:(CGPoint)menuLocation { + if (!self.containerViewController) { + return; + } + + const ReadingListEntry* entry = + readingListCollectionViewController.readingListModel->GetEntryByURL( + readingListItem.url); + + if (!entry) { + [readingListCollectionViewController reloadData]; + return; + } + const GURL entryURL = entry->URL(); + + __weak ReadingListCoordinator* weakSelf = self; + + _alertCoordinator = [[ActionSheetCoordinator alloc] + initWithBaseViewController:self.containerViewController + title:readingListItem.text + message:readingListItem.detailText + rect:CGRectMake(menuLocation.x, menuLocation.y, 0, + 0) + view:readingListCollectionViewController + .collectionView]; + + NSString* openInNewTabTitle = + l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB); + [_alertCoordinator + addItemWithTitle:openInNewTabTitle + action:^{ + [weakSelf openNewTabWithURL:entryURL incognito:NO]; + UMA_HISTOGRAM_ENUMERATION("ReadingList.ContextMenu", NEW_TAB, + ENUM_MAX); + + } + style:UIAlertActionStyleDefault]; + + NSString* openInNewTabIncognitoTitle = + l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWINCOGNITOTAB); + [_alertCoordinator + addItemWithTitle:openInNewTabIncognitoTitle + action:^{ + UMA_HISTOGRAM_ENUMERATION("ReadingList.ContextMenu", + NEW_INCOGNITO_TAB, ENUM_MAX); + [weakSelf openNewTabWithURL:entryURL incognito:YES]; + } + style:UIAlertActionStyleDefault]; + + NSString* copyLinkTitle = + l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_COPY); + [_alertCoordinator + addItemWithTitle:copyLinkTitle + action:^{ + UMA_HISTOGRAM_ENUMERATION("ReadingList.ContextMenu", + COPY_LINK, ENUM_MAX); + StoreURLInPasteboard(entryURL); + } + style:UIAlertActionStyleDefault]; + + if (entry->DistilledState() == ReadingListEntry::PROCESSED) { + GURL offlineURL = reading_list::OfflineURLForPath( + entry->DistilledPath(), entryURL, entry->DistilledURL()); + NSString* viewOfflineVersionTitle = + l10n_util::GetNSString(IDS_IOS_READING_LIST_CONTENT_CONTEXT_OFFLINE); + [_alertCoordinator + addItemWithTitle:viewOfflineVersionTitle + action:^{ + UMA_HISTOGRAM_ENUMERATION("ReadingList.ContextMenu", + VIEW_OFFLINE, ENUM_MAX); + [weakSelf openOfflineURL:offlineURL + correspondingEntryURL:entryURL + fromReadingListCollectionViewController: + readingListCollectionViewController]; + } + style:UIAlertActionStyleDefault]; + } + + [_alertCoordinator + addItemWithTitle:l10n_util::GetNSString(IDS_APP_CANCEL) + action:^{ + UMA_HISTOGRAM_ENUMERATION("ReadingList.ContextMenu", CANCEL, + ENUM_MAX); + } + style:UIAlertActionStyleCancel]; + + [_alertCoordinator start]; +} + +- (void) +readingListCollectionViewController: + (ReadingListCollectionViewController*)readingListCollectionViewController + openItem: + (ReadingListCollectionViewItem*)readingListItem { + const ReadingListEntry* entry = + readingListCollectionViewController.readingListModel->GetEntryByURL( + readingListItem.url); + + if (!entry) { + [readingListCollectionViewController reloadData]; + return; + } + + base::RecordAction(base::UserMetricsAction("MobileReadingListOpen")); + + [self.URLLoader loadURL:entry->URL() + referrer:web::Referrer() + transition:ui::PAGE_TRANSITION_AUTO_BOOKMARK + rendererInitiated:NO]; + + [self stop]; +} + +#pragma mark - Private + +- (void)openOfflineURL:(const GURL&)offlineURL + correspondingEntryURL:(const GURL&)entryURL + fromReadingListCollectionViewController: + (ReadingListCollectionViewController*) + readingListCollectionViewController { + [readingListCollectionViewController willBeDismissed]; + + [self openNewTabWithURL:offlineURL incognito:NO]; + + UMA_HISTOGRAM_BOOLEAN("ReadingList.OfflineVersionDisplayed", true); + const GURL updateURL = entryURL; + readingListCollectionViewController.readingListModel->SetReadStatus(updateURL, + true); +} + +- (void)openNewTabWithURL:(const GURL&)URL incognito:(BOOL)incognito { + base::RecordAction(base::UserMetricsAction("MobileReadingListOpen")); + + [self.URLLoader webPageOrderedOpen:URL + referrer:web::Referrer() + windowName:nil + inIncognito:incognito + inBackground:NO + appendTo:kLastTab]; + + [self stop]; +} + +@end
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_view_controller_unittest.mm b/ios/chrome/browser/ui/reading_list/reading_list_coordinator_unittest.mm similarity index 82% rename from ios/chrome/browser/ui/reading_list/reading_list_view_controller_unittest.mm rename to ios/chrome/browser/ui/reading_list/reading_list_coordinator_unittest.mm index d41a48d7..c0aec66 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_coordinator_unittest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/reading_list/reading_list_view_controller.h" +#import "ios/chrome/browser/ui/reading_list/reading_list_coordinator.h" #include "base/mac/scoped_nsobject.h" #include "base/memory/ptr_util.h" @@ -12,6 +12,7 @@ #include "components/favicon/core/large_icon_service.h" #include "components/reading_list/ios/reading_list_entry.h" #include "components/reading_list/ios/reading_list_model_impl.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h" #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h" @@ -110,29 +111,32 @@ @end -#pragma mark - ReadingListViewControllerTest +#pragma mark - ReadingListCoordinatorTest -class ReadingListViewControllerTest : public web::WebTestWithWebState { +class ReadingListCoordinatorTest : public web::WebTestWithWebState { public: - ReadingListViewControllerTest() { + ReadingListCoordinatorTest() { loader_mock_.reset([[UrlLoaderStub alloc] init]); mock_favicon_service_.reset(new MockFaviconService()); + TestChromeBrowserState::Builder builder; + browser_state_ = builder.Build(); + reading_list_model_.reset(new ReadingListModelImpl(nullptr, nullptr)); large_icon_service_.reset(new favicon::LargeIconService( mock_favicon_service_.get(), base::ThreadTaskRunnerHandle::Get())); - container_.reset([[ReadingListViewController alloc] - initWithModel:reading_list_model_.get() - loader:loader_mock_ - largeIconService:large_icon_service_.get() - readingListDownloadService:nil]); + coordinator_.reset([[ReadingListCoordinator alloc] + initWithBaseViewController:nil + browserState:browser_state_.get() + loader:loader_mock_]); } - ~ReadingListViewControllerTest() override {} + ~ReadingListCoordinatorTest() override {} - ReadingListViewController* GetContainer() { return container_; } + ReadingListCoordinator* GetCoordinator() { return coordinator_; } ReadingListModel* GetReadingListModel() { return reading_list_model_.get(); } UrlLoaderStub* GetLoaderStub() { return loader_mock_; } + ReadingListCollectionViewController* GetAReadingListCollectionViewController() { return [[[ReadingListCollectionViewController alloc] @@ -143,16 +147,17 @@ } private: - base::scoped_nsobject<ReadingListViewController> container_; + base::scoped_nsobject<ReadingListCoordinator> coordinator_; std::unique_ptr<ReadingListModelImpl> reading_list_model_; base::scoped_nsobject<UrlLoaderStub> loader_mock_; std::unique_ptr<favicon::LargeIconService> large_icon_service_; std::unique_ptr<MockFaviconService> mock_favicon_service_; + std::unique_ptr<TestChromeBrowserState> browser_state_; }; -// Tests that the implementation of ReadingListCollectionViewController -// openItemAtIndexPath opens the entry. -TEST_F(ReadingListViewControllerTest, OpenItem) { +// Tests that the implementation of ReadingListCoordinator openItemAtIndexPath +// opens the entry. +TEST_F(ReadingListCoordinatorTest, OpenItem) { // Setup. GURL url("https://chromium.org"); std::string title("Chromium"); @@ -169,9 +174,9 @@ distillationState:ReadingListEntry::PROCESSED]); // Action. - [GetContainer() readingListCollectionViewController: - GetAReadingListCollectionViewController() - openItem:item]; + [GetCoordinator() readingListCollectionViewController: + GetAReadingListCollectionViewController() + openItem:item]; // Tests. UrlLoaderStub* loader = GetLoaderStub();
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_view_controller.h b/ios/chrome/browser/ui/reading_list/reading_list_view_controller.h index 1904d97..7584304 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_view_controller.h +++ b/ios/chrome/browser/ui/reading_list/reading_list_view_controller.h
@@ -5,34 +5,28 @@ #ifndef IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_VIEW_CONTROLLER_H_ #define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_VIEW_CONTROLLER_H_ -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h" #import "ios/chrome/browser/ui/reading_list/reading_list_toolbar.h" -namespace favicon { -class LargeIconService; -} - @class ReadingListCollectionViewController; -class ReadingListDownloadService; -class ReadingListModel; -@protocol UrlLoader; +@protocol ReadingListCollectionViewControllerDelegate; // Container for the ReadingList Collection View Controller and the toolbar. It -// handles the interactions between the two. It also acts as a ReadingList -// delegate, opening entries and displaying context menu. -@interface ReadingListViewController - : UIViewController<ReadingListCollectionViewControllerDelegate> +// handles the interactions between the two. +@interface ReadingListViewController : UIViewController -- (instancetype)initWithModel:(ReadingListModel*)model - loader:(id<UrlLoader>)loader - largeIconService:(favicon::LargeIconService*)largeIconService - readingListDownloadService: - (ReadingListDownloadService*)readingListDownloadService +- (instancetype)initWithCollectionViewController: + (ReadingListCollectionViewController*) + collectionViewController + toolbar:(ReadingListToolbar*)toolbar NS_DESIGNATED_INITIALIZER; - (instancetype)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil NS_UNAVAILABLE; - (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +@property(nonatomic, weak) id<ReadingListCollectionViewControllerDelegate> + delegate; @end
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm index 253ce847..6e0eb577 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm
@@ -6,47 +6,16 @@ #import <MobileCoreServices/MobileCoreServices.h> -#include "base/metrics/histogram_macros.h" -#include "base/metrics/user_metrics.h" -#include "base/metrics/user_metrics_action.h" -#include "components/reading_list/ios/reading_list_model.h" -#include "ios/chrome/browser/reading_list/offline_url_utils.h" -#import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h" -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" #import "ios/chrome/browser/ui/keyboard/UIKeyCommand+Chrome.h" #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h" #import "ios/chrome/browser/ui/reading_list/reading_list_toolbar.h" #import "ios/chrome/browser/ui/uikit_ui_util.h" -#import "ios/chrome/browser/ui/url_loader.h" -#import "ios/chrome/browser/ui/util/pasteboard_util.h" -#include "ios/chrome/grit/ios_strings.h" -#include "ios/web/public/navigation_manager.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/strings/grit/ui_strings.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif namespace { -// Action chosen by the user in the context menu, for UMA report. -// These match tools/metrics/histograms/histograms.xml. -enum UMAContextMenuAction { - // The user opened the entry in a new tab. - NEW_TAB = 0, - // The user opened the entry in a new incognito tab. - NEW_INCOGNITO_TAB = 1, - // The user copied the url of the entry. - COPY_LINK = 2, - // The user chose to view the offline version of the entry. - VIEW_OFFLINE = 3, - // The user cancelled the context menu. - CANCEL = 4, - // Add new enum above ENUM_MAX. - ENUM_MAX -}; - // Height of the toolbar in normal state. const int kToolbarNormalHeight = 48; // Height of the expanded toolbar (buttons on multiple lines). @@ -58,58 +27,37 @@ }; } -@interface ReadingListViewController ()<ReadingListToolbarActions, - ReadingListToolbarHeightDelegate> { - // Toolbar with the actions. - ReadingListToolbar* _toolbar; +@interface ReadingListViewController ()< + ReadingListToolbarActions, + ReadingListToolbarHeightDelegate, + ReadingListCollectionViewControllerAudience> { // This constraint control the expanded mode of the toolbar. NSLayoutConstraint* _expandedToolbarConstraint; - // Coordinator for the alert displayed when the user long presses an entry. - AlertCoordinator* _alertCoordinator; } -// UrlLoader for navigating to entries. -@property(nonatomic, weak, readonly) id<UrlLoader> URLLoader; @property(nonatomic, strong, readonly) ReadingListCollectionViewController* readingListCollectionViewController; - -// Closes the ReadingList view. -- (void)dismiss; -// Opens |URL| in a new tab |incognito| or not. -- (void)openNewTabWithURL:(const GURL&)URL incognito:(BOOL)incognito; -// Opens the offline url |offlineURL| of the entry saved in the reading list -// model with the |entryURL| url. -- (void)openOfflineURL:(const GURL&)offlineURL - correspondingEntryURL:(const GURL&)entryURL - fromReadingListCollectionViewController: - (ReadingListCollectionViewController*) - readingListCollectionViewController; +@property(nonatomic, strong, readonly) ReadingListToolbar* toolbar; @end @implementation ReadingListViewController +@synthesize delegate = _delegate; @synthesize readingListCollectionViewController = _readingListCollectionViewController; -@synthesize URLLoader = _URLLoader; +@synthesize toolbar = _toolbar; -- (instancetype)initWithModel:(ReadingListModel*)model - loader:(id<UrlLoader>)loader - largeIconService:(favicon::LargeIconService*)largeIconService - readingListDownloadService: - (ReadingListDownloadService*)readingListDownloadService { +- (instancetype)initWithCollectionViewController: + (ReadingListCollectionViewController*) + collectionViewController + toolbar:(ReadingListToolbar*)toolbar { self = [super initWithNibName:nil bundle:nil]; if (self) { - _URLLoader = loader; - _toolbar = [[ReadingListToolbar alloc] initWithFrame:CGRectZero]; - _toolbar.heightDelegate = self; - _readingListCollectionViewController = - [[ReadingListCollectionViewController alloc] - initWithModel:model - largeIconService:largeIconService - readingListDownloadService:readingListDownloadService - toolbar:_toolbar]; - _readingListCollectionViewController.delegate = self; + _toolbar = toolbar; + toolbar.heightDelegate = self; + _readingListCollectionViewController = collectionViewController; + collectionViewController.audience = self; // Configure modal presentation. [self setModalPresentationStyle:UIModalPresentationFormSheet]; @@ -148,160 +96,11 @@ #pragma mark UIAccessibilityAction - (BOOL)accessibilityPerformEscape { - [self dismiss]; + [self.delegate dismissReadingListCollectionViewController: + self.readingListCollectionViewController]; return YES; } -#pragma mark - ReadingListCollectionViewControllerDelegate - -- (void)readingListCollectionViewController: - (ReadingListCollectionViewController*) - readingListCollectionViewController - hasItems:(BOOL)hasItems { - if (hasItems) { - // If there are items, add the toolbar. - [self.view addSubview:_toolbar]; - NSDictionary* views = @{ - @"toolbar" : _toolbar, - @"collection" : readingListCollectionViewController.view - }; - NSArray* constraints = @[ @"V:[collection][toolbar]|", @"H:|[toolbar]|" ]; - ApplyVisualConstraints(constraints, views); - NSLayoutConstraint* height = - [_toolbar.heightAnchor constraintEqualToConstant:kToolbarNormalHeight]; - height.priority = LayoutPriorityHigh; - height.active = YES; - // When the toolbar is added, the only button is the "edit" button. No need - // to go in expanded mode. - _expandedToolbarConstraint = [_toolbar.heightAnchor - constraintEqualToConstant:kToolbarExpandedHeight]; - } else { - // If there is no item, remove the toolbar. The constraints will make sure - // the collection takes the whole view. - [_toolbar removeFromSuperview]; - } -} - -- (void)dismissReadingListCollectionViewController: - (ReadingListCollectionViewController*)readingListCollectionViewController { - [readingListCollectionViewController willBeDismissed]; - [self dismiss]; -} - -- (void)readingListCollectionViewController: - (ReadingListCollectionViewController*) - readingListCollectionViewController - displayContextMenuForItem: - (ReadingListCollectionViewItem*)readingListItem - atPoint:(CGPoint)menuLocation { - const ReadingListEntry* entry = - readingListCollectionViewController.readingListModel->GetEntryByURL( - readingListItem.url); - - if (!entry) { - [readingListCollectionViewController reloadData]; - return; - } - const GURL entryURL = entry->URL(); - - __weak ReadingListViewController* weakSelf = self; - - _alertCoordinator = [[ActionSheetCoordinator alloc] - initWithBaseViewController:self - title:readingListItem.text - message:readingListItem.detailText - rect:CGRectMake(menuLocation.x, menuLocation.y, 0, - 0) - view:readingListCollectionViewController - .collectionView]; - - NSString* openInNewTabTitle = - l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB); - [_alertCoordinator - addItemWithTitle:openInNewTabTitle - action:^{ - [weakSelf openNewTabWithURL:entryURL incognito:NO]; - UMA_HISTOGRAM_ENUMERATION("ReadingList.ContextMenu", NEW_TAB, - ENUM_MAX); - - } - style:UIAlertActionStyleDefault]; - - NSString* openInNewTabIncognitoTitle = - l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWINCOGNITOTAB); - [_alertCoordinator - addItemWithTitle:openInNewTabIncognitoTitle - action:^{ - UMA_HISTOGRAM_ENUMERATION("ReadingList.ContextMenu", - NEW_INCOGNITO_TAB, ENUM_MAX); - [weakSelf openNewTabWithURL:entryURL incognito:YES]; - } - style:UIAlertActionStyleDefault]; - - NSString* copyLinkTitle = - l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_COPY); - [_alertCoordinator - addItemWithTitle:copyLinkTitle - action:^{ - UMA_HISTOGRAM_ENUMERATION("ReadingList.ContextMenu", - COPY_LINK, ENUM_MAX); - StoreURLInPasteboard(entryURL); - } - style:UIAlertActionStyleDefault]; - - if (entry->DistilledState() == ReadingListEntry::PROCESSED) { - GURL offlineURL = reading_list::OfflineURLForPath( - entry->DistilledPath(), entryURL, entry->DistilledURL()); - NSString* viewOfflineVersionTitle = - l10n_util::GetNSString(IDS_IOS_READING_LIST_CONTENT_CONTEXT_OFFLINE); - [_alertCoordinator - addItemWithTitle:viewOfflineVersionTitle - action:^{ - UMA_HISTOGRAM_ENUMERATION("ReadingList.ContextMenu", - VIEW_OFFLINE, ENUM_MAX); - [weakSelf openOfflineURL:offlineURL - correspondingEntryURL:entryURL - fromReadingListCollectionViewController: - readingListCollectionViewController]; - } - style:UIAlertActionStyleDefault]; - } - - [_alertCoordinator - addItemWithTitle:l10n_util::GetNSString(IDS_APP_CANCEL) - action:^{ - UMA_HISTOGRAM_ENUMERATION("ReadingList.ContextMenu", CANCEL, - ENUM_MAX); - } - style:UIAlertActionStyleCancel]; - - [_alertCoordinator start]; -} - -- (void) -readingListCollectionViewController: - (ReadingListCollectionViewController*)readingListCollectionViewController - openItem: - (ReadingListCollectionViewItem*)readingListItem { - const ReadingListEntry* entry = - readingListCollectionViewController.readingListModel->GetEntryByURL( - readingListItem.url); - - if (!entry) { - [readingListCollectionViewController reloadData]; - return; - } - - base::RecordAction(base::UserMetricsAction("MobileReadingListOpen")); - - [self.URLLoader loadURL:entry->URL() - referrer:web::Referrer() - transition:ui::PAGE_TRANSITION_AUTO_BOOKMARK - rendererInitiated:NO]; - - [self dismiss]; -} - #pragma mark - ReadingListToolbarActionTarget - (void)markPressed { @@ -320,6 +119,33 @@ [self.readingListCollectionViewController exitEditingModePressed]; } +#pragma mark - ReadingListCollectionViewControllerAudience + +- (void)readingListHasItems:(BOOL)hasItems { + if (hasItems) { + // If there are items, add the toolbar. + [self.view addSubview:_toolbar]; + NSDictionary* views = @{ + @"toolbar" : _toolbar, + @"collection" : self.readingListCollectionViewController.view + }; + NSArray* constraints = @[ @"V:[collection][toolbar]|", @"H:|[toolbar]|" ]; + ApplyVisualConstraints(constraints, views); + NSLayoutConstraint* height = + [_toolbar.heightAnchor constraintEqualToConstant:kToolbarNormalHeight]; + height.priority = LayoutPriorityHigh; + height.active = YES; + // When the toolbar is added, the only button is the "edit" button. No need + // to go in expanded mode. + _expandedToolbarConstraint = [_toolbar.heightAnchor + constraintEqualToConstant:kToolbarExpandedHeight]; + } else { + // If there is no item, remove the toolbar. The constraints will make sure + // the collection takes the whole view. + [_toolbar removeFromSuperview]; + } +} + #pragma mark - ReadingListToolbarHeightDelegate - (void)toolbar:(id)toolbar onHeightChanged:(ReadingListToolbarHeight)height { @@ -336,51 +162,19 @@ }); } -#pragma mark - Private - -- (void)dismiss { - [self.presentingViewController dismissViewControllerAnimated:YES - completion:nil]; -} - -- (void)openNewTabWithURL:(const GURL&)URL incognito:(BOOL)incognito { - base::RecordAction(base::UserMetricsAction("MobileReadingListOpen")); - - [self.URLLoader webPageOrderedOpen:URL - referrer:web::Referrer() - windowName:nil - inIncognito:incognito - inBackground:NO - appendTo:kLastTab]; - - [self dismiss]; -} - -- (void)openOfflineURL:(const GURL&)offlineURL - correspondingEntryURL:(const GURL&)entryURL - fromReadingListCollectionViewController: - (ReadingListCollectionViewController*) - readingListCollectionViewController { - [readingListCollectionViewController willBeDismissed]; - - [self openNewTabWithURL:offlineURL incognito:NO]; - - UMA_HISTOGRAM_BOOLEAN("ReadingList.OfflineVersionDisplayed", true); - const GURL updateURL = entryURL; - readingListCollectionViewController.readingListModel->SetReadStatus(updateURL, - true); -} - #pragma mark - UIResponder - (NSArray*)keyCommands { __weak ReadingListViewController* weakSelf = self; - return @[ [UIKeyCommand cr_keyCommandWithInput:UIKeyInputEscape - modifierFlags:Cr_UIKeyModifierNone - title:nil - action:^{ - [weakSelf dismiss]; - }] ]; + return @[ [UIKeyCommand + cr_keyCommandWithInput:UIKeyInputEscape + modifierFlags:Cr_UIKeyModifierNone + title:nil + action:^{ + [weakSelf.delegate + dismissReadingListCollectionViewController: + weakSelf.readingListCollectionViewController]; + }] ]; } @end
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_view_controller_builder.h b/ios/chrome/browser/ui/reading_list/reading_list_view_controller_builder.h deleted file mode 100644 index bc33b6a..0000000 --- a/ios/chrome/browser/ui/reading_list/reading_list_view_controller_builder.h +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_VIEW_CONTROLLER_BUILDER_H_ -#define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_VIEW_CONTROLLER_BUILDER_H_ - -#import <UIKit/UIKit.h> - -#import "ios/chrome/browser/ui/reading_list/reading_list_view_controller.h" - -namespace ios { -class ChromeBrowserState; -} - -@class TabModel; -@protocol UrlLoader; - -@protocol ReadingListViewControllerDelegate; - -// A builder class that constructs ReadingListViewControllers. -@interface ReadingListViewControllerBuilder : NSObject - -+ (ReadingListViewController*) -readingListViewControllerInBrowserState:(ios::ChromeBrowserState*)browserState - loader:(id<UrlLoader>)loader; - -@end - -#endif // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_VIEW_CONTROLLER_BUILDER_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_view_controller_builder.mm b/ios/chrome/browser/ui/reading_list/reading_list_view_controller_builder.mm deleted file mode 100644 index 1c0df38..0000000 --- a/ios/chrome/browser/ui/reading_list/reading_list_view_controller_builder.mm +++ /dev/null
@@ -1,39 +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 "ios/chrome/browser/ui/reading_list/reading_list_view_controller_builder.h" - -#include "components/prefs/pref_service.h" -#include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" -#include "ios/chrome/browser/pref_names.h" -#include "ios/chrome/browser/reading_list/reading_list_download_service.h" -#include "ios/chrome/browser/reading_list/reading_list_download_service_factory.h" -#include "ios/chrome/browser/reading_list/reading_list_model_factory.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@implementation ReadingListViewControllerBuilder - -+ (ReadingListViewController*) -readingListViewControllerInBrowserState:(ios::ChromeBrowserState*)browserState - loader:(id<UrlLoader>)loader { - ReadingListModel* model = - ReadingListModelFactory::GetInstance()->GetForBrowserState(browserState); - favicon::LargeIconService* service = - IOSChromeLargeIconServiceFactory::GetForBrowserState(browserState); - ReadingListDownloadService* rlservice = - ReadingListDownloadServiceFactory::GetInstance()->GetForBrowserState( - browserState); - ReadingListViewController* vc = - [[ReadingListViewController alloc] initWithModel:model - loader:loader - largeIconService:service - readingListDownloadService:rlservice]; - return vc; -} - -@end
diff --git a/ios/chrome/browser/ui/util/BUILD.gn b/ios/chrome/browser/ui/util/BUILD.gn index 6c810dc..09d47cbb 100644 --- a/ios/chrome/browser/ui/util/BUILD.gn +++ b/ios/chrome/browser/ui/util/BUILD.gn
@@ -8,6 +8,8 @@ "CRUILabel+AttributeUtils.mm", "core_text_util.h", "core_text_util.mm", + "i18n_string.h", + "i18n_string.mm", "label_link_controller.h", "label_link_controller.mm", "label_observer.h",
diff --git a/ios/chrome/browser/ui/util/i18n_string.h b/ios/chrome/browser/ui/util/i18n_string.h new file mode 100644 index 0000000..6cd734a --- /dev/null +++ b/ios/chrome/browser/ui/util/i18n_string.h
@@ -0,0 +1,16 @@ +// 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_BROWSER_UI_UTIL_I18N_STRING_H_ +#define IOS_CHROME_BROWSER_UI_UTIL_I18N_STRING_H_ + +#import <Foundation/Foundation.h> + +// Wrapper for base::i18n::AdjustStringForLocaleDirection. +// Given the string in |text|, this function returns a new string with +// the appropriate Unicode formatting marks that mark the string direction +// (either left-to-right or right-to-left). +NSString* AdjustStringForLocaleDirection(NSString* text); + +#endif // IOS_CHROME_BROWSER_UI_UTIL_I18N_STRING_H_
diff --git a/ios/chrome/browser/ui/util/i18n_string.mm b/ios/chrome/browser/ui/util/i18n_string.mm new file mode 100644 index 0000000..5242053c0 --- /dev/null +++ b/ios/chrome/browser/ui/util/i18n_string.mm
@@ -0,0 +1,19 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/util/i18n_string.h" + +#include "base/i18n/rtl.h" +#include "base/strings/string16.h" +#include "base/strings/sys_string_conversions.h" + +NSString* AdjustStringForLocaleDirection(NSString* text) { + base::string16 converted_text = base::SysNSStringToUTF16(text); + bool has_changed = + base::i18n::AdjustStringForLocaleDirection(&converted_text); + if (has_changed) { + return base::SysUTF16ToNSString(converted_text); + } + return text; +}
diff --git a/ios/chrome/common/app_group/app_group_constants.h b/ios/chrome/common/app_group/app_group_constants.h index 483b66bb..445e86d 100644 --- a/ios/chrome/common/app_group/app_group_constants.h +++ b/ios/chrome/common/app_group/app_group_constants.h
@@ -52,6 +52,9 @@ // The command to open a new tab. extern const char kChromeAppGroupNewTabCommand[]; +// The command to focus the omnibox. +extern const char kChromeAppGroupFocusOmniboxCommand[]; + // The key in kChromeAppGroupCommandPreference containing a NSDate at which // |kChromeAppGroupCommandAppPreference| issued the command. extern const char kChromeAppGroupCommandTimePreference[];
diff --git a/ios/chrome/common/app_group/app_group_constants.mm b/ios/chrome/common/app_group/app_group_constants.mm index f080bb9f..926db07 100644 --- a/ios/chrome/common/app_group/app_group_constants.mm +++ b/ios/chrome/common/app_group/app_group_constants.mm
@@ -31,6 +31,7 @@ const char kChromeAppGroupOpenURLCommand[] = "openurl"; const char kChromeAppGroupVoiceSearchCommand[] = "voicesearch"; const char kChromeAppGroupNewTabCommand[] = "newtab"; +const char kChromeAppGroupFocusOmniboxCommand[] = "focusomnibox"; const char kChromeAppClientID[] = "ClientID"; const char kUserMetricsEnabledDate[] = "UserMetricsEnabledDate";
diff --git a/ios/chrome/widget_extension/BUILD.gn b/ios/chrome/widget_extension/BUILD.gn index 1316fa9..6b020507 100644 --- a/ios/chrome/widget_extension/BUILD.gn +++ b/ios/chrome/widget_extension/BUILD.gn
@@ -3,6 +3,7 @@ # found in the LICENSE file. import("//build/config/ios/rules.gni") +import("//build/config/mac/base_rules.gni") import("//build/mac/tweak_info_plist.gni") import("//ios/build/chrome_build.gni") @@ -27,6 +28,23 @@ "widget_view_controller.mm", ] + deps = [ + "//base", + "//base:i18n", + "//components/prefs", + "//components/variations", + "//components/version_info", + "//ios/chrome/common", + "//ios/chrome/common/app_group", + "//ios/chrome/common/app_group:client", + "//ios/chrome/common/physical_web", + "//ios/chrome/today_extension/strings", + "//ios/third_party/material_components_ios", + "//net", + "//ui/base", + "//url", + ] + libs = [ "Foundation.framework", "NotificationCenter.framework",
diff --git a/ios/chrome/widget_extension/widget_view.h b/ios/chrome/widget_extension/widget_view.h index a13f35ee..9e2ff38 100644 --- a/ios/chrome/widget_extension/widget_view.h +++ b/ios/chrome/widget_extension/widget_view.h
@@ -7,9 +7,23 @@ #import <UIKit/UIKit.h> +// Protocol to be implemented by targets for user actions coming from the widget +// view. +@protocol WidgetViewActionTarget + +// Called when the user taps the fake omnibox. +- (void)openApp:(id)sender; + +@end + +// View for the widget. Shows a blinking cursor for a fake omnibox and calls the +// target when tapped. @interface WidgetView : UIView -- (instancetype)init NS_DESIGNATED_INITIALIZER; +// Designated initializer, creates the widget view with a |target| for user +// actions. +- (instancetype)initWithActionTarget:(id<WidgetViewActionTarget>)target + NS_DESIGNATED_INITIALIZER; - (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; - (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
diff --git a/ios/chrome/widget_extension/widget_view.mm b/ios/chrome/widget_extension/widget_view.mm index d2c5a77e..d746fd0 100644 --- a/ios/chrome/widget_extension/widget_view.mm +++ b/ios/chrome/widget_extension/widget_view.mm
@@ -4,6 +4,8 @@ #import "ios/chrome/widget_extension/widget_view.h" +#include "base/logging.h" + #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif @@ -12,16 +14,22 @@ const CGFloat kCursorHeight = 40; const CGFloat kCursorWidth = 2; -const CGFloat kCursorHorizontalPadding = 40; +const CGFloat kCursorHorizontalPadding = 10; +const CGFloat kCursorVerticalPadding = 10; +const CGFloat kFakeboxHorizontalPadding = 40; +const CGFloat kFakeboxVerticalPadding = 40; } // namespace -@interface WidgetView () +@interface WidgetView () { + __weak id<WidgetViewActionTarget> _target; +} @property(nonatomic, weak) UIView* cursor; -// Creates a cursor, adds it to the view and sets the class cursor property. -- (void)addCursor; +// Creates and adds a fake omnibox with blinking cursor to the view and sets the +// class cursor property. +- (void)addFakebox; @end @@ -29,28 +37,50 @@ @synthesize cursor = _cursor; -- (instancetype)init { +- (instancetype)initWithActionTarget:(id<WidgetViewActionTarget>)target { self = [super initWithFrame:CGRectZero]; if (self) { - [self addCursor]; + DCHECK(target); + _target = target; + [self addFakebox]; } return self; } -- (void)addCursor { +- (void)addFakebox { + UIView* fakebox = [[UIView alloc] initWithFrame:CGRectZero]; + + UIGestureRecognizer* tapRecognizer = + [[UITapGestureRecognizer alloc] initWithTarget:_target + action:@selector(openApp:)]; + + [fakebox addGestureRecognizer:tapRecognizer]; + [self addSubview:fakebox]; + UIView* cursor = [[UIView alloc] initWithFrame:CGRectZero]; self.cursor = cursor; self.cursor.backgroundColor = [UIColor blueColor]; - [self addSubview:self.cursor]; + [fakebox addSubview:self.cursor]; + [fakebox setTranslatesAutoresizingMaskIntoConstraints:NO]; [self.cursor setTranslatesAutoresizingMaskIntoConstraints:NO]; [NSLayoutConstraint activateConstraints:@[ + [[fakebox leadingAnchor] constraintEqualToAnchor:self.leadingAnchor + constant:kFakeboxHorizontalPadding], + [[fakebox trailingAnchor] + constraintEqualToAnchor:self.trailingAnchor + constant:-kFakeboxHorizontalPadding], + [[fakebox topAnchor] constraintEqualToAnchor:self.topAnchor + constant:kFakeboxVerticalPadding], + [[fakebox heightAnchor] + constraintEqualToConstant:kCursorHeight + 2 * kCursorVerticalPadding], + [[self.cursor widthAnchor] constraintEqualToConstant:kCursorWidth], [[self.cursor leadingAnchor] - constraintEqualToAnchor:self.leadingAnchor + constraintEqualToAnchor:fakebox.leadingAnchor constant:kCursorHorizontalPadding], [[self.cursor heightAnchor] constraintEqualToConstant:kCursorHeight], - [[self.cursor centerYAnchor] constraintEqualToAnchor:self.centerYAnchor] + [[self.cursor centerYAnchor] constraintEqualToAnchor:fakebox.centerYAnchor] ]]; [UIView animateWithDuration:0.3
diff --git a/ios/chrome/widget_extension/widget_view_controller.mm b/ios/chrome/widget_extension/widget_view_controller.mm index 735d49e..aa93999c 100644 --- a/ios/chrome/widget_extension/widget_view_controller.mm +++ b/ios/chrome/widget_extension/widget_view_controller.mm
@@ -6,13 +6,19 @@ #import <NotificationCenter/NotificationCenter.h> +#include "base/mac/foundation_util.h" +#include "base/strings/sys_string_conversions.h" +#include "ios/chrome/common/app_group/app_group_constants.h" +#include "ios/chrome/common/x_callback_url.h" #import "ios/chrome/widget_extension/widget_view.h" +#import "net/base/mac/url_conversions.h" +#include "url/gurl.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif -@interface WidgetViewController () +@interface WidgetViewController ()<WidgetViewActionTarget> @property(nonatomic, weak) WidgetView* widgetView; @end @@ -27,7 +33,7 @@ // A local variable is necessary here as the property is declared weak and the // object would be deallocated before being retained by the addSubview call. - WidgetView* widgetView = [[WidgetView alloc] init]; + WidgetView* widgetView = [[WidgetView alloc] initWithActionTarget:self]; self.widgetView = widgetView; [self.view addSubview:self.widgetView]; @@ -44,4 +50,40 @@ ]]; } +- (void)openApp:(id)sender { + NSUserDefaults* sharedDefaults = + [[NSUserDefaults alloc] initWithSuiteName:app_group::ApplicationGroup()]; + NSString* defaultsKey = + base::SysUTF8ToNSString(app_group::kChromeAppGroupCommandPreference); + [sharedDefaults setObject:[WidgetViewController commandDict] + forKey:defaultsKey]; + [sharedDefaults synchronize]; + + NSString* scheme = base::mac::ObjCCast<NSString>([[NSBundle mainBundle] + objectForInfoDictionaryKey:@"KSChannelChromeScheme"]); + if (!scheme) + return; + const GURL openURL = + CreateXCallbackURL(base::SysNSStringToUTF8(scheme), + app_group::kChromeAppGroupXCallbackCommand); + [self.extensionContext openURL:net::NSURLWithGURL(openURL) + completionHandler:nil]; +} + ++ (NSDictionary*)commandDict { + NSString* command = + base::SysUTF8ToNSString(app_group::kChromeAppGroupFocusOmniboxCommand); + NSString* timePrefKey = + base::SysUTF8ToNSString(app_group::kChromeAppGroupCommandTimePreference); + NSString* appPrefKey = + base::SysUTF8ToNSString(app_group::kChromeAppGroupCommandAppPreference); + NSString* commandPrefKey = base::SysUTF8ToNSString( + app_group::kChromeAppGroupCommandCommandPreference); + return @{ + timePrefKey : [NSDate date], + appPrefKey : @"TodayExtension", + commandPrefKey : command, + }; +} + @end
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 31b114f..74f72b0 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1848,10 +1848,8 @@ # were matched on pass/fail but not exact error messages. crbug.com/688854 external/wpt/hr-time/window-worker-time-origin.html [ Failure ] -# 2017-02-14: These directories were just imported but expectations and baselines haven't been set yet. -crbug.com/692105 external/wpt/mixed-content [ Skip ] -crbug.com/692105 external/wpt/content-security-policy [ Skip ] # 2017-02-17: These directories were just imported but expectations and baselines haven't been set yet. +crbug.com/692105 external/wpt/content-security-policy [ Skip ] crbug.com/692105 external/wpt/domxpath/interfaces.html [ Skip ] crbug.com/692105 external/wpt/html/browsers/browsing-the-web/unloading-documents/beforeunload-canceling.html [ Skip ] crbug.com/692105 external/wpt/html/browsers/history/the-location-interface/location-valueof.html [ Skip ] @@ -1882,6 +1880,45 @@ crbug.com/627968 external/wpt/referrer-policy/strict-origin/ [ Skip ] crbug.com/627968 external/wpt/referrer-policy/strict-origin-when-cross-origin/ [ Skip ] +# These wpt/mixed-content tests have console errors that are different on different test runs. +crbug.com/679742 external/wpt/mixed-content/allowed/http-csp/same-host-wss/websocket-request/top-level/keep-scheme-redirect/websocket-allowed.https.html [ Failure ] +crbug.com/679742 external/wpt/mixed-content/allowed/meta-csp/same-host-wss/websocket-request/top-level/no-redirect/websocket-allowed.https.html [ Failure ] +crbug.com/679742 external/wpt/mixed-content/allowed/no-opt-in/same-host-wss/websocket-request/top-level/keep-scheme-redirect/websocket-allowed.https.html [ Failure ] +crbug.com/679742 external/wpt/mixed-content/allowed/no-opt-in/same-host-wss/websocket-request/top-level/no-redirect/websocket-allowed.https.html [ Failure ] +crbug.com/679742 external/wpt/mixed-content/allowed/http-csp/same-host-wss/websocket-request/top-level/no-redirect/websocket-allowed.https.html [ Failure ] +crbug.com/679742 external/wpt/mixed-content/optionally-blockable/http-csp/cross-origin-http/link-prefetch-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html [ Failure ] +crbug.com/679742 external/wpt/mixed-content/optionally-blockable/http-csp/cross-origin-http/link-prefetch-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html [ Failure ] + +# These wpt/mixed-content tests consistently time out. +crbug.com/626703 external/wpt/mixed-content/blockable/http-csp/cross-origin-http/form-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/http-csp/cross-origin-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/http-csp/cross-origin-http/form-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/http-csp/cross-origin-http/iframe-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/http-csp/cross-origin-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/http-csp/cross-origin-http/iframe-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/http-csp/same-host-http/form-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/http-csp/same-host-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/http-csp/same-host-http/form-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/http-csp/same-host-http/iframe-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/http-csp/same-host-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/http-csp/same-host-http/iframe-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/meta-csp/cross-origin-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/meta-csp/cross-origin-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/meta-csp/same-host-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/meta-csp/same-host-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/no-opt-in/cross-origin-http/form-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/no-opt-in/cross-origin-http/form-tag/top-level/no-redirect/no-opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/no-opt-in/cross-origin-http/form-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/no-opt-in/same-host-http/form-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/no-opt-in/same-host-http/form-tag/top-level/no-redirect/no-opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/no-opt-in/same-host-http/form-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html [ Timeout ] +crbug.com/626703 external/wpt/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html [ Timeout ] + # ====== New tests from w3c-test-autoroller added here ====== crbug.com/626703 external/wpt/html/webappapis/idle-callbacks/cancel-invoked.html [ Timeout ] crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/editing/selection/extend-expected.txt b/third_party/WebKit/LayoutTests/editing/selection/extend-expected.txt index 83532dc4..0aec32e 100644 --- a/third_party/WebKit/LayoutTests/editing/selection/extend-expected.txt +++ b/third_party/WebKit/LayoutTests/editing/selection/extend-expected.txt
@@ -1,7 +1,7 @@ foobarbaz Success: window.getSelection() is ar. -Success: s.extend(span2.firstChild, 4) raised IndexSizeError: Failed to execute 'extend' on 'Selection': The offset 4 is larger than or equal to the node's length (3).. -Success: s.extend(span2.firstChild, -1) raised IndexSizeError: Failed to execute 'extend' on 'Selection': The offset -1 is larger than or equal to the node's length (3).. +Success: s.extend(span2.firstChild, 4) raised IndexSizeError: Failed to execute 'extend' on 'Selection': The offset 4 is larger than the node's length (3).. +Success: s.extend(span2.firstChild, -1) raised IndexSizeError: Failed to execute 'extend' on 'Selection': The offset 4294967295 is larger than the node's length (3).. Success: window.getSelection() is b. Success: window.getSelection() is arbaz. Success: s.extend() raised TypeError: Failed to execute 'extend' on 'Selection': 1 argument required, but only 0 present..
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/http-csp/same-host-https/audio-tag/top-level/keep-scheme-redirect/allowed.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/http-csp/same-host-https/audio-tag/top-level/keep-scheme-redirect/allowed.https-expected.txt new file mode 100644 index 0000000..3f9d961 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/http-csp/same-host-https/audio-tag/top-level/keep-scheme-redirect/allowed.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: http-csp + origin: same-host-https + source_scheme: https + context_nesting: top-level + redirection: keep-scheme-redirect + subresource: audio-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/http-csp/same-host-https/audio-tag/top-level/no-redirect/allowed.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/http-csp/same-host-https/audio-tag/top-level/no-redirect/allowed.https-expected.txt new file mode 100644 index 0000000..df64316 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/http-csp/same-host-https/audio-tag/top-level/no-redirect/allowed.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: http-csp + origin: same-host-https + source_scheme: https + context_nesting: top-level + redirection: no-redirect + subresource: audio-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/http-csp/same-host-https/video-tag/top-level/keep-scheme-redirect/allowed.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/http-csp/same-host-https/video-tag/top-level/keep-scheme-redirect/allowed.https-expected.txt new file mode 100644 index 0000000..f9885bec --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/http-csp/same-host-https/video-tag/top-level/keep-scheme-redirect/allowed.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: http-csp + origin: same-host-https + source_scheme: https + context_nesting: top-level + redirection: keep-scheme-redirect + subresource: video-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/http-csp/same-host-https/video-tag/top-level/no-redirect/allowed.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/http-csp/same-host-https/video-tag/top-level/no-redirect/allowed.https-expected.txt new file mode 100644 index 0000000..914f1b5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/http-csp/same-host-https/video-tag/top-level/no-redirect/allowed.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: http-csp + origin: same-host-https + source_scheme: https + context_nesting: top-level + redirection: no-redirect + subresource: video-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/meta-csp/same-host-https/audio-tag/top-level/no-redirect/allowed.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/meta-csp/same-host-https/audio-tag/top-level/no-redirect/allowed.https-expected.txt new file mode 100644 index 0000000..5cc06fce --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/meta-csp/same-host-https/audio-tag/top-level/no-redirect/allowed.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: meta-csp + origin: same-host-https + source_scheme: https + context_nesting: top-level + redirection: no-redirect + subresource: audio-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/meta-csp/same-host-https/video-tag/top-level/no-redirect/allowed.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/meta-csp/same-host-https/video-tag/top-level/no-redirect/allowed.https-expected.txt new file mode 100644 index 0000000..dab56d99 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/meta-csp/same-host-https/video-tag/top-level/no-redirect/allowed.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: meta-csp + origin: same-host-https + source_scheme: https + context_nesting: top-level + redirection: no-redirect + subresource: video-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/keep-scheme-redirect/allowed.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/keep-scheme-redirect/allowed.https-expected.txt new file mode 100644 index 0000000..73233aebc --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/keep-scheme-redirect/allowed.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: no-opt-in + origin: same-host-https + source_scheme: https + context_nesting: top-level + redirection: keep-scheme-redirect + subresource: audio-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/no-redirect/allowed.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/no-redirect/allowed.https-expected.txt new file mode 100644 index 0000000..a1235887 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/no-redirect/allowed.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: no-opt-in + origin: same-host-https + source_scheme: https + context_nesting: top-level + redirection: no-redirect + subresource: audio-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/no-opt-in/same-host-https/video-tag/top-level/keep-scheme-redirect/allowed.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/no-opt-in/same-host-https/video-tag/top-level/keep-scheme-redirect/allowed.https-expected.txt new file mode 100644 index 0000000..8ef5634 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/no-opt-in/same-host-https/video-tag/top-level/keep-scheme-redirect/allowed.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: no-opt-in + origin: same-host-https + source_scheme: https + context_nesting: top-level + redirection: keep-scheme-redirect + subresource: video-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/no-opt-in/same-host-https/video-tag/top-level/no-redirect/allowed.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/no-opt-in/same-host-https/video-tag/top-level/no-redirect/allowed.https-expected.txt new file mode 100644 index 0000000..228c938f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/allowed/no-opt-in/same-host-https/video-tag/top-level/no-redirect/allowed.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: no-opt-in + origin: same-host-https + source_scheme: https + context_nesting: top-level + redirection: no-redirect + subresource: video-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https-expected.txt new file mode 100644 index 0000000..d98a36f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: no-opt-in + origin: cross-origin-http + source_scheme: https + context_nesting: top-level + redirection: keep-scheme-redirect + subresource: audio-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/no-redirect/no-opt-in-allows.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/no-redirect/no-opt-in-allows.https-expected.txt new file mode 100644 index 0000000..fcf141f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/no-redirect/no-opt-in-allows.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: no-opt-in + origin: cross-origin-http + source_scheme: https + context_nesting: top-level + redirection: no-redirect + subresource: audio-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https-expected.txt new file mode 100644 index 0000000..35a25232 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: no-opt-in + origin: cross-origin-http + source_scheme: https + context_nesting: top-level + redirection: swap-scheme-redirect + subresource: audio-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https-expected.txt new file mode 100644 index 0000000..68e4c5f3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: no-opt-in + origin: cross-origin-http + source_scheme: https + context_nesting: top-level + redirection: keep-scheme-redirect + subresource: video-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/no-redirect/no-opt-in-allows.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/no-redirect/no-opt-in-allows.https-expected.txt new file mode 100644 index 0000000..85532b4b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/no-redirect/no-opt-in-allows.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: no-opt-in + origin: cross-origin-http + source_scheme: https + context_nesting: top-level + redirection: no-redirect + subresource: video-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https-expected.txt new file mode 100644 index 0000000..2bca83be --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: no-opt-in + origin: cross-origin-http + source_scheme: https + context_nesting: top-level + redirection: swap-scheme-redirect + subresource: video-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https-expected.txt new file mode 100644 index 0000000..8cd8c2d --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: no-opt-in + origin: same-host-http + source_scheme: https + context_nesting: top-level + redirection: keep-scheme-redirect + subresource: audio-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/no-redirect/no-opt-in-allows.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/no-redirect/no-opt-in-allows.https-expected.txt new file mode 100644 index 0000000..24dea3b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/no-redirect/no-opt-in-allows.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: no-opt-in + origin: same-host-http + source_scheme: https + context_nesting: top-level + redirection: no-redirect + subresource: audio-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https-expected.txt new file mode 100644 index 0000000..86dd1ff2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: no-opt-in + origin: same-host-http + source_scheme: https + context_nesting: top-level + redirection: swap-scheme-redirect + subresource: audio-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https-expected.txt new file mode 100644 index 0000000..eff10c8f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: no-opt-in + origin: same-host-http + source_scheme: https + context_nesting: top-level + redirection: keep-scheme-redirect + subresource: video-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/no-redirect/no-opt-in-allows.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/no-redirect/no-opt-in-allows.https-expected.txt new file mode 100644 index 0000000..dfb612b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/no-redirect/no-opt-in-allows.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: no-opt-in + origin: same-host-http + source_scheme: https + context_nesting: top-level + redirection: no-redirect + subresource: video-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https-expected.txt new file mode 100644 index 0000000..6866856 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +FAIL opt_in_method: no-opt-in + origin: same-host-http + source_scheme: https + context_nesting: top-level + redirection: swap-scheme-redirect + subresource: video-tag + expectation: allowed assert_equals: The triggered event should match 'allowed'. expected "allowed" but got "blocked" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/fast/text/selection-exceptions-expected.txt b/third_party/WebKit/LayoutTests/fast/text/selection-exceptions-expected.txt index 6ed111c..dd9f853 100644 --- a/third_party/WebKit/LayoutTests/fast/text/selection-exceptions-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/text/selection-exceptions-expected.txt
@@ -3,15 +3,15 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -PASS getSelection().collapse(document.documentElement, -1) threw exception IndexSizeError: Failed to execute 'collapse' on 'Selection': There is no child at offset -1.. +PASS getSelection().collapse(document.documentElement, -1) threw exception IndexSizeError: Failed to execute 'collapse' on 'Selection': There is no child at offset 4294967295.. PASS getSelection().collapseToStart() threw exception InvalidStateError: Failed to execute 'collapseToStart' on 'Selection': there is no selection.. PASS getSelection().collapseToEnd() threw exception InvalidStateError: Failed to execute 'collapseToEnd' on 'Selection': there is no selection.. -PASS getSelection().setBaseAndExtent(document.documentElement, -1, document.documentElement, 0) threw exception IndexSizeError: Failed to execute 'setBaseAndExtent' on 'Selection': There is no child at offset -1.. -PASS getSelection().setBaseAndExtent(document.documentElement, 0, document.documentElement, -1) threw exception IndexSizeError: Failed to execute 'setBaseAndExtent' on 'Selection': There is no child at offset -1.. -PASS getSelection().collapse(document.documentElement, -1) threw exception IndexSizeError: Failed to execute 'collapse' on 'Selection': There is no child at offset -1.. +PASS getSelection().setBaseAndExtent(document.documentElement, -1, document.documentElement, 0) threw exception IndexSizeError: Failed to execute 'setBaseAndExtent' on 'Selection': There is no child at offset 4294967295.. +PASS getSelection().setBaseAndExtent(document.documentElement, 0, document.documentElement, -1) threw exception IndexSizeError: Failed to execute 'setBaseAndExtent' on 'Selection': There is no child at offset 4294967295.. +PASS getSelection().collapse(document.documentElement, -1) threw exception IndexSizeError: Failed to execute 'collapse' on 'Selection': There is no child at offset 4294967295.. PASS getSelection().getRangeAt(-1) threw exception IndexSizeError: Failed to execute 'getRangeAt' on 'Selection': -1 is not a valid index.. PASS getSelection().extend(0, -1) threw exception TypeError: Failed to execute 'extend' on 'Selection': parameter 1 is not of type 'Node'.. -PASS getSelection().extend(document.documentElement, -1) threw exception IndexSizeError: Failed to execute 'extend' on 'Selection': There is no child at offset -1.. +PASS getSelection().extend(document.documentElement, -1) threw exception IndexSizeError: Failed to execute 'extend' on 'Selection': There is no child at offset 4294967295.. PASS getSelection().extend(document.documentElement, 1000) threw exception IndexSizeError: Failed to execute 'extend' on 'Selection': There is no child at offset 1000.. PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/fast/text/selection-exceptions.html b/third_party/WebKit/LayoutTests/fast/text/selection-exceptions.html index d2bf0bf..51df485 100644 --- a/third_party/WebKit/LayoutTests/fast/text/selection-exceptions.html +++ b/third_party/WebKit/LayoutTests/fast/text/selection-exceptions.html
@@ -7,22 +7,22 @@ <script> description("This tests that 'Selection' methods throw exceptions with reasonable messages."); - shouldThrow('getSelection().collapse(document.documentElement, -1)', '"IndexSizeError: Failed to execute \'collapse\' on \'Selection\': There is no child at offset -1."'); + shouldThrow('getSelection().collapse(document.documentElement, -1)', '"IndexSizeError: Failed to execute \'collapse\' on \'Selection\': There is no child at offset 4294967295."'); getSelection().empty(); shouldThrow('getSelection().collapseToStart()', '"InvalidStateError: Failed to execute \'collapseToStart\' on \'Selection\': there is no selection."'); shouldThrow('getSelection().collapseToEnd()', '"InvalidStateError: Failed to execute \'collapseToEnd\' on \'Selection\': there is no selection."'); - shouldThrow('getSelection().setBaseAndExtent(document.documentElement, -1, document.documentElement, 0)', '"IndexSizeError: Failed to execute \'setBaseAndExtent\' on \'Selection\': There is no child at offset -1."'); - shouldThrow('getSelection().setBaseAndExtent(document.documentElement, 0, document.documentElement, -1)', '"IndexSizeError: Failed to execute \'setBaseAndExtent\' on \'Selection\': There is no child at offset -1."'); + shouldThrow('getSelection().setBaseAndExtent(document.documentElement, -1, document.documentElement, 0)', '"IndexSizeError: Failed to execute \'setBaseAndExtent\' on \'Selection\': There is no child at offset 4294967295."'); + shouldThrow('getSelection().setBaseAndExtent(document.documentElement, 0, document.documentElement, -1)', '"IndexSizeError: Failed to execute \'setBaseAndExtent\' on \'Selection\': There is no child at offset 4294967295."'); - shouldThrow('getSelection().collapse(document.documentElement, -1)', '"IndexSizeError: Failed to execute \'collapse\' on \'Selection\': There is no child at offset -1."'); + shouldThrow('getSelection().collapse(document.documentElement, -1)', '"IndexSizeError: Failed to execute \'collapse\' on \'Selection\': There is no child at offset 4294967295."'); shouldThrow('getSelection().getRangeAt(-1)', '"IndexSizeError: Failed to execute \'getRangeAt\' on \'Selection\': -1 is not a valid index."'); shouldThrow('getSelection().extend(0, -1)', '"TypeError: Failed to execute \'extend\' on \'Selection\': parameter 1 is not of type \'Node\'."'); getSelection().addRange(document.createRange()); - shouldThrow('getSelection().extend(document.documentElement, -1)', '"IndexSizeError: Failed to execute \'extend\' on \'Selection\': There is no child at offset -1."'); + shouldThrow('getSelection().extend(document.documentElement, -1)', '"IndexSizeError: Failed to execute \'extend\' on \'Selection\': There is no child at offset 4294967295."'); shouldThrow('getSelection().extend(document.documentElement, 1000)', '"IndexSizeError: Failed to execute \'extend\' on \'Selection\': There is no child at offset 1000."'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/vr/getVRDisplays_detached.html b/third_party/WebKit/LayoutTests/vr/getVRDisplays_detached.html new file mode 100644 index 0000000..b3d7079a --- /dev/null +++ b/third_party/WebKit/LayoutTests/vr/getVRDisplays_detached.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html> +<head> +<title>Detached use of navigator.getVRDisplays()</title> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +</head> +<body> +<iframe sandbox="allow-same-origin" id="subframe"></iframe> +<script> +test(() => { + var nav = window.frames[0].navigator; + document.getElementById("subframe").remove(); + // A promise won't be rejected when in a detached context, + // so the undefined value is returned. + assert_equals(nav.getVRDisplays(), undefined); +}); +</script> +</body> +</html>
diff --git a/third_party/WebKit/Source/core/dom/BUILD.gn b/third_party/WebKit/Source/core/dom/BUILD.gn index d9183b9f..09ff510 100644 --- a/third_party/WebKit/Source/core/dom/BUILD.gn +++ b/third_party/WebKit/Source/core/dom/BUILD.gn
@@ -261,6 +261,8 @@ "ShadowTreeStyleSheetCollection.cpp", "ShadowTreeStyleSheetCollection.h", "SimulatedClickOptions.h", + "SinkDocument.cpp", + "SinkDocument.h", "SpaceSplitString.cpp", "StaticNodeList.h", "StaticRange.cpp",
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp index 4b14631..03583eda 100644 --- a/third_party/WebKit/Source/core/dom/Element.cpp +++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -2693,7 +2693,10 @@ // When focusing an editable element in an iframe, don't reset the selection // if it already contains a selection. - if (this == frame->selection().rootEditableElement()) + if (this == + frame->selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .rootEditableElement()) return; // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
diff --git a/third_party/WebKit/Source/core/dom/NodeWithIndex.h b/third_party/WebKit/Source/core/dom/NodeWithIndex.h index 9d8fc49..aa74968 100644 --- a/third_party/WebKit/Source/core/dom/NodeWithIndex.h +++ b/third_party/WebKit/Source/core/dom/NodeWithIndex.h
@@ -41,6 +41,7 @@ Node& node() const { return *m_node; } + // TODO(tkent): Should be unsigned. int index() const { if (!hasIndex()) m_index = node().nodeIndex();
diff --git a/third_party/WebKit/Source/core/dom/Range.cpp b/third_party/WebKit/Source/core/dom/Range.cpp index 0805621..bd212e13 100644 --- a/third_party/WebKit/Source/core/dom/Range.cpp +++ b/third_party/WebKit/Source/core/dom/Range.cpp
@@ -70,9 +70,9 @@ inline Range::Range(Document& ownerDocument, Node* startContainer, - int startOffset, + unsigned startOffset, Node* endContainer, - int endOffset) + unsigned endOffset) : m_ownerDocument(&ownerDocument), m_start(m_ownerDocument), m_end(m_ownerDocument) { @@ -86,9 +86,9 @@ Range* Range::create(Document& ownerDocument, Node* startContainer, - int startOffset, + unsigned startOffset, Node* endContainer, - int endOffset) { + unsigned endOffset) { return new Range(ownerDocument, startContainer, startOffset, endContainer, endOffset); } @@ -163,7 +163,7 @@ } void Range::setStart(Node* refNode, - int offset, + unsigned offset, ExceptionState& exceptionState) { if (!refNode) { // FIXME: Generated bindings code never calls with null, and neither should @@ -193,7 +193,9 @@ updateSelectionIfAddedToSelection(); } -void Range::setEnd(Node* refNode, int offset, ExceptionState& exceptionState) { +void Range::setEnd(Node* refNode, + unsigned offset, + ExceptionState& exceptionState) { if (!refNode) { // FIXME: Generated bindings code never calls with null, and neither should // other callers! @@ -244,7 +246,7 @@ bool Range::isNodeFullyContained(Node& node) const { ContainerNode* parentNode = node.parentNode(); - int nodeIndex = node.nodeIndex(); + unsigned nodeIndex = node.nodeIndex(); return isPointInRange( parentNode, nodeIndex, IGNORE_EXCEPTION_FOR_TESTING) // starts in the middle of this @@ -268,7 +270,7 @@ } bool Range::isPointInRange(Node* refNode, - int offset, + unsigned offset, ExceptionState& exceptionState) const { if (!refNode) { // FIXME: Generated bindings code never calls with null, and neither should @@ -292,7 +294,7 @@ } short Range::comparePoint(Node* refNode, - int offset, + unsigned offset, ExceptionState& exceptionState) const { // http://developer.mozilla.org/en/docs/DOM:range.comparePoint // This method returns -1, 0 or 1 depending on if the point described by the @@ -379,9 +381,9 @@ } short Range::compareBoundaryPoints(Node* containerA, - int offsetA, + unsigned offsetA, Node* containerB, - int offsetB, + unsigned offsetB, ExceptionState& exceptionState) { bool disconnected = false; short result = comparePositionsInDOMTree(containerA, offsetA, containerB, @@ -957,13 +959,12 @@ Node::NodeType type = n->getNodeType(); if (type == Node::kTextNode || type == Node::kCdataSectionNode) { String data = toCharacterData(n)->data(); - int length = data.length(); - int start = (n == m_start.container()) - ? std::min(std::max(0, m_start.offset()), length) - : 0; - int end = (n == m_end.container()) - ? std::min(std::max(start, m_end.offset()), length) - : length; + unsigned length = data.length(); + unsigned start = + (n == m_start.container()) ? std::min(m_start.offset(), length) : 0; + unsigned end = (n == m_end.container()) + ? std::min(std::max(start, m_end.offset()), length) + : length; builder.append(data, start, end - start); } } @@ -1025,7 +1026,7 @@ } Node* Range::checkNodeWOffset(Node* n, - int offset, + unsigned offset, ExceptionState& exceptionState) { switch (n->getNodeType()) { case Node::kDocumentTypeNode: @@ -1036,22 +1037,23 @@ case Node::kCdataSectionNode: case Node::kCommentNode: case Node::kTextNode: - if (static_cast<unsigned>(offset) > toCharacterData(n)->length()) + if (offset > toCharacterData(n)->length()) { exceptionState.throwDOMException( - IndexSizeError, - "The offset " + String::number(offset) + - " is larger than or equal to the node's length (" + - String::number(toCharacterData(n)->length()) + ")."); + IndexSizeError, "The offset " + String::number(offset) + + " is larger than the node's length (" + + String::number(toCharacterData(n)->length()) + + ")."); + } return nullptr; case Node::kProcessingInstructionNode: - if (static_cast<unsigned>(offset) > - toProcessingInstruction(n)->data().length()) + if (offset > toProcessingInstruction(n)->data().length()) { exceptionState.throwDOMException( IndexSizeError, "The offset " + String::number(offset) + - " is larger than or equal to than the node's length (" + + " is larger than the node's length (" + String::number(toProcessingInstruction(n)->data().length()) + ")."); + } return nullptr; case Node::kAttributeNode: case Node::kDocumentFragmentNode: @@ -1060,10 +1062,11 @@ if (!offset) return nullptr; Node* childBefore = NodeTraversal::childAt(*n, offset - 1); - if (!childBefore) + if (!childBefore) { exceptionState.throwDOMException( IndexSizeError, "There is no child at offset " + String::number(offset) + "."); + } return childBefore; } } @@ -1424,9 +1427,10 @@ if (!r || !r->isText()) continue; LayoutText* layoutText = toLayoutText(r); - int startOffset = node == startContainer ? m_start.offset() : 0; - int endOffset = - node == endContainer ? m_end.offset() : std::numeric_limits<int>::max(); + unsigned startOffset = node == startContainer ? m_start.offset() : 0; + unsigned endOffset = node == endContainer + ? m_end.offset() + : std::numeric_limits<unsigned>::max(); layoutText->absoluteRectsForRange(rects, startOffset, endOffset, useSelectionHeight); } @@ -1445,9 +1449,10 @@ if (!r || !r->isText()) continue; LayoutText* layoutText = toLayoutText(r); - int startOffset = node == startContainer ? m_start.offset() : 0; - int endOffset = - node == endContainer ? m_end.offset() : std::numeric_limits<int>::max(); + unsigned startOffset = node == startContainer ? m_start.offset() : 0; + unsigned endOffset = node == endContainer + ? m_end.offset() + : std::numeric_limits<unsigned>::max(); layoutText->absoluteQuadsForRange(quads, startOffset, endOffset, useSelectionHeight); } @@ -1564,7 +1569,7 @@ boundary.set(oldNode.node().previousSibling(), boundary.offset() + offset, 0); else if (boundary.container() == oldNode.node().parentNode() && - boundary.offset() == oldNode.index()) + boundary.offset() == static_cast<unsigned>(oldNode.index())) boundary.set(oldNode.node().previousSibling(), offset, 0); } @@ -1682,8 +1687,10 @@ } } else if (node->isTextNode()) { if (LayoutText* layoutText = toText(node)->layoutObject()) { - int startOffset = (node == startContainer) ? m_start.offset() : 0; - int endOffset = (node == endContainer) ? m_end.offset() : INT_MAX; + unsigned startOffset = (node == startContainer) ? m_start.offset() : 0; + unsigned endOffset = (node == endContainer) + ? m_end.offset() + : std::numeric_limits<unsigned>::max(); Vector<FloatQuad> textQuads; layoutText->absoluteQuadsForRange(textQuads, startOffset, endOffset);
diff --git a/third_party/WebKit/Source/core/dom/Range.h b/third_party/WebKit/Source/core/dom/Range.h index 18bc278c..f76b3f020 100644 --- a/third_party/WebKit/Source/core/dom/Range.h +++ b/third_party/WebKit/Source/core/dom/Range.h
@@ -56,9 +56,9 @@ static Range* create(Document&); static Range* create(Document&, Node* startContainer, - int startOffset, + unsigned startOffset, Node* endContainer, - int endOffset); + unsigned endOffset); static Range* create(Document&, const Position&, const Position&); static Range* createAdjustedToTreeScope(const TreeScope&, const Position&); @@ -69,9 +69,9 @@ return *m_ownerDocument.get(); } Node* startContainer() const { return m_start.container(); } - int startOffset() const { return m_start.offset(); } + unsigned startOffset() const { return m_start.offset(); } Node* endContainer() const { return m_end.container(); } - int endOffset() const { return m_end.offset(); } + unsigned endOffset() const { return m_end.offset(); } bool collapsed() const { return m_start == m_end; } bool isConnected() const; @@ -80,15 +80,15 @@ static Node* commonAncestorContainer(const Node* containerA, const Node* containerB); void setStart(Node* container, - int offset, + unsigned offset, ExceptionState& = ASSERT_NO_EXCEPTION); void setEnd(Node* container, - int offset, + unsigned offset, ExceptionState& = ASSERT_NO_EXCEPTION); void collapse(bool toStart); bool isNodeFullyContained(Node&) const; - bool isPointInRange(Node* refNode, int offset, ExceptionState&) const; - short comparePoint(Node* refNode, int offset, ExceptionState&) const; + bool isPointInRange(Node* refNode, unsigned offset, ExceptionState&) const; + short comparePoint(Node* refNode, unsigned offset, ExceptionState&) const; enum CompareResults { NODE_BEFORE, NODE_AFTER, @@ -100,9 +100,9 @@ const Range* sourceRange, ExceptionState&) const; static short compareBoundaryPoints(Node* containerA, - int offsetA, + unsigned offsetA, Node* containerB, - int offsetB, + unsigned offsetB, ExceptionState&); static short compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const RangeBoundaryPoint& boundaryB, @@ -166,7 +166,7 @@ ClientRectList* getClientRects() const; ClientRect* getBoundingClientRect() const; - static Node* checkNodeWOffset(Node*, int offset, ExceptionState&); + static Node* checkNodeWOffset(Node*, unsigned offset, ExceptionState&); DECLARE_TRACE(); @@ -174,9 +174,9 @@ explicit Range(Document&); Range(Document&, Node* startContainer, - int startOffset, + unsigned startOffset, Node* endContainer, - int endOffset); + unsigned endOffset); void setDocument(Document&);
diff --git a/third_party/WebKit/Source/core/dom/Range.idl b/third_party/WebKit/Source/core/dom/Range.idl index d5a8567..5c45326 100644 --- a/third_party/WebKit/Source/core/dom/Range.idl +++ b/third_party/WebKit/Source/core/dom/Range.idl
@@ -19,21 +19,19 @@ */ // https://dom.spec.whatwg.org/#interface-range - -// FIXME: All long types in this interface should be unsigned long. [ Constructor, ConstructorCallWith=Document, ] interface Range { readonly attribute Node startContainer; - readonly attribute long startOffset; + readonly attribute unsigned long startOffset; readonly attribute Node endContainer; - readonly attribute long endOffset; + readonly attribute unsigned long endOffset; readonly attribute boolean collapsed; readonly attribute Node commonAncestorContainer; - [RaisesException] void setStart(Node node, long offset); - [RaisesException] void setEnd(Node node, long offset); + [RaisesException] void setStart(Node node, unsigned long offset); + [RaisesException] void setEnd(Node node, unsigned long offset); [RaisesException] void setStartBefore(Node node); [RaisesException] void setStartAfter(Node node); [RaisesException] void setEndBefore(Node node); @@ -57,8 +55,8 @@ [NewObject] Range cloneRange(); [MeasureAs=RangeDetach] void detach(); - [RaisesException] boolean isPointInRange(Node node, long offset); - [RaisesException] short comparePoint(Node node, long offset); + [RaisesException] boolean isPointInRange(Node node, unsigned long offset); + [RaisesException] short comparePoint(Node node, unsigned long offset); [RaisesException] boolean intersectsNode(Node node);
diff --git a/third_party/WebKit/Source/core/dom/RangeBoundaryPoint.h b/third_party/WebKit/Source/core/dom/RangeBoundaryPoint.h index 7b2dd71..32d2681f 100644 --- a/third_party/WebKit/Source/core/dom/RangeBoundaryPoint.h +++ b/third_party/WebKit/Source/core/dom/RangeBoundaryPoint.h
@@ -44,13 +44,13 @@ const Position toPosition() const; Node* container() const; - int offset() const; + unsigned offset() const; Node* childBefore() const; void clear(); - void set(Node* container, int offset, Node* childBefore); - void setOffset(int); + void set(Node* container, unsigned offset, Node* childBefore); + void setOffset(unsigned); void setToBeforeChild(Node&); void setToStartOfNode(Node&); @@ -70,12 +70,12 @@ void ensureOffsetIsValid() const; bool isOffsetValid() const; - static const int invalidOffset = -1; + static const unsigned invalidOffset = static_cast<unsigned>(-1); Member<Node> m_containerNode; Member<Node> m_childBeforeBoundary; mutable uint64_t m_domTreeVersion; - mutable int m_offsetInContainer; + mutable unsigned m_offsetInContainer; }; inline RangeBoundaryPoint::RangeBoundaryPoint(Node* container) @@ -135,7 +135,7 @@ m_offsetInContainer); } -inline int RangeBoundaryPoint::offset() const { +inline unsigned RangeBoundaryPoint::offset() const { ensureOffsetIsValid(); return m_offsetInContainer; } @@ -148,10 +148,10 @@ } inline void RangeBoundaryPoint::set(Node* container, - int offset, + unsigned offset, Node* childBefore) { DCHECK(container); - DCHECK_GE(offset, 0); + DCHECK_GE(offset, 0u); DCHECK_EQ(childBefore, offset ? NodeTraversal::childAt(*container, offset - 1) : 0); m_containerNode = container; @@ -160,10 +160,10 @@ markValid(); } -inline void RangeBoundaryPoint::setOffset(int offset) { +inline void RangeBoundaryPoint::setOffset(unsigned offset) { DCHECK(m_containerNode); DCHECK(m_containerNode->isCharacterDataNode()); - DCHECK_GE(m_offsetInContainer, 0); + DCHECK_GE(m_offsetInContainer, 0u); DCHECK(!m_childBeforeBoundary); m_offsetInContainer = offset; markValid(); @@ -200,7 +200,7 @@ m_childBeforeBoundary = m_childBeforeBoundary->previousSibling(); if (!isOffsetValid()) return; - DCHECK_GT(m_offsetInContainer, 0); + DCHECK_GT(m_offsetInContainer, 0u); if (!m_childBeforeBoundary) m_offsetInContainer = 0; else if (m_offsetInContainer > 0)
diff --git a/third_party/WebKit/Source/core/dom/RangeTest.cpp b/third_party/WebKit/Source/core/dom/RangeTest.cpp index c3127e40..18762ae 100644 --- a/third_party/WebKit/Source/core/dom/RangeTest.cpp +++ b/third_party/WebKit/Source/core/dom/RangeTest.cpp
@@ -76,29 +76,29 @@ EXPECT_TRUE(range04->boundaryPointsValid()); EXPECT_EQ(oldText, range04->startContainer()); - EXPECT_EQ(0, range04->startOffset()); + EXPECT_EQ(0u, range04->startOffset()); EXPECT_EQ(newText, range04->endContainer()); - EXPECT_EQ(2, range04->endOffset()); + EXPECT_EQ(2u, range04->endOffset()); EXPECT_TRUE(range02->boundaryPointsValid()); EXPECT_EQ(oldText, range02->startContainer()); - EXPECT_EQ(0, range02->startOffset()); + EXPECT_EQ(0u, range02->startOffset()); EXPECT_EQ(oldText, range02->endContainer()); - EXPECT_EQ(2, range02->endOffset()); + EXPECT_EQ(2u, range02->endOffset()); // Our implementation always moves the boundary point at the separation point // to the end of the original text node. EXPECT_TRUE(range22->boundaryPointsValid()); EXPECT_EQ(oldText, range22->startContainer()); - EXPECT_EQ(2, range22->startOffset()); + EXPECT_EQ(2u, range22->startOffset()); EXPECT_EQ(oldText, range22->endContainer()); - EXPECT_EQ(2, range22->endOffset()); + EXPECT_EQ(2u, range22->endOffset()); EXPECT_TRUE(range24->boundaryPointsValid()); EXPECT_EQ(oldText, range24->startContainer()); - EXPECT_EQ(2, range24->startOffset()); + EXPECT_EQ(2u, range24->startOffset()); EXPECT_EQ(newText, range24->endContainer()); - EXPECT_EQ(2, range24->endOffset()); + EXPECT_EQ(2u, range24->endOffset()); } TEST_F(RangeTest, SplitTextNodeRangeOutsideText) { @@ -128,41 +128,41 @@ EXPECT_TRUE(rangeOuterOutside->boundaryPointsValid()); EXPECT_EQ(outer, rangeOuterOutside->startContainer()); - EXPECT_EQ(0, rangeOuterOutside->startOffset()); + EXPECT_EQ(0u, rangeOuterOutside->startOffset()); EXPECT_EQ(outer, rangeOuterOutside->endContainer()); - EXPECT_EQ(6, + EXPECT_EQ(6u, rangeOuterOutside ->endOffset()); // Increased by 1 since a new node is inserted. EXPECT_TRUE(rangeOuterInside->boundaryPointsValid()); EXPECT_EQ(outer, rangeOuterInside->startContainer()); - EXPECT_EQ(1, rangeOuterInside->startOffset()); + EXPECT_EQ(1u, rangeOuterInside->startOffset()); EXPECT_EQ(outer, rangeOuterInside->endContainer()); - EXPECT_EQ(5, rangeOuterInside->endOffset()); + EXPECT_EQ(5u, rangeOuterInside->endOffset()); EXPECT_TRUE(rangeOuterSurroundingText->boundaryPointsValid()); EXPECT_EQ(outer, rangeOuterSurroundingText->startContainer()); - EXPECT_EQ(2, rangeOuterSurroundingText->startOffset()); + EXPECT_EQ(2u, rangeOuterSurroundingText->startOffset()); EXPECT_EQ(outer, rangeOuterSurroundingText->endContainer()); - EXPECT_EQ(4, rangeOuterSurroundingText->endOffset()); + EXPECT_EQ(4u, rangeOuterSurroundingText->endOffset()); EXPECT_TRUE(rangeInnerLeft->boundaryPointsValid()); EXPECT_EQ(innerLeft, rangeInnerLeft->startContainer()); - EXPECT_EQ(0, rangeInnerLeft->startOffset()); + EXPECT_EQ(0u, rangeInnerLeft->startOffset()); EXPECT_EQ(innerLeft, rangeInnerLeft->endContainer()); - EXPECT_EQ(1, rangeInnerLeft->endOffset()); + EXPECT_EQ(1u, rangeInnerLeft->endOffset()); EXPECT_TRUE(rangeInnerRight->boundaryPointsValid()); EXPECT_EQ(innerRight, rangeInnerRight->startContainer()); - EXPECT_EQ(0, rangeInnerRight->startOffset()); + EXPECT_EQ(0u, rangeInnerRight->startOffset()); EXPECT_EQ(innerRight, rangeInnerRight->endContainer()); - EXPECT_EQ(1, rangeInnerRight->endOffset()); + EXPECT_EQ(1u, rangeInnerRight->endOffset()); EXPECT_TRUE(rangeFromTextToMiddleOfElement->boundaryPointsValid()); EXPECT_EQ(newText, rangeFromTextToMiddleOfElement->startContainer()); - EXPECT_EQ(3, rangeFromTextToMiddleOfElement->startOffset()); + EXPECT_EQ(3u, rangeFromTextToMiddleOfElement->startOffset()); EXPECT_EQ(outer, rangeFromTextToMiddleOfElement->endContainer()); - EXPECT_EQ(4, rangeFromTextToMiddleOfElement->endOffset()); + EXPECT_EQ(4u, rangeFromTextToMiddleOfElement->endOffset()); } TEST_F(RangeTest, updateOwnerDocumentIfNeeded) { @@ -176,9 +176,9 @@ anotherDocument->appendChild(foo); EXPECT_EQ(bar, range->startContainer()); - EXPECT_EQ(0, range->startOffset()); + EXPECT_EQ(0u, range->startOffset()); EXPECT_EQ(foo, range->endContainer()); - EXPECT_EQ(1, range->endOffset()); + EXPECT_EQ(1u, range->endOffset()); } // Regression test for crbug.com/639184 @@ -198,9 +198,9 @@ EXPECT_TRUE(range->boundaryPointsValid()); EXPECT_EQ(span2, range->startContainer()); - EXPECT_EQ(0, range->startOffset()); + EXPECT_EQ(0u, range->startOffset()); EXPECT_EQ(div, range->endContainer()); - EXPECT_EQ(2, range->endOffset()); + EXPECT_EQ(2u, range->endOffset()); } // Regression test for crbug.com/639184 @@ -220,9 +220,9 @@ EXPECT_TRUE(range->boundaryPointsValid()); EXPECT_EQ(span2, range->startContainer()); - EXPECT_EQ(0, range->startOffset()); + EXPECT_EQ(0u, range->startOffset()); EXPECT_EQ(div, range->endContainer()); - EXPECT_EQ(2, range->endOffset()); + EXPECT_EQ(2u, range->endOffset()); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/SinkDocument.cpp b/third_party/WebKit/Source/core/dom/SinkDocument.cpp similarity index 98% rename from third_party/WebKit/Source/core/loader/SinkDocument.cpp rename to third_party/WebKit/Source/core/dom/SinkDocument.cpp index a0e1cb1..30c42a1 100644 --- a/third_party/WebKit/Source/core/loader/SinkDocument.cpp +++ b/third_party/WebKit/Source/core/dom/SinkDocument.cpp
@@ -23,7 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "core/loader/SinkDocument.h" +#include "core/dom/SinkDocument.h" #include "core/dom/RawDataDocumentParser.h" #include "core/frame/UseCounter.h"
diff --git a/third_party/WebKit/Source/core/loader/SinkDocument.h b/third_party/WebKit/Source/core/dom/SinkDocument.h similarity index 100% rename from third_party/WebKit/Source/core/loader/SinkDocument.h rename to third_party/WebKit/Source/core/dom/SinkDocument.h
diff --git a/third_party/WebKit/Source/core/dom/StaticRangeTest.cpp b/third_party/WebKit/Source/core/dom/StaticRangeTest.cpp index 1fd88c54..885cfe7 100644 --- a/third_party/WebKit/Source/core/dom/StaticRangeTest.cpp +++ b/third_party/WebKit/Source/core/dom/StaticRangeTest.cpp
@@ -66,29 +66,29 @@ // Range should mutate. EXPECT_TRUE(range04->boundaryPointsValid()); EXPECT_EQ(oldText, range04->startContainer()); - EXPECT_EQ(0, range04->startOffset()); + EXPECT_EQ(0u, range04->startOffset()); EXPECT_EQ(newText, range04->endContainer()); - EXPECT_EQ(2, range04->endOffset()); + EXPECT_EQ(2u, range04->endOffset()); EXPECT_TRUE(range02->boundaryPointsValid()); EXPECT_EQ(oldText, range02->startContainer()); - EXPECT_EQ(0, range02->startOffset()); + EXPECT_EQ(0u, range02->startOffset()); EXPECT_EQ(oldText, range02->endContainer()); - EXPECT_EQ(2, range02->endOffset()); + EXPECT_EQ(2u, range02->endOffset()); // Our implementation always moves the boundary point at the separation point // to the end of the original text node. EXPECT_TRUE(range22->boundaryPointsValid()); EXPECT_EQ(oldText, range22->startContainer()); - EXPECT_EQ(2, range22->startOffset()); + EXPECT_EQ(2u, range22->startOffset()); EXPECT_EQ(oldText, range22->endContainer()); - EXPECT_EQ(2, range22->endOffset()); + EXPECT_EQ(2u, range22->endOffset()); EXPECT_TRUE(range24->boundaryPointsValid()); EXPECT_EQ(oldText, range24->startContainer()); - EXPECT_EQ(2, range24->startOffset()); + EXPECT_EQ(2u, range24->startOffset()); EXPECT_EQ(newText, range24->endContainer()); - EXPECT_EQ(2, range24->endOffset()); + EXPECT_EQ(2u, range24->endOffset()); // StaticRange shouldn't mutate. EXPECT_EQ(oldText, staticRange04->startContainer()); @@ -154,41 +154,41 @@ // Range should mutate. EXPECT_TRUE(rangeOuterOutside->boundaryPointsValid()); EXPECT_EQ(outer, rangeOuterOutside->startContainer()); - EXPECT_EQ(0, rangeOuterOutside->startOffset()); + EXPECT_EQ(0u, rangeOuterOutside->startOffset()); EXPECT_EQ(outer, rangeOuterOutside->endContainer()); - EXPECT_EQ(6, + EXPECT_EQ(6u, rangeOuterOutside ->endOffset()); // Increased by 1 since a new node is inserted. EXPECT_TRUE(rangeOuterInside->boundaryPointsValid()); EXPECT_EQ(outer, rangeOuterInside->startContainer()); - EXPECT_EQ(1, rangeOuterInside->startOffset()); + EXPECT_EQ(1u, rangeOuterInside->startOffset()); EXPECT_EQ(outer, rangeOuterInside->endContainer()); - EXPECT_EQ(5, rangeOuterInside->endOffset()); + EXPECT_EQ(5u, rangeOuterInside->endOffset()); EXPECT_TRUE(rangeOuterSurroundingText->boundaryPointsValid()); EXPECT_EQ(outer, rangeOuterSurroundingText->startContainer()); - EXPECT_EQ(2, rangeOuterSurroundingText->startOffset()); + EXPECT_EQ(2u, rangeOuterSurroundingText->startOffset()); EXPECT_EQ(outer, rangeOuterSurroundingText->endContainer()); - EXPECT_EQ(4, rangeOuterSurroundingText->endOffset()); + EXPECT_EQ(4u, rangeOuterSurroundingText->endOffset()); EXPECT_TRUE(rangeInnerLeft->boundaryPointsValid()); EXPECT_EQ(innerLeft, rangeInnerLeft->startContainer()); - EXPECT_EQ(0, rangeInnerLeft->startOffset()); + EXPECT_EQ(0u, rangeInnerLeft->startOffset()); EXPECT_EQ(innerLeft, rangeInnerLeft->endContainer()); - EXPECT_EQ(1, rangeInnerLeft->endOffset()); + EXPECT_EQ(1u, rangeInnerLeft->endOffset()); EXPECT_TRUE(rangeInnerRight->boundaryPointsValid()); EXPECT_EQ(innerRight, rangeInnerRight->startContainer()); - EXPECT_EQ(0, rangeInnerRight->startOffset()); + EXPECT_EQ(0u, rangeInnerRight->startOffset()); EXPECT_EQ(innerRight, rangeInnerRight->endContainer()); - EXPECT_EQ(1, rangeInnerRight->endOffset()); + EXPECT_EQ(1u, rangeInnerRight->endOffset()); EXPECT_TRUE(rangeFromTextToMiddleOfElement->boundaryPointsValid()); EXPECT_EQ(newText, rangeFromTextToMiddleOfElement->startContainer()); - EXPECT_EQ(3, rangeFromTextToMiddleOfElement->startOffset()); + EXPECT_EQ(3u, rangeFromTextToMiddleOfElement->startOffset()); EXPECT_EQ(outer, rangeFromTextToMiddleOfElement->endContainer()); - EXPECT_EQ(4, rangeFromTextToMiddleOfElement->endOffset()); + EXPECT_EQ(4u, rangeFromTextToMiddleOfElement->endOffset()); // StaticRange shouldn't mutate. EXPECT_EQ(outer, staticRangeOuterOutside->startContainer());
diff --git a/third_party/WebKit/Source/core/editing/Editor.cpp b/third_party/WebKit/Source/core/editing/Editor.cpp index ff28ffad..e60d713 100644 --- a/third_party/WebKit/Source/core/editing/Editor.cpp +++ b/third_party/WebKit/Source/core/editing/Editor.cpp
@@ -204,7 +204,7 @@ } static bool isCaretAtStartOfWrappedLine(const FrameSelection& selection) { - if (!selection.isCaret()) + if (!selection.computeVisibleSelectionInDOMTreeDeprecated().isCaret()) return false; if (selection.affinity() != TextAffinity::Downstream) return false; @@ -263,7 +263,10 @@ } bool Editor::canEdit() const { - return frame().selection().rootEditableElement(); + return frame() + .selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .rootEditableElement(); } bool Editor::canEditRichly() const {
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.cpp b/third_party/WebKit/Source/core/editing/FrameSelection.cpp index 5ac86457..7a0fa9a 100644 --- a/third_party/WebKit/Source/core/editing/FrameSelection.cpp +++ b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
@@ -480,7 +480,8 @@ bool FrameSelection::shouldPaintCaret(const LayoutBlock& block) const { DCHECK_GE(document().lifecycle().state(), DocumentLifecycle::LayoutClean); bool result = m_frameCaret->shouldPaintCaret(block); - DCHECK(!result || (isCaret() && hasEditableStyle())); + DCHECK(!result || (computeVisibleSelectionInDOMTreeDeprecated().isCaret() && + hasEditableStyle())); return result; }
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.h b/third_party/WebKit/Source/core/editing/FrameSelection.h index bcb452c..d2a3c77 100644 --- a/third_party/WebKit/Source/core/editing/FrameSelection.h +++ b/third_party/WebKit/Source/core/editing/FrameSelection.h
@@ -198,9 +198,6 @@ Position start() const { return computeVisibleSelectionInDOMTreeDeprecated().start(); } - Position end() const { - return computeVisibleSelectionInDOMTreeDeprecated().end(); - } // Returns true if specified layout block should paint caret. This function is // called during painting only. @@ -216,9 +213,6 @@ bool isNone() const { return computeVisibleSelectionInDOMTreeDeprecated().isNone(); } - bool isCaret() const { - return computeVisibleSelectionInDOMTreeDeprecated().isCaret(); - } bool isRange() const { return computeVisibleSelectionInDOMTreeDeprecated().isRange(); }
diff --git a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp index ddfaa7f..a3c95cd 100644 --- a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp +++ b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
@@ -78,7 +78,8 @@ selection().setSelection( SelectionInDOMTree::Builder().collapse(Position(text, 0)).build()); document().view()->updateAllLifecyclePhases(); - EXPECT_TRUE(selection().isCaret()); + EXPECT_TRUE( + selection().computeVisibleSelectionInDOMTreeDeprecated().isCaret()); EXPECT_TRUE(toLayoutBlock(document().body()->layoutObject()) ->shouldPaintCursorCaret());
diff --git a/third_party/WebKit/Source/core/editing/InputMethodController.cpp b/third_party/WebKit/Source/core/editing/InputMethodController.cpp index 01eaa00..7ea8eddf 100644 --- a/third_party/WebKit/Source/core/editing/InputMethodController.cpp +++ b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
@@ -279,7 +279,11 @@ return true; } - Element* rootEditableElement = frame().selection().rootEditableElement(); + Element* rootEditableElement = + frame() + .selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .rootEditableElement(); if (!rootEditableElement) return false; PlainTextRange compositionRange = @@ -374,7 +378,11 @@ const String& text, int relativeCaretPosition, const Vector<CompositionUnderline>& underlines) { - Element* rootEditableElement = frame().selection().rootEditableElement(); + Element* rootEditableElement = + frame() + .selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .rootEditableElement(); if (!rootEditableElement) return false; DCHECK(hasComposition()); @@ -419,7 +427,11 @@ if (!insertText(text)) return false; - Element* rootEditableElement = frame().selection().rootEditableElement(); + Element* rootEditableElement = + frame() + .selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .rootEditableElement(); if (rootEditableElement) { addCompositionUnderlines(underlines, rootEditableElement, textStart); } @@ -626,7 +638,10 @@ const Vector<CompositionUnderline>& underlines, unsigned compositionStart, unsigned compositionEnd) { - Element* editable = frame().selection().rootEditableElement(); + Element* editable = frame() + .selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .rootEditableElement(); if (!editable) return; @@ -689,7 +704,11 @@ const PlainTextRange& offsets) const { if (offsets.isNull()) return EphemeralRange(); - Element* rootEditableElement = frame().selection().rootEditableElement(); + Element* rootEditableElement = + frame() + .selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .rootEditableElement(); if (!rootEditableElement) return EphemeralRange(); @@ -726,7 +745,11 @@ start = std::max(start, 0); end = std::max(end, start); - Element* rootEditableElement = frame().selection().rootEditableElement(); + Element* rootEditableElement = + frame() + .selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .rootEditableElement(); if (!rootEditableElement) return PlainTextRange(); const EphemeralRange& range = @@ -793,7 +816,11 @@ if (before == 0) break; ++before; - } while (frame().selection().start() == frame().selection().end() && + } while (frame().selection().start() == + frame() + .selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .end() && before <= static_cast<int>(selectionOffsets.start())); // TODO(chongz): Find a way to distinguish Forward and Backward. Node* target = document().focusedElement(); @@ -813,7 +840,10 @@ if (selectionOffsets.isNull()) return; Element* const rootEditableElement = - frame().selection().rootEditableElement(); + frame() + .selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .rootEditableElement(); if (!rootEditableElement) return; int selectionStart = static_cast<int>(selectionOffsets.start()); @@ -877,7 +907,10 @@ // plugins/mouse-capture-inside-shadow.html reaches here. return info; } - Element* element = frame().selection().rootEditableElement(); + Element* element = frame() + .selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .rootEditableElement(); if (!element) return info;
diff --git a/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp b/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp index af4913f..eb342fb 100644 --- a/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp +++ b/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp
@@ -175,8 +175,8 @@ controller().setCompositionFromExistingText(underlines, 0, 5); Range* range = controller().compositionRange(); - EXPECT_EQ(0, range->startOffset()); - EXPECT_EQ(5, range->endOffset()); + EXPECT_EQ(0u, range->startOffset()); + EXPECT_EQ(5u, range->endOffset()); PlainTextRange plainTextRange(PlainTextRange::create(*div, *range)); EXPECT_EQ(0u, plainTextRange.start()); @@ -194,7 +194,11 @@ document().updateStyleAndLayout(); controller().setEditableSelectionOffsets(PlainTextRange(2, 2)); EXPECT_EQ(2, frame().selection().start().computeOffsetInContainerNode()); - EXPECT_EQ(2, frame().selection().end().computeOffsetInContainerNode()); + EXPECT_EQ(2, frame() + .selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .end() + .computeOffsetInContainerNode()); controller().setComposition(String("a"), underlines, 1, 1); EXPECT_STREQ("\xF0\x9F\x8F\x86\x61", div->innerText().utf8().data()); @@ -342,7 +346,11 @@ controller().finishComposingText(InputMethodController::KeepSelection); EXPECT_EQ(0, frame().selection().start().computeOffsetInContainerNode()); - EXPECT_EQ(0, frame().selection().end().computeOffsetInContainerNode()); + EXPECT_EQ(0, frame() + .selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .end() + .computeOffsetInContainerNode()); } TEST_F(InputMethodControllerTest, DeleteBySettingEmptyComposition) { @@ -384,8 +392,8 @@ controller().setCompositionFromExistingText(underlines, 0, 5); Range* range = controller().compositionRange(); - EXPECT_EQ(1, range->startOffset()); - EXPECT_EQ(6, range->endOffset()); + EXPECT_EQ(1u, range->startOffset()); + EXPECT_EQ(6u, range->endOffset()); PlainTextRange plainTextRange(PlainTextRange::create(*div, *range)); EXPECT_EQ(0u, plainTextRange.start());
diff --git a/third_party/WebKit/Source/core/editing/PendingSelection.cpp b/third_party/WebKit/Source/core/editing/PendingSelection.cpp index 1aca83e8..1b10665 100644 --- a/third_party/WebKit/Source/core/editing/PendingSelection.cpp +++ b/third_party/WebKit/Source/core/editing/PendingSelection.cpp
@@ -55,7 +55,7 @@ return true; } -VisibleSelectionInFlatTree PendingSelection::calcVisibleSelection( +SelectionInFlatTree PendingSelection::calcVisibleSelection( const VisibleSelectionInFlatTree& originalSelection) const { const PositionInFlatTree& start = originalSelection.start(); const PositionInFlatTree& end = originalSelection.end(); @@ -66,7 +66,6 @@ m_frameSelection->shouldShowBlockCursor() && selectionType == SelectionType::CaretSelection && !isLogicalEndOfLine(createVisiblePosition(end, affinity)); - VisibleSelectionInFlatTree selection; if (enclosingTextControl(start.computeContainerNode())) { // TODO(yosin) We should use |PositionMoveType::CodePoint| to avoid // ending paint at middle of character. @@ -74,8 +73,9 @@ paintBlockCursor ? nextPositionOf(originalSelection.extent(), PositionMoveType::CodeUnit) : end; - selection.setWithoutValidation(start, endPosition); - return selection; + return SelectionInFlatTree::Builder() + .setBaseAndExtent(start, endPosition) + .build(); } const VisiblePositionInFlatTree& visibleStart = createVisiblePosition( @@ -83,27 +83,27 @@ ? TextAffinity::Downstream : affinity); if (visibleStart.isNull()) - return VisibleSelectionInFlatTree(); + return SelectionInFlatTree(); if (paintBlockCursor) { const VisiblePositionInFlatTree visibleExtent = nextPositionOf( createVisiblePosition(end, affinity), CanSkipOverEditingBoundary); if (visibleExtent.isNull()) - return VisibleSelectionInFlatTree(); + return SelectionInFlatTree(); SelectionInFlatTree::Builder builder; builder.collapse(visibleStart.toPositionWithAffinity()); builder.extend(visibleExtent.deepEquivalent()); - return createVisibleSelection(builder.build()); + return builder.build(); } const VisiblePositionInFlatTree visibleEnd = createVisiblePosition(end, selectionType == SelectionType::RangeSelection ? TextAffinity::Upstream : affinity); if (visibleEnd.isNull()) - return VisibleSelectionInFlatTree(); + return SelectionInFlatTree(); SelectionInFlatTree::Builder builder; builder.collapse(visibleStart.toPositionWithAffinity()); builder.extend(visibleEnd.deepEquivalent()); - return createVisibleSelection(builder.build()); + return builder.build(); } void PendingSelection::commit(LayoutView& layoutView) { @@ -124,7 +124,7 @@ // <https://bugs.webkit.org/show_bug.cgi?id=69563> and // <rdar://problem/10232866>. const VisibleSelectionInFlatTree& selection = - calcVisibleSelection(originalSelection); + createVisibleSelection(calcVisibleSelection(originalSelection)); if (!selection.isRange()) { layoutView.clearSelection();
diff --git a/third_party/WebKit/Source/core/editing/PendingSelection.h b/third_party/WebKit/Source/core/editing/PendingSelection.h index aec09a8..f1b7b624 100644 --- a/third_party/WebKit/Source/core/editing/PendingSelection.h +++ b/third_party/WebKit/Source/core/editing/PendingSelection.h
@@ -48,7 +48,7 @@ const VisibleSelection& visibleSelection() const; - VisibleSelectionInFlatTree calcVisibleSelection( + SelectionInFlatTree calcVisibleSelection( const VisibleSelectionInFlatTree&) const; Member<FrameSelection> m_frameSelection;
diff --git a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp index 8d897926..72c96efb 100644 --- a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp +++ b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
@@ -85,13 +85,9 @@ DCHECK(end.isNull()); return NoSelection; } + DCHECK(!needsLayoutTreeUpdate(start)) << start << ' ' << end; if (start == end) return CaretSelection; - // TODO(yosin) We should call |Document::updateStyleAndLayout()| here for - // |mostBackwardCaretPosition()|. However, we are here during - // |Node::removeChild()|. - start.anchorNode()->updateDistribution(); - end.anchorNode()->updateDistribution(); if (mostBackwardCaretPosition(start) == mostBackwardCaretPosition(end)) return CaretSelection; return RangeSelection;
diff --git a/third_party/WebKit/Source/core/editing/VisibleSelectionTest.cpp b/third_party/WebKit/Source/core/editing/VisibleSelectionTest.cpp index 549b61c..b7b0415 100644 --- a/third_party/WebKit/Source/core/editing/VisibleSelectionTest.cpp +++ b/third_party/WebKit/Source/core/editing/VisibleSelectionTest.cpp
@@ -209,8 +209,8 @@ EXPECT_TRUE(selectionInFlatTree.isCaret()); Range* range = firstRangeOf(selection); - EXPECT_EQ(0, range->startOffset()); - EXPECT_EQ(0, range->endOffset()); + EXPECT_EQ(0u, range->startOffset()); + EXPECT_EQ(0u, range->endOffset()); EXPECT_EQ("", range->text()); testFlatTreePositionsToEqualToDOMTreePositions(selection, selectionInFlatTree); @@ -351,8 +351,8 @@ expandUsingGranularity(selectionInFlatTree, WordGranularity); Range* range = firstRangeOf(selection); - EXPECT_EQ(0, range->startOffset()); - EXPECT_EQ(5, range->endOffset()); + EXPECT_EQ(0u, range->startOffset()); + EXPECT_EQ(5u, range->endOffset()); EXPECT_EQ("Lorem", range->text()); testFlatTreePositionsToEqualToDOMTreePositions(selection, selectionInFlatTree); @@ -367,8 +367,8 @@ expandUsingGranularity(selectionInFlatTree, WordGranularity); Range* range = firstRangeOf(selection); - EXPECT_EQ(6, range->startOffset()); - EXPECT_EQ(11, range->endOffset()); + EXPECT_EQ(6u, range->startOffset()); + EXPECT_EQ(11u, range->endOffset()); EXPECT_EQ("ipsum", range->text()); testFlatTreePositionsToEqualToDOMTreePositions(selection, selectionInFlatTree); @@ -385,8 +385,8 @@ expandUsingGranularity(selectionInFlatTree, WordGranularity); Range* range = firstRangeOf(selection); - EXPECT_EQ(5, range->startOffset()); - EXPECT_EQ(6, range->endOffset()); + EXPECT_EQ(5u, range->startOffset()); + EXPECT_EQ(6u, range->endOffset()); EXPECT_EQ(" ", range->text()); testFlatTreePositionsToEqualToDOMTreePositions(selection, selectionInFlatTree); @@ -403,8 +403,8 @@ expandUsingGranularity(selectionInFlatTree, WordGranularity); Range* range = firstRangeOf(selection); - EXPECT_EQ(26, range->startOffset()); - EXPECT_EQ(27, range->endOffset()); + EXPECT_EQ(26u, range->startOffset()); + EXPECT_EQ(27u, range->endOffset()); EXPECT_EQ(",", range->text()); testFlatTreePositionsToEqualToDOMTreePositions(selection, selectionInFlatTree); @@ -419,8 +419,8 @@ expandUsingGranularity(selectionInFlatTree, WordGranularity); Range* range = firstRangeOf(selection); - EXPECT_EQ(27, range->startOffset()); - EXPECT_EQ(28, range->endOffset()); + EXPECT_EQ(27u, range->startOffset()); + EXPECT_EQ(28u, range->endOffset()); EXPECT_EQ(" ", range->text()); testFlatTreePositionsToEqualToDOMTreePositions(selection, selectionInFlatTree); @@ -435,8 +435,8 @@ expandUsingGranularity(selectionInFlatTree, WordGranularity); Range* range = firstRangeOf(selection); - EXPECT_EQ(0, range->startOffset()); - EXPECT_EQ(5, range->endOffset()); + EXPECT_EQ(0u, range->startOffset()); + EXPECT_EQ(5u, range->endOffset()); EXPECT_EQ("Lorem", range->text()); testFlatTreePositionsToEqualToDOMTreePositions(selection, selectionInFlatTree); @@ -451,8 +451,8 @@ expandUsingGranularity(selectionInFlatTree, WordGranularity); Range* range = firstRangeOf(selection); - EXPECT_EQ(0, range->startOffset()); - EXPECT_EQ(11, range->endOffset()); + EXPECT_EQ(0u, range->startOffset()); + EXPECT_EQ(11u, range->endOffset()); EXPECT_EQ("Lorem ipsum", range->text()); testFlatTreePositionsToEqualToDOMTreePositions(selection, selectionInFlatTree);
diff --git a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommandTest.cpp b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommandTest.cpp index d9851af..6dfd318 100644 --- a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommandTest.cpp +++ b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommandTest.cpp
@@ -54,7 +54,9 @@ EXPECT_TRUE(command->apply()) << "the delete command should have succeeded"; EXPECT_EQ("<div contenteditable=\"true\"><br></div>", document().body()->innerHTML()); - EXPECT_TRUE(frame->selection().isCaret()); + EXPECT_TRUE(frame->selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .isCaret()); EXPECT_EQ(Position(div, 0), frame->selection().base().toOffsetInAnchor()); }
diff --git a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp index f82a155..f1c8290 100644 --- a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
@@ -415,7 +415,7 @@ static TriState selectionListState(const FrameSelection& selection, const QualifiedName& tagName) { - if (selection.isCaret()) { + if (selection.computeVisibleSelectionInDOMTreeDeprecated().isCaret()) { if (enclosingElementWithTag( selection.computeVisibleSelectionInDOMTreeDeprecated().start(), tagName)) @@ -1918,7 +1918,9 @@ frame.selection() .computeVisibleSelectionInDOMTreeDeprecated() .isContentRichlyEditable() && - frame.selection().rootEditableElement(); + frame.selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .rootEditableElement(); } static bool enabledPaste(LocalFrame& frame,
diff --git a/third_party/WebKit/Source/core/editing/commands/RemoveFormatCommand.cpp b/third_party/WebKit/Source/core/editing/commands/RemoveFormatCommand.cpp index 8132dae..f57bda07 100644 --- a/third_party/WebKit/Source/core/editing/commands/RemoveFormatCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/RemoveFormatCommand.cpp
@@ -65,7 +65,9 @@ // Get the default style for this editable root, it's the style that we'll // give the content that we're operating on. - Element* root = frame->selection().rootEditableElement(); + Element* root = frame->selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .rootEditableElement(); EditingStyle* defaultStyle = EditingStyle::create(root); // We want to remove everything but transparent background.
diff --git a/third_party/WebKit/Source/core/editing/iterators/CharacterIteratorTest.cpp b/third_party/WebKit/Source/core/editing/iterators/CharacterIteratorTest.cpp index a5e54ed9..ffba4aa 100644 --- a/third_party/WebKit/Source/core/editing/iterators/CharacterIteratorTest.cpp +++ b/third_party/WebKit/Source/core/editing/iterators/CharacterIteratorTest.cpp
@@ -61,8 +61,8 @@ Node* textNode = document().getElementById("div")->lastChild(); Range* entireRange = Range::create(document(), textNode, 1, textNode, 4); - EXPECT_EQ(1, entireRange->startOffset()); - EXPECT_EQ(4, entireRange->endOffset()); + EXPECT_EQ(1u, entireRange->startOffset()); + EXPECT_EQ(4u, entireRange->endOffset()); const EphemeralRange& result = calculateCharacterSubrange(EphemeralRange(entireRange), 2, 0);
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp index bd4b4a3..ed065a7 100644 --- a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp +++ b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp
@@ -640,11 +640,15 @@ int selectionOffset = 0; int ambiguousBoundaryOffset = -1; - if (frame().selection().isCaret()) { + if (frame() + .selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .isCaret()) { // TODO(xiaochengh): The following comment does not match the current // behavior and should be rewritten. // Attempt to save the caret position so we can restore it later if needed - const Position& caretPosition = frame().selection().end(); + const Position& caretPosition = + frame().selection().computeVisibleSelectionInDOMTreeDeprecated().end(); selectionOffset = paragraph.offsetTo(caretPosition); if (selectionOffset > 0 && static_cast<unsigned>(selectionOffset) <= paragraph.text().length() &&
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp index 824c132..4810ed8 100644 --- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp +++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
@@ -40,6 +40,7 @@ #include "core/dom/DocumentUserGestureToken.h" #include "core/dom/FrameRequestCallback.h" #include "core/dom/SandboxFlags.h" +#include "core/dom/SinkDocument.h" #include "core/dom/TaskRunnerHelper.h" #include "core/dom/custom/CustomElementRegistry.h" #include "core/editing/Editor.h" @@ -70,7 +71,6 @@ #include "core/inspector/InspectorTraceEvents.h" #include "core/loader/DocumentLoader.h" #include "core/loader/FrameLoaderClient.h" -#include "core/loader/SinkDocument.h" #include "core/loader/appcache/ApplicationCache.h" #include "core/page/ChromeClient.h" #include "core/page/CreateWindow.h"
diff --git a/third_party/WebKit/Source/core/frame/Location.cpp b/third_party/WebKit/Source/core/frame/Location.cpp index d030155..23ffea3f 100644 --- a/third_party/WebKit/Source/core/frame/Location.cpp +++ b/third_party/WebKit/Source/core/frame/Location.cpp
@@ -286,7 +286,7 @@ } bool Location::isAttached() const { - return m_domWindow->frame() && m_domWindow->frame()->host(); + return m_domWindow->frame(); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/Location.h b/third_party/WebKit/Source/core/frame/Location.h index 43a58ff..12fc280 100644 --- a/third_party/WebKit/Source/core/frame/Location.h +++ b/third_party/WebKit/Source/core/frame/Location.h
@@ -131,9 +131,7 @@ // LocalDOMWindow. Document* document() const; - // Returns true if: - // (1) the associated Window is the active Window in the frame - // (2) and the frame is attached. + // Returns true if the associated Window is the active Window in the frame. bool isAttached() const; enum class SetLocationPolicy { Normal, ReplaceThisFrame };
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h index f0e2f9e0..ef4fa20 100644 --- a/third_party/WebKit/Source/core/frame/UseCounter.h +++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -1476,6 +1476,7 @@ FetchResponseConstructionWithStream = 1826, LocationOrigin = 1827, DocumentOrigin = 1828, + SubtleCryptoOnlyStrictSecureContextCheckFailed = 1829, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/Source/core/input/EventHandlerTest.cpp b/third_party/WebKit/Source/core/input/EventHandlerTest.cpp index f2646b8..7055cd55 100644 --- a/third_party/WebKit/Source/core/input/EventHandlerTest.cpp +++ b/third_party/WebKit/Source/core/input/EventHandlerTest.cpp
@@ -153,7 +153,8 @@ TapEventBuilder singleTapEvent(IntPoint(0, 0), 1); document().frame()->eventHandler().handleGestureEvent(singleTapEvent); - ASSERT_TRUE(selection().isCaret()); + ASSERT_TRUE( + selection().computeVisibleSelectionInDOMTreeDeprecated().isCaret()); EXPECT_EQ(Position(line, 0), selection().start()); // Multi-tap events on editable elements should trigger selection, just @@ -163,10 +164,12 @@ ASSERT_TRUE(selection().isRange()); EXPECT_EQ(Position(line, 0), selection().start()); if (document().frame()->editor().isSelectTrailingWhitespaceEnabled()) { - EXPECT_EQ(Position(line, 4), selection().end()); + EXPECT_EQ(Position(line, 4), + selection().computeVisibleSelectionInDOMTreeDeprecated().end()); EXPECT_EQ("One ", WebString(selection().selectedText()).utf8()); } else { - EXPECT_EQ(Position(line, 3), selection().end()); + EXPECT_EQ(Position(line, 3), + selection().computeVisibleSelectionInDOMTreeDeprecated().end()); EXPECT_EQ("One", WebString(selection().selectedText()).utf8()); } @@ -174,7 +177,8 @@ document().frame()->eventHandler().handleGestureEvent(tripleTapEvent); ASSERT_TRUE(selection().isRange()); EXPECT_EQ(Position(line, 0), selection().start()); - EXPECT_EQ(Position(line, 13), selection().end()); + EXPECT_EQ(Position(line, 13), + selection().computeVisibleSelectionInDOMTreeDeprecated().end()); EXPECT_EQ("One Two Three", WebString(selection().selectedText()).utf8()); } @@ -188,18 +192,21 @@ TapEventBuilder singleTapEvent(IntPoint(0, 0), 1); document().frame()->eventHandler().handleGestureEvent(singleTapEvent); - ASSERT_TRUE(selection().isCaret()); + ASSERT_TRUE( + selection().computeVisibleSelectionInDOMTreeDeprecated().isCaret()); EXPECT_EQ(Position(line, 0), selection().start()); // As the text is readonly, multi-tap events should not trigger selection. TapEventBuilder doubleTapEvent(IntPoint(0, 0), 2); document().frame()->eventHandler().handleGestureEvent(doubleTapEvent); - ASSERT_TRUE(selection().isCaret()); + ASSERT_TRUE( + selection().computeVisibleSelectionInDOMTreeDeprecated().isCaret()); EXPECT_EQ(Position(line, 0), selection().start()); TapEventBuilder tripleTapEvent(IntPoint(0, 0), 3); document().frame()->eventHandler().handleGestureEvent(tripleTapEvent); - ASSERT_TRUE(selection().isCaret()); + ASSERT_TRUE( + selection().computeVisibleSelectionInDOMTreeDeprecated().isCaret()); EXPECT_EQ(Position(line, 0), selection().start()); } @@ -304,7 +311,8 @@ TapEventBuilder singleTapEvent(IntPoint(200, 200), 1); document().frame()->eventHandler().handleGestureEvent(singleTapEvent); - ASSERT_TRUE(selection().isCaret()); + ASSERT_TRUE( + selection().computeVisibleSelectionInDOMTreeDeprecated().isCaret()); ASSERT_FALSE(selection().isHandleVisible()); } @@ -314,7 +322,8 @@ TapEventBuilder singleTapEvent(IntPoint(200, 200), 1); document().frame()->eventHandler().handleGestureEvent(singleTapEvent); - ASSERT_TRUE(selection().isCaret()); + ASSERT_TRUE( + selection().computeVisibleSelectionInDOMTreeDeprecated().isCaret()); ASSERT_TRUE(selection().isHandleVisible()); } @@ -324,14 +333,16 @@ LongPressEventBuilder longPressEvent(IntPoint(200, 200)); document().frame()->eventHandler().handleGestureEvent(longPressEvent); - ASSERT_TRUE(selection().isCaret()); + ASSERT_TRUE( + selection().computeVisibleSelectionInDOMTreeDeprecated().isCaret()); ASSERT_TRUE(selection().isHandleVisible()); // Single Tap on an empty edit field should clear insertion handle TapEventBuilder singleTapEvent(IntPoint(200, 200), 1); document().frame()->eventHandler().handleGestureEvent(singleTapEvent); - ASSERT_TRUE(selection().isCaret()); + ASSERT_TRUE( + selection().computeVisibleSelectionInDOMTreeDeprecated().isCaret()); ASSERT_FALSE(selection().isHandleVisible()); } @@ -341,7 +352,8 @@ LongPressEventBuilder longPressEvent(IntPoint(200, 200)); document().frame()->eventHandler().handleGestureEvent(longPressEvent); - ASSERT_TRUE(selection().isCaret()); + ASSERT_TRUE( + selection().computeVisibleSelectionInDOMTreeDeprecated().isCaret()); ASSERT_TRUE(selection().isHandleVisible()); } @@ -352,7 +364,8 @@ LongPressEventBuilder longPressEvent(IntPoint(200, 200)); document().frame()->eventHandler().handleGestureEvent(longPressEvent); - ASSERT_TRUE(selection().isCaret()); + ASSERT_TRUE( + selection().computeVisibleSelectionInDOMTreeDeprecated().isCaret()); ASSERT_TRUE(selection().isHandleVisible()); // Tap away from text area should clear handle @@ -370,7 +383,8 @@ IntPoint(200, 200), 1, WebPointerProperties::Button::Left); document().frame()->eventHandler().handleMousePressEvent(leftMousePressEvent); - ASSERT_TRUE(selection().isCaret()); + ASSERT_TRUE( + selection().computeVisibleSelectionInDOMTreeDeprecated().isCaret()); ASSERT_FALSE(selection().isHandleVisible()); MousePressEventBuilder rightMousePressEvent( @@ -378,7 +392,8 @@ document().frame()->eventHandler().handleMousePressEvent( rightMousePressEvent); - ASSERT_TRUE(selection().isCaret()); + ASSERT_TRUE( + selection().computeVisibleSelectionInDOMTreeDeprecated().isCaret()); ASSERT_FALSE(selection().isHandleVisible()); MousePressEventBuilder doubleClickMousePressEvent(
diff --git a/third_party/WebKit/Source/core/loader/BUILD.gn b/third_party/WebKit/Source/core/loader/BUILD.gn index be6e6a63..e58fc416 100644 --- a/third_party/WebKit/Source/core/loader/BUILD.gn +++ b/third_party/WebKit/Source/core/loader/BUILD.gn
@@ -41,8 +41,6 @@ "PrerendererClient.cpp", "PrerendererClient.h", "ProgressTracker.cpp", - "SinkDocument.cpp", - "SinkDocument.h", "TextResourceDecoderBuilder.cpp", "TextResourceDecoderBuilder.h", "TextTrackLoader.cpp",
diff --git a/third_party/WebKit/Source/core/page/DragController.cpp b/third_party/WebKit/Source/core/page/DragController.cpp index 3ffdd07b..4622e1d 100644 --- a/third_party/WebKit/Source/core/page/DragController.cpp +++ b/third_party/WebKit/Source/core/page/DragController.cpp
@@ -572,7 +572,10 @@ return false; } Range* range = createRange(dragCaret.toNormalizedEphemeralRange()); - Element* rootEditableElement = innerFrame->selection().rootEditableElement(); + Element* rootEditableElement = + innerFrame->selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .rootEditableElement(); // For range to be null a WebKit client must have done something bad while // manually controlling drag behaviour @@ -1139,7 +1142,10 @@ } else if (state.m_dragType == DragSourceActionLink) { if (linkURL.isEmpty()) return false; - if (src->selection().isCaret() && src->selection().isContentEditable()) { + if (src->selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .isCaret() && + src->selection().isContentEditable()) { // a user can initiate a drag on a link without having any text // selected. In this case, we should expand the selection to // the enclosing anchor element
diff --git a/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.cpp b/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.cpp index 7c21c93..dd8655f5 100644 --- a/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.cpp
@@ -19,7 +19,8 @@ void WorkerLoaderProxy::detachProvider( WorkerLoaderProxyProvider* proxyProvider) { MutexLocker locker(m_lock); - DCHECK(proxyProvider == m_loaderProxyProvider); + DCHECK(isMainThread()); + DCHECK_EQ(proxyProvider, m_loaderProxyProvider); m_loaderProxyProvider = nullptr; } @@ -27,6 +28,7 @@ const WebTraceLocation& location, std::unique_ptr<ExecutionContextTask> task) { MutexLocker locker(m_lock); + DCHECK(!isMainThread()); if (!m_loaderProxyProvider) return; m_loaderProxyProvider->postTaskToLoader(location, std::move(task)); @@ -36,6 +38,7 @@ const WebTraceLocation& location, std::unique_ptr<WTF::CrossThreadClosure> task) { MutexLocker locker(m_lock); + DCHECK(isMainThread()); if (!m_loaderProxyProvider) return; m_loaderProxyProvider->postTaskToWorkerGlobalScope(location, std::move(task));
diff --git a/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.h b/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.h index 5951d8b..770719f 100644 --- a/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.h +++ b/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.h
@@ -62,11 +62,12 @@ virtual ~WorkerLoaderProxyProvider() {} // Posts a task to the thread which runs the loading code (normally, the main - // thread). + // thread). This must be called from a worker thread. virtual void postTaskToLoader(const WebTraceLocation&, std::unique_ptr<ExecutionContextTask>) = 0; - // Posts callbacks from loading code to the WorkerGlobalScope. + // Posts callbacks from loading code to the WorkerGlobalScope. This must be + // called from the main thread. virtual void postTaskToWorkerGlobalScope( const WebTraceLocation&, std::unique_ptr<WTF::CrossThreadClosure>) = 0; @@ -82,14 +83,17 @@ ~WorkerLoaderProxy(); + // This must be called from a worker thread. void postTaskToLoader(const WebTraceLocation&, std::unique_ptr<ExecutionContextTask>); + + // This must be called from the main thread. void postTaskToWorkerGlobalScope(const WebTraceLocation&, std::unique_ptr<WTF::CrossThreadClosure>); // Notification from the provider that it can no longer be accessed. An // implementation of WorkerLoaderProxyProvider is required to call - // detachProvider() when finalizing. + // detachProvider() when finalizing. This must be called from the main thread. void detachProvider(WorkerLoaderProxyProvider*); private:
diff --git a/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp b/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp index 5c3e3e3..9d8c75e5 100644 --- a/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp +++ b/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp
@@ -35,6 +35,7 @@ #include "core/dom/DOMArrayBufferView.h" #include "core/dom/DOMArrayPiece.h" #include "core/dom/ExecutionContext.h" +#include "core/frame/UseCounter.h" #include "modules/crypto/CryptoHistograms.h" #include "modules/crypto/CryptoKey.h" #include "modules/crypto/CryptoResultImpl.h" @@ -65,6 +66,12 @@ return false; } + if (!scriptState->getExecutionContext()->isSecureContext()) { + UseCounter::count( + scriptState->getExecutionContext(), + UseCounter::SubtleCryptoOnlyStrictSecureContextCheckFailed); + } + return true; }
diff --git a/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp b/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp index 9afab67..10b97ce 100644 --- a/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp +++ b/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp
@@ -25,9 +25,19 @@ namespace blink { +namespace { + +void rejectNavigatorDetached(ScriptPromiseResolver* resolver) { + DOMException* exception = DOMException::create( + InvalidStateError, "The object is no longer associated with a document."); + resolver->reject(exception); +} + +} // namespace + NavigatorVR* NavigatorVR::from(Document& document) { if (!document.frame() || !document.frame()->domWindow()) - return 0; + return nullptr; Navigator& navigator = *document.frame()->domWindow()->navigator(); return &from(navigator); } @@ -44,6 +54,13 @@ ScriptPromise NavigatorVR::getVRDisplays(ScriptState* scriptState, Navigator& navigator) { + if (!navigator.frame()) { + ScriptPromiseResolver* resolver = + ScriptPromiseResolver::create(scriptState); + ScriptPromise promise = resolver->promise(); + rejectNavigatorDetached(resolver); + return promise; + } return NavigatorVR::from(navigator).getVRDisplays(scriptState); } @@ -52,9 +69,7 @@ ScriptPromise promise = resolver->promise(); if (!document()) { - DOMException* exception = DOMException::create( - InvalidStateError, "The object is no longer associated to a document."); - resolver->reject(exception); + rejectNavigatorDetached(resolver); return promise; } @@ -73,7 +88,7 @@ VRController* NavigatorVR::controller() { if (!supplementable()->frame()) - return 0; + return nullptr; if (!m_controller) { m_controller = new VRController(this); @@ -85,8 +100,10 @@ } Document* NavigatorVR::document() { - return supplementable()->frame() ? supplementable()->frame()->document() - : nullptr; + if (!supplementable()->frame()) + return nullptr; + + return supplementable()->frame()->document(); } DEFINE_TRACE(NavigatorVR) { @@ -108,14 +125,16 @@ } void NavigatorVR::enqueueVREvent(VRDisplayEvent* event) { - if (supplementable()->frame()) { - supplementable()->frame()->domWindow()->enqueueWindowEvent(event); - } + if (!supplementable()->frame()) + return; + + supplementable()->frame()->domWindow()->enqueueWindowEvent(event); } void NavigatorVR::dispatchVRGestureEvent(VRDisplayEvent* event) { if (!(supplementable()->frame())) return; + UserGestureIndicator gestureIndicator( DocumentUserGestureToken::create(document())); LocalDOMWindow* window = supplementable()->frame()->domWindow(); @@ -161,10 +180,11 @@ } void NavigatorVR::didRemoveAllEventListeners(LocalDOMWindow* window) { - if (m_controller) { - m_controller->setListeningForActivate(false); - m_listeningForActivate = false; - } + if (!m_controller) + return; + + m_controller->setListeningForActivate(false); + m_listeningForActivate = false; } } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.cpp b/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.cpp index 04e14ae0..d7160669 100644 --- a/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.cpp
@@ -36,14 +36,10 @@ MediaStreamAudioSourceHandler::MediaStreamAudioSourceHandler( AudioNode& node, - MediaStream& mediaStream, - MediaStreamTrack* audioTrack, std::unique_ptr<AudioSourceProvider> audioSourceProvider) : AudioHandler(NodeTypeMediaStreamAudioSource, node, node.context()->sampleRate()), - m_mediaStream(mediaStream), - m_audioTrack(audioTrack), m_audioSourceProvider(std::move(audioSourceProvider)), m_sourceNumberOfChannels(0) { // Default to stereo. This could change depending on the format of the @@ -55,11 +51,9 @@ PassRefPtr<MediaStreamAudioSourceHandler> MediaStreamAudioSourceHandler::create( AudioNode& node, - MediaStream& mediaStream, - MediaStreamTrack* audioTrack, std::unique_ptr<AudioSourceProvider> audioSourceProvider) { - return adoptRef(new MediaStreamAudioSourceHandler( - node, mediaStream, audioTrack, std::move(audioSourceProvider))); + return adoptRef( + new MediaStreamAudioSourceHandler(node, std::move(audioSourceProvider))); } MediaStreamAudioSourceHandler::~MediaStreamAudioSourceHandler() { @@ -104,8 +98,7 @@ return; } - if (!getMediaStream() || - m_sourceNumberOfChannels != outputBus->numberOfChannels()) { + if (m_sourceNumberOfChannels != outputBus->numberOfChannels()) { outputBus->zero(); return; } @@ -129,9 +122,9 @@ MediaStream& mediaStream, MediaStreamTrack* audioTrack, std::unique_ptr<AudioSourceProvider> audioSourceProvider) - : AudioNode(context) { + : AudioNode(context), m_audioTrack(audioTrack), m_mediaStream(mediaStream) { setHandler(MediaStreamAudioSourceHandler::create( - *this, mediaStream, audioTrack, std::move(audioSourceProvider))); + *this, std::move(audioSourceProvider))); } MediaStreamAudioSourceNode* MediaStreamAudioSourceNode::create( @@ -180,6 +173,8 @@ } DEFINE_TRACE(MediaStreamAudioSourceNode) { + visitor->trace(m_audioTrack); + visitor->trace(m_mediaStream); AudioSourceProviderClient::trace(visitor); AudioNode::trace(visitor); } @@ -190,7 +185,7 @@ } MediaStream* MediaStreamAudioSourceNode::getMediaStream() const { - return mediaStreamAudioSourceHandler().getMediaStream(); + return m_mediaStream; } void MediaStreamAudioSourceNode::setFormat(size_t numberOfChannels,
diff --git a/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.h b/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.h index a771111..52e245c 100644 --- a/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.h +++ b/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.h
@@ -43,13 +43,9 @@ public: static PassRefPtr<MediaStreamAudioSourceHandler> create( AudioNode&, - MediaStream&, - MediaStreamTrack*, std::unique_ptr<AudioSourceProvider>); ~MediaStreamAudioSourceHandler() override; - MediaStream* getMediaStream() { return m_mediaStream.get(); } - // AudioHandler void process(size_t framesToProcess) override; @@ -57,22 +53,17 @@ // MediaStreamAudioSourceNode. void setFormat(size_t numberOfChannels, float sampleRate); + private: + MediaStreamAudioSourceHandler(AudioNode&, + std::unique_ptr<AudioSourceProvider>); + + // As an audio source, we will never propagate silence. + bool propagatesSilence() const override { return false; } + AudioSourceProvider* getAudioSourceProvider() const { return m_audioSourceProvider.get(); } - private: - MediaStreamAudioSourceHandler(AudioNode&, - MediaStream&, - MediaStreamTrack*, - std::unique_ptr<AudioSourceProvider>); - // As an audio source, we will never propagate silence. - bool propagatesSilence() const override { return false; } - - // These Persistents don't make reference cycles including the owner - // MediaStreamAudioSourceNode. - Persistent<MediaStream> m_mediaStream; - Persistent<MediaStreamTrack> m_audioTrack; std::unique_ptr<AudioSourceProvider> m_audioSourceProvider; Mutex m_processLock; @@ -95,7 +86,6 @@ ExceptionState&); DECLARE_VIRTUAL_TRACE(); - MediaStreamAudioSourceHandler& mediaStreamAudioSourceHandler() const; MediaStream* getMediaStream() const; @@ -107,6 +97,11 @@ MediaStream&, MediaStreamTrack*, std::unique_ptr<AudioSourceProvider>); + + MediaStreamAudioSourceHandler& mediaStreamAudioSourceHandler() const; + + Member<MediaStreamTrack> m_audioTrack; + Member<MediaStream> m_mediaStream; }; } // namespace blink
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp index dba0b1d5..925929f 100644 --- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp +++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
@@ -558,7 +558,7 @@ DocumentLifecycle::DisallowTransitionScope disallowTransition( localFrame->document()->lifecycle()); - if (selection.isCaret()) { + if (selection.computeVisibleSelectionInDOMTreeDeprecated().isCaret()) { anchor = focus = selection.absoluteCaretBounds(); } else { const EphemeralRange selectedRange = @@ -604,7 +604,10 @@ return false; start = toWebTextDirection(primaryDirectionOf(*selection.start().anchorNode())); - end = toWebTextDirection(primaryDirectionOf(*selection.end().anchorNode())); + end = toWebTextDirection( + primaryDirectionOf(*selection.computeVisibleSelectionInDOMTreeDeprecated() + .end() + .anchorNode())); return true; }
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp index de2132e..89d55678 100644 --- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp +++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -1086,7 +1086,11 @@ return pluginContainer->plugin()->hasSelection(); // frame()->selection()->isNone() never returns true. - return frame()->selection().start() != frame()->selection().end(); + return frame()->selection().start() != + frame() + ->selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .end(); } WebRange WebLocalFrameImpl::selectionRange() const {
diff --git a/third_party/WebKit/Source/web/WebRange.cpp b/third_party/WebKit/Source/web/WebRange.cpp index e3194e3..803d842 100644 --- a/third_party/WebKit/Source/web/WebRange.cpp +++ b/third_party/WebKit/Source/web/WebRange.cpp
@@ -61,7 +61,9 @@ } EphemeralRange WebRange::createEphemeralRange(LocalFrame* frame) const { - Element* selectionRoot = frame->selection().rootEditableElement(); + Element* selectionRoot = frame->selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .rootEditableElement(); ContainerNode* scope = selectionRoot ? selectionRoot : frame->document()->documentElement();
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp index 155c10e..a203cd2 100644 --- a/third_party/WebKit/Source/web/WebViewImpl.cpp +++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -2367,7 +2367,7 @@ DocumentLifecycle::DisallowTransitionScope disallowTransition( localFrame->document()->lifecycle()); - if (selection.isCaret()) { + if (selection.computeVisibleSelectionInDOMTreeDeprecated().isCaret()) { anchor = focus = selection.absoluteCaretBounds(); } else { const EphemeralRange selectedRange = @@ -2423,7 +2423,10 @@ return false; start = toWebTextDirection(primaryDirectionOf(*selection.start().anchorNode())); - end = toWebTextDirection(primaryDirectionOf(*selection.end().anchorNode())); + end = toWebTextDirection( + primaryDirectionOf(*selection.computeVisibleSelectionInDOMTreeDeprecated() + .end() + .anchorNode())); return true; }
diff --git a/third_party/WebKit/Source/web/tests/TextFinderTest.cpp b/third_party/WebKit/Source/web/tests/TextFinderTest.cpp index 76f22e4..6f23217 100644 --- a/third_party/WebKit/Source/web/tests/TextFinderTest.cpp +++ b/third_party/WebKit/Source/web/tests/TextFinderTest.cpp
@@ -85,9 +85,9 @@ Range* activeMatch = textFinder().activeMatch(); ASSERT_TRUE(activeMatch); EXPECT_EQ(textNode, activeMatch->startContainer()); - EXPECT_EQ(4, activeMatch->startOffset()); + EXPECT_EQ(4u, activeMatch->startOffset()); EXPECT_EQ(textNode, activeMatch->endContainer()); - EXPECT_EQ(10, activeMatch->endOffset()); + EXPECT_EQ(10u, activeMatch->endOffset()); findOptions.findNext = true; ASSERT_TRUE( @@ -95,9 +95,9 @@ activeMatch = textFinder().activeMatch(); ASSERT_TRUE(activeMatch); EXPECT_EQ(textNode, activeMatch->startContainer()); - EXPECT_EQ(14, activeMatch->startOffset()); + EXPECT_EQ(14u, activeMatch->startOffset()); EXPECT_EQ(textNode, activeMatch->endContainer()); - EXPECT_EQ(20, activeMatch->endOffset()); + EXPECT_EQ(20u, activeMatch->endOffset()); // Should wrap to the first match. ASSERT_TRUE( @@ -105,9 +105,9 @@ activeMatch = textFinder().activeMatch(); ASSERT_TRUE(activeMatch); EXPECT_EQ(textNode, activeMatch->startContainer()); - EXPECT_EQ(4, activeMatch->startOffset()); + EXPECT_EQ(4u, activeMatch->startOffset()); EXPECT_EQ(textNode, activeMatch->endContainer()); - EXPECT_EQ(10, activeMatch->endOffset()); + EXPECT_EQ(10u, activeMatch->endOffset()); // Search in the reverse order. identifier = 1; @@ -119,9 +119,9 @@ activeMatch = textFinder().activeMatch(); ASSERT_TRUE(activeMatch); EXPECT_EQ(textNode, activeMatch->startContainer()); - EXPECT_EQ(14, activeMatch->startOffset()); + EXPECT_EQ(14u, activeMatch->startOffset()); EXPECT_EQ(textNode, activeMatch->endContainer()); - EXPECT_EQ(20, activeMatch->endOffset()); + EXPECT_EQ(20u, activeMatch->endOffset()); findOptions.findNext = true; ASSERT_TRUE( @@ -129,9 +129,9 @@ activeMatch = textFinder().activeMatch(); ASSERT_TRUE(activeMatch); EXPECT_EQ(textNode, activeMatch->startContainer()); - EXPECT_EQ(4, activeMatch->startOffset()); + EXPECT_EQ(4u, activeMatch->startOffset()); EXPECT_EQ(textNode, activeMatch->endContainer()); - EXPECT_EQ(10, activeMatch->endOffset()); + EXPECT_EQ(10u, activeMatch->endOffset()); // Wrap to the first match (last occurence in the document). ASSERT_TRUE( @@ -139,9 +139,9 @@ activeMatch = textFinder().activeMatch(); ASSERT_TRUE(activeMatch); EXPECT_EQ(textNode, activeMatch->startContainer()); - EXPECT_EQ(14, activeMatch->startOffset()); + EXPECT_EQ(14u, activeMatch->startOffset()); EXPECT_EQ(textNode, activeMatch->endContainer()); - EXPECT_EQ(20, activeMatch->endOffset()); + EXPECT_EQ(20u, activeMatch->endOffset()); } TEST_F(TextFinderTest, FindTextAutosizing) { @@ -220,9 +220,9 @@ Range* activeMatch = textFinder().activeMatch(); ASSERT_TRUE(activeMatch); EXPECT_EQ(textInIElement, activeMatch->startContainer()); - EXPECT_EQ(0, activeMatch->startOffset()); + EXPECT_EQ(0u, activeMatch->startOffset()); EXPECT_EQ(textInIElement, activeMatch->endContainer()); - EXPECT_EQ(3, activeMatch->endOffset()); + EXPECT_EQ(3u, activeMatch->endOffset()); findOptions.findNext = true; ASSERT_TRUE( @@ -230,18 +230,18 @@ activeMatch = textFinder().activeMatch(); ASSERT_TRUE(activeMatch); EXPECT_EQ(textInUElement, activeMatch->startContainer()); - EXPECT_EQ(0, activeMatch->startOffset()); + EXPECT_EQ(0u, activeMatch->startOffset()); EXPECT_EQ(textInUElement, activeMatch->endContainer()); - EXPECT_EQ(3, activeMatch->endOffset()); + EXPECT_EQ(3u, activeMatch->endOffset()); ASSERT_TRUE( textFinder().find(identifier, searchText, findOptions, wrapWithinFrame)); activeMatch = textFinder().activeMatch(); ASSERT_TRUE(activeMatch); EXPECT_EQ(textInBElement, activeMatch->startContainer()); - EXPECT_EQ(0, activeMatch->startOffset()); + EXPECT_EQ(0u, activeMatch->startOffset()); EXPECT_EQ(textInBElement, activeMatch->endContainer()); - EXPECT_EQ(3, activeMatch->endOffset()); + EXPECT_EQ(3u, activeMatch->endOffset()); // Should wrap to the first match. ASSERT_TRUE( @@ -249,9 +249,9 @@ activeMatch = textFinder().activeMatch(); ASSERT_TRUE(activeMatch); EXPECT_EQ(textInIElement, activeMatch->startContainer()); - EXPECT_EQ(0, activeMatch->startOffset()); + EXPECT_EQ(0u, activeMatch->startOffset()); EXPECT_EQ(textInIElement, activeMatch->endContainer()); - EXPECT_EQ(3, activeMatch->endOffset()); + EXPECT_EQ(3u, activeMatch->endOffset()); // Fresh search in the reverse order. identifier = 1; @@ -263,9 +263,9 @@ activeMatch = textFinder().activeMatch(); ASSERT_TRUE(activeMatch); EXPECT_EQ(textInBElement, activeMatch->startContainer()); - EXPECT_EQ(0, activeMatch->startOffset()); + EXPECT_EQ(0u, activeMatch->startOffset()); EXPECT_EQ(textInBElement, activeMatch->endContainer()); - EXPECT_EQ(3, activeMatch->endOffset()); + EXPECT_EQ(3u, activeMatch->endOffset()); findOptions.findNext = true; ASSERT_TRUE( @@ -273,18 +273,18 @@ activeMatch = textFinder().activeMatch(); ASSERT_TRUE(activeMatch); EXPECT_EQ(textInUElement, activeMatch->startContainer()); - EXPECT_EQ(0, activeMatch->startOffset()); + EXPECT_EQ(0u, activeMatch->startOffset()); EXPECT_EQ(textInUElement, activeMatch->endContainer()); - EXPECT_EQ(3, activeMatch->endOffset()); + EXPECT_EQ(3u, activeMatch->endOffset()); ASSERT_TRUE( textFinder().find(identifier, searchText, findOptions, wrapWithinFrame)); activeMatch = textFinder().activeMatch(); ASSERT_TRUE(activeMatch); EXPECT_EQ(textInIElement, activeMatch->startContainer()); - EXPECT_EQ(0, activeMatch->startOffset()); + EXPECT_EQ(0u, activeMatch->startOffset()); EXPECT_EQ(textInIElement, activeMatch->endContainer()); - EXPECT_EQ(3, activeMatch->endOffset()); + EXPECT_EQ(3u, activeMatch->endOffset()); // And wrap. ASSERT_TRUE( @@ -292,9 +292,9 @@ activeMatch = textFinder().activeMatch(); ASSERT_TRUE(activeMatch); EXPECT_EQ(textInBElement, activeMatch->startContainer()); - EXPECT_EQ(0, activeMatch->startOffset()); + EXPECT_EQ(0u, activeMatch->startOffset()); EXPECT_EQ(textInBElement, activeMatch->endContainer()); - EXPECT_EQ(3, activeMatch->endOffset()); + EXPECT_EQ(3u, activeMatch->endOffset()); } TEST_F(TextFinderTest, ScopeTextMatchesSimple) { @@ -485,8 +485,8 @@ Range* activeMatch = textFinder().activeMatch(); ASSERT_TRUE(activeMatch); EXPECT_FALSE(activeNow); - EXPECT_EQ(2, activeMatch->startOffset()); - EXPECT_EQ(8, activeMatch->endOffset()); + EXPECT_EQ(2u, activeMatch->startOffset()); + EXPECT_EQ(8u, activeMatch->endOffset()); // Restart full search and check that added text is found. findOptions.findNext = false; @@ -539,8 +539,8 @@ Range* activeMatch = textFinder().activeMatch(); ASSERT_TRUE(activeMatch); EXPECT_FALSE(activeNow); - EXPECT_EQ(2, activeMatch->startOffset()); - EXPECT_EQ(8, activeMatch->endOffset()); + EXPECT_EQ(2u, activeMatch->startOffset()); + EXPECT_EQ(8u, activeMatch->endOffset()); // Restart full search and check that added text is found. findOptions.findNext = false;
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp index ad05184..5cf3d88 100644 --- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp +++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -5452,9 +5452,18 @@ EXPECT_EQ("Length", selectionAsString(frame)); webViewHelper.webView()->selectionBounds(startWebRect, endWebRect); - EXPECT_EQ(0, frame->frame()->selection().rootEditableElement()->scrollLeft()); + EXPECT_EQ(0, frame->frame() + ->selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .rootEditableElement() + ->scrollLeft()); frame->moveRangeSelectionExtent(WebPoint(endWebRect.x + 500, endWebRect.y)); - EXPECT_GE(frame->frame()->selection().rootEditableElement()->scrollLeft(), 1); + EXPECT_GE(frame->frame() + ->selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .rootEditableElement() + ->scrollLeft(), + 1); EXPECT_EQ("Lengthy text goes here.", selectionAsString(frame)); } @@ -5473,8 +5482,11 @@ initializeTextSelectionWebView(m_baseURL + "select_range_span_editable.html", &webViewHelper); WebLocalFrameImpl* mainFrame = webViewHelper.webView()->mainFrameImpl(); - LayoutObject* layoutObject = - mainFrame->frame()->selection().rootEditableElement()->layoutObject(); + LayoutObject* layoutObject = mainFrame->frame() + ->selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .rootEditableElement() + ->layoutObject(); EXPECT_EQ(0, computeOffset(layoutObject, -1, -1)); EXPECT_EQ(64, computeOffset(layoutObject, 1000, 1000)); @@ -5482,8 +5494,11 @@ initializeTextSelectionWebView(m_baseURL + "select_range_div_editable.html", &webViewHelper); mainFrame = webViewHelper.webView()->mainFrameImpl(); - layoutObject = - mainFrame->frame()->selection().rootEditableElement()->layoutObject(); + layoutObject = mainFrame->frame() + ->selection() + .computeVisibleSelectionInDOMTreeDeprecated() + .rootEditableElement() + ->layoutObject(); EXPECT_EQ(0, computeOffset(layoutObject, -1, -1)); EXPECT_EQ(64, computeOffset(layoutObject, 1000, 1000)); }
diff --git a/tools/idl_parser/idl_lexer.py b/tools/idl_parser/idl_lexer.py index 1f186d72..a5fc49c3 100755 --- a/tools/idl_parser/idl_lexer.py +++ b/tools/idl_parser/idl_lexer.py
@@ -17,20 +17,10 @@ import os.path import sys -# -# Try to load the ply module, if not, then assume it is in the third_party -# directory. -# -try: - # Disable lint check which fails to find the ply module. - # pylint: disable=F0401 - from ply import lex -except ImportError: - module_path, module_name = os.path.split(__file__) - third_party = os.path.join(module_path, '..', '..', 'third_party') - sys.path.append(third_party) - # pylint: disable=F0401 - from ply import lex +SRC_DIR = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir) +sys.path.insert(0, os.path.join(SRC_DIR, 'third_party')) +from ply import lex + # # IDL Lexer
diff --git a/tools/idl_parser/idl_parser.py b/tools/idl_parser/idl_parser.py index b1e74c7..d7a00aa 100755 --- a/tools/idl_parser/idl_parser.py +++ b/tools/idl_parser/idl_parser.py
@@ -36,22 +36,11 @@ from idl_lexer import IDLLexer from idl_node import IDLAttribute, IDLNode -# -# Try to load the ply module, if not, then assume it is in the third_party -# directory. -# -try: - # Disable lint check which fails to find the ply module. - # pylint: disable=F0401 - from ply import lex - from ply import yacc -except ImportError: - module_path, module_name = os.path.split(__file__) - third_party = os.path.join(module_path, os.par, os.par, 'third_party') - sys.path.append(third_party) - # pylint: disable=F0401 - from ply import lex - from ply import yacc +SRC_DIR = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir) +sys.path.insert(0, os.path.join(SRC_DIR, 'third_party')) +from ply import lex +from ply import yacc + # # ERROR_REMAP
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 242b9f62..48e0bb9b 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -91450,6 +91450,7 @@ <int value="1826" label="FetchResponseConstructionWithStream"/> <int value="1827" label="LocationOrigin"/> <int value="1828" label="DocumentOrigin"/> + <int value="1829" label="SubtleCryptoOnlyStrictSecureContextCheckFailed"/> </enum> <enum name="FetchRequestMode" type="int">