Commit 6c688717 authored by Katie Dillon's avatar Katie Dillon Committed by Commit Bot

Exposing navigator.language to web workers.

navigator.language should be supported in workers according to
specifications.

This CL adds a virtual function for retrieving the accept_language
to navigator_language which is then overridden by navigator, who gets
the languages from the frame, and woker_navigator, who gets the languages
from renderer preferences. From there, navigator_language parses the
string and returns either the top prefered language or a vector of all
of the preferred languages.

In addition, any changes to the language fires an event that notifies all
of the worker threads to the change, as per specification.

Based on this CL: https://chromium-review.googlesource.com/c/chromium/src/+/1136794

Bug: 276159, 655458
Change-Id: I53bd454f10b5b9b9dc8fd3afa82415b6e93698ca
Reviewed-on: https://chromium-review.googlesource.com/c/1255151
Commit-Queue: Ojan Vafai <ojan@chromium.org>
Reviewed-by: default avatarOjan Vafai <ojan@chromium.org>
Reviewed-by: default avatarTsuyoshi Horo <horo@chromium.org>
Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#613381}
parent f08835e6
......@@ -230,7 +230,8 @@ WebWorkerFetchContextImpl::CloneForNestedWorker() {
return new_context;
}
void WebWorkerFetchContextImpl::InitializeOnWorkerThread() {
void WebWorkerFetchContextImpl::InitializeOnWorkerThread(
blink::AcceptLanguagesWatcher* watcher) {
DCHECK(!resource_dispatcher_);
DCHECK(!binding_.is_bound());
DCHECK(!preference_watcher_binding_.is_bound());
......@@ -262,6 +263,7 @@ void WebWorkerFetchContextImpl::InitializeOnWorkerThread() {
base::RefCountedData<blink::mojom::BlobRegistryPtr>>(
std::move(blob_registry_ptr));
}
accept_languages_watcher_ = watcher;
DCHECK(loader_factory_);
DCHECK(!web_loader_factory_);
......@@ -465,6 +467,9 @@ void WebWorkerFetchContextImpl::ResetServiceWorkerURLLoaderFactory() {
void WebWorkerFetchContextImpl::NotifyUpdate(
const RendererPreferences& new_prefs) {
if (accept_languages_watcher_ &&
renderer_preferences_.accept_languages != new_prefs.accept_languages)
accept_languages_watcher_->NotifyUpdate();
renderer_preferences_ = new_prefs;
child_preference_watchers_.ForAllPtrs(
[&new_prefs](mojom::RendererPreferenceWatcher* watcher) {
......@@ -472,4 +477,8 @@ void WebWorkerFetchContextImpl::NotifyUpdate(
});
}
blink::WebString WebWorkerFetchContextImpl::GetAcceptLanguages() const {
return blink::WebString::FromUTF8(renderer_preferences_.accept_languages);
}
} // namespace content
......@@ -22,6 +22,7 @@
#include "third_party/blink/public/mojom/blob/blob_registry.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/platform/web_application_cache_host.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_worker_fetch_context.h"
#include "url/gurl.h"
......@@ -84,7 +85,7 @@ class CONTENT_EXPORT WebWorkerFetchContextImpl
// blink::WebWorkerFetchContext implementation:
scoped_refptr<blink::WebWorkerFetchContext> CloneForNestedWorker() override;
void SetTerminateSyncLoadEvent(base::WaitableEvent*) override;
void InitializeOnWorkerThread() override;
void InitializeOnWorkerThread(blink::AcceptLanguagesWatcher*) override;
blink::WebURLLoaderFactory* GetURLLoaderFactory() override;
std::unique_ptr<blink::WebURLLoaderFactory> WrapURLLoaderFactory(
mojo::ScopedMessagePipeHandle url_loader_factory_handle) override;
......@@ -131,6 +132,8 @@ class CONTENT_EXPORT WebWorkerFetchContextImpl
using RewriteURLFunction = blink::WebURL (*)(const std::string&, bool);
static void InstallRewriteURLFunction(RewriteURLFunction rewrite_url);
blink::WebString GetAcceptLanguages() const override;
private:
class Factory;
......@@ -239,6 +242,8 @@ class CONTENT_EXPORT WebWorkerFetchContextImpl
websocket_handshake_throttle_provider_;
std::unique_ptr<service_manager::Connector> service_manager_connection_;
blink::AcceptLanguagesWatcher* accept_languages_watcher_ = nullptr;
};
} // namespace content
......
......@@ -49,7 +49,8 @@ void ServiceWorkerFetchContextImpl::SetTerminateSyncLoadEvent(
terminate_sync_load_event_ = terminate_sync_load_event;
}
void ServiceWorkerFetchContextImpl::InitializeOnWorkerThread() {
void ServiceWorkerFetchContextImpl::InitializeOnWorkerThread(
blink::AcceptLanguagesWatcher* watcher) {
resource_dispatcher_ = std::make_unique<ResourceDispatcher>();
resource_dispatcher_->set_terminate_sync_load_event(
terminate_sync_load_event_);
......@@ -67,6 +68,8 @@ void ServiceWorkerFetchContextImpl::InitializeOnWorkerThread() {
network::SharedURLLoaderFactory::Create(
std::move(script_loader_factory_info_)));
}
accept_languages_watcher_ = watcher;
}
blink::WebURLLoaderFactory*
......@@ -135,7 +138,14 @@ ServiceWorkerFetchContextImpl::CreateWebSocketHandshakeThrottle() {
void ServiceWorkerFetchContextImpl::NotifyUpdate(
const RendererPreferences& new_prefs) {
DCHECK(accept_languages_watcher_);
if (renderer_preferences_.accept_languages != new_prefs.accept_languages)
accept_languages_watcher_->NotifyUpdate();
renderer_preferences_ = new_prefs;
}
blink::WebString ServiceWorkerFetchContextImpl::GetAcceptLanguages() const {
return blink::WebString::FromUTF8(renderer_preferences_.accept_languages);
}
} // namespace content
......@@ -43,7 +43,7 @@ class ServiceWorkerFetchContextImpl final
// blink::WebWorkerFetchContext implementation:
void SetTerminateSyncLoadEvent(base::WaitableEvent*) override;
void InitializeOnWorkerThread() override;
void InitializeOnWorkerThread(blink::AcceptLanguagesWatcher*) override;
blink::WebURLLoaderFactory* GetURLLoaderFactory() override;
std::unique_ptr<blink::WebURLLoaderFactory> WrapURLLoaderFactory(
mojo::ScopedMessagePipeHandle url_loader_factory_handle) override;
......@@ -54,6 +54,7 @@ class ServiceWorkerFetchContextImpl final
blink::WebURL SiteForCookies() const override;
std::unique_ptr<blink::WebSocketHandshakeThrottle>
CreateWebSocketHandshakeThrottle() override;
blink::WebString GetAcceptLanguages() const override;
private:
~ServiceWorkerFetchContextImpl() override;
......@@ -90,6 +91,8 @@ class ServiceWorkerFetchContextImpl final
// This is owned by ThreadedMessagingProxyBase on the main thread.
base::WaitableEvent* terminate_sync_load_event_ = nullptr;
blink::AcceptLanguagesWatcher* accept_languages_watcher_ = nullptr;
};
} // namespace content
......
......@@ -14,6 +14,7 @@
#include "third_party/blink/public/platform/web_application_cache_host.h"
#include "third_party/blink/public/platform/web_document_subresource_filter.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_loader_factory.h"
#include "third_party/blink/public/platform/websocket_handshake_throttle.h"
......@@ -27,6 +28,13 @@ namespace blink {
class WebURLRequest;
class WebDocumentSubresourceFilter;
// Helper class allowing WebWorkerFetchContextImpl to notify blink upon an
// accept languages update. This class will be extended by WorkerNavigator.
class AcceptLanguagesWatcher {
public:
virtual void NotifyUpdate() = 0;
};
// WebWorkerFetchContext is a per-worker object created on the main thread,
// passed to a worker (dedicated, shared and service worker) and initialized on
// the worker thread by InitializeOnWorkerThread(). It contains information
......@@ -58,7 +66,7 @@ class WebWorkerFetchContext : public base::RefCounted<WebWorkerFetchContext> {
// pointer is valid throughout the lifetime of this context.
virtual void SetTerminateSyncLoadEvent(base::WaitableEvent*) = 0;
virtual void InitializeOnWorkerThread() = 0;
virtual void InitializeOnWorkerThread(AcceptLanguagesWatcher*) = 0;
// Returns a WebURLLoaderFactory which is associated with the worker context.
// The returned WebURLLoaderFactory is owned by |this|.
......@@ -133,6 +141,9 @@ class WebWorkerFetchContext : public base::RefCounted<WebWorkerFetchContext> {
CreateWebSocketHandshakeThrottle() {
return nullptr;
}
// Returns the current list of user prefered languages.
virtual blink::WebString GetAcceptLanguages() const = 0;
};
} // namespace blink
......
......@@ -282,7 +282,7 @@ void LocalDOMWindow::ClearDocument() {
void LocalDOMWindow::AcceptLanguagesChanged() {
if (navigator_)
navigator_->SetLanguagesChanged();
navigator_->SetLanguagesDirty();
DispatchEvent(*Event::Create(event_type_names::kLanguagechange));
}
......
......@@ -32,13 +32,13 @@
#include "third_party/blink/renderer/core/loader/frame_loader.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/platform/language.h"
#include "third_party/blink/renderer/platform/memory_coordinator.h"
namespace blink {
Navigator::Navigator(LocalFrame* frame) : DOMWindowClient(frame) {}
Navigator::Navigator(LocalFrame* frame)
: NavigatorLanguage(frame->GetDocument()), DOMWindowClient(frame) {}
String Navigator::productSub() const {
return "20030107";
......@@ -83,38 +83,21 @@ bool Navigator::cookieEnabled() const {
return CookiesEnabled(GetFrame()->GetDocument());
}
Vector<String> Navigator::languages() {
languages_changed_ = false;
String Navigator::GetAcceptLanguages() {
String accept_languages;
if (GetFrame() && GetFrame()->GetPage()) {
accept_languages =
GetFrame()->GetPage()->GetChromeClient().AcceptLanguages();
} else {
accept_languages = DefaultLanguage();
}
probe::applyAcceptLanguageOverride(GetFrame(), &accept_languages);
Vector<String> languages;
accept_languages.Split(',', languages);
// Sanitizing tokens. We could do that more extensively but we should assume
// that the accept languages are already sane and support BCP47. It is
// likely a waste of time to make sure the tokens matches that spec here.
for (wtf_size_t i = 0; i < languages.size(); ++i) {
String& token = languages[i];
token = token.StripWhiteSpace();
if (token.length() >= 3 && token[2] == '_')
token.replace(2, 1, "-");
}
if (languages.IsEmpty())
languages.push_back(DefaultLanguage());
return languages;
return accept_languages;
}
void Navigator::Trace(blink::Visitor* visitor) {
ScriptWrappable::Trace(visitor);
NavigatorLanguage::Trace(visitor);
DOMWindowClient::Trace(visitor);
Supplementable<Navigator>::Trace(visitor);
}
......
......@@ -66,8 +66,7 @@ class CORE_EXPORT Navigator final : public ScriptWrappable,
String platform() const override;
String userAgent() const override;
// NavigatorLanguage
Vector<String> languages() override;
String GetAcceptLanguages() override;
void Trace(blink::Visitor*) override;
};
......
......@@ -4,22 +4,65 @@
#include "third_party/blink/renderer/core/frame/navigator_language.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/platform/language.h"
namespace blink {
NavigatorLanguage::NavigatorLanguage() = default;
Vector<String> ParseAndSanitize(const String& accept_languages) {
Vector<String> languages;
accept_languages.Split(',', languages);
// Sanitizing tokens. We could do that more extensively but we should assume
// that the accept languages are already sane and support BCP47. It is
// likely a waste of time to make sure the tokens matches that spec here.
for (size_t i = 0; i < languages.size(); ++i) {
String& token = languages[i];
token = token.StripWhiteSpace();
if (token.length() >= 3 && token[2] == '_')
token.replace(2, 1, "-");
}
if (languages.IsEmpty())
languages.push_back(DefaultLanguage());
return languages;
}
NavigatorLanguage::NavigatorLanguage(ExecutionContext* context)
: context_(context) {}
AtomicString NavigatorLanguage::language() {
return AtomicString(languages().front());
}
bool NavigatorLanguage::hasLanguagesChanged() const {
return languages_changed_;
const Vector<String>& NavigatorLanguage::languages() {
if (languages_dirty_) {
String accept_languages_override;
probe::applyAcceptLanguageOverride(context_, &accept_languages_override);
if (!accept_languages_override.IsNull()) {
languages_ = ParseAndSanitize(accept_languages_override);
} else {
languages_ = ParseAndSanitize(GetAcceptLanguages());
}
languages_dirty_ = false;
}
return languages_;
}
bool NavigatorLanguage::IsLanguagesDirty() const {
return languages_dirty_;
}
void NavigatorLanguage::SetLanguagesDirty() {
languages_dirty_ = true;
languages_.clear();
}
void NavigatorLanguage::SetLanguagesChanged() {
languages_changed_ = true;
void NavigatorLanguage::Trace(blink::Visitor* visitor) {
visitor->Trace(context_);
}
} // namespace blink
......@@ -6,21 +6,29 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_NAVIGATOR_LANGUAGE_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
namespace blink {
class CORE_EXPORT NavigatorLanguage {
class CORE_EXPORT NavigatorLanguage : public GarbageCollectedMixin {
public:
NavigatorLanguage();
explicit NavigatorLanguage(ExecutionContext*);
AtomicString language();
virtual Vector<String> languages() = 0;
bool hasLanguagesChanged() const;
void SetLanguagesChanged();
const Vector<String>& languages();
bool IsLanguagesDirty() const;
void SetLanguagesDirty();
void Trace(blink::Visitor*) override;
protected:
bool languages_changed_ = true;
bool languages_dirty_ = true;
WeakMember<ExecutionContext> context_;
virtual String GetAcceptLanguages() = 0;
private:
Vector<String> languages_;
};
} // namespace blink
......
......@@ -9,5 +9,5 @@
Exposed=(Window,Worker)
] interface NavigatorLanguage {
readonly attribute DOMString language;
[CachedAttribute=hasLanguagesChanged] readonly attribute FrozenArray<DOMString> languages;
[CachedAttribute=IsLanguagesDirty] readonly attribute FrozenArray<DOMString> languages;
};
......@@ -110,7 +110,7 @@ void WorkerInspectorController::AttachSession(DevToolsSession* session,
session->Append(MakeGarbageCollected<InspectorLogAgent>(
thread_->GetConsoleMessageStorage(), nullptr, session->V8Session()));
if (auto* scope = DynamicTo<WorkerGlobalScope>(thread_->GlobalScope())) {
DCHECK(scope->EnsureFetcher());
scope->EnsureFetcher();
session->Append(MakeGarbageCollected<InspectorNetworkAgent>(
inspected_frames_.Get(), scope, session->V8Session()));
session->Append(MakeGarbageCollected<InspectorEmulationAgent>(nullptr));
......
......@@ -87,7 +87,7 @@ interface CoreProbes {
void didFireWebGLErrorOrWarning(Element*, const String& message);
void didResizeMainFrame(LocalFrame*);
void didPaint(LocalFrame*, const GraphicsLayer*, GraphicsContext&, const LayoutRect&);
void applyAcceptLanguageOverride(LocalFrame*, String* acceptLanguage);
void applyAcceptLanguageOverride(ExecutionContext*, String* acceptLanguage);
void applyUserAgentOverride(ExecutionContext*, String* userAgent);
void didBlockRequest([Keep] ExecutionContext*, const ResourceRequest&, DocumentLoader*, const FetchInitiatorInfo&, ResourceRequestBlockedReason, ResourceType);
void didChangeResourcePriority(LocalFrame*, DocumentLoader*, unsigned long identifier, ResourceLoadPriority loadPriority);
......
......@@ -123,7 +123,7 @@ WorkerLocation* WorkerGlobalScope::location() const {
WorkerNavigator* WorkerGlobalScope::navigator() const {
if (!navigator_)
navigator_ = WorkerNavigator::Create(user_agent_);
navigator_ = WorkerNavigator::Create(user_agent_, GetExecutionContext());
return navigator_.Get();
}
......
......@@ -93,7 +93,7 @@ class CORE_EXPORT WorkerGlobalScope
// WorkerGlobalScope
WorkerGlobalScope* self() { return this; }
WorkerLocation* location() const;
WorkerNavigator* navigator() const;
WorkerNavigator* navigator() const override;
void close();
bool isSecureContextForBindings() const {
return ExecutionContext::IsSecureContext();
......@@ -102,6 +102,7 @@ class CORE_EXPORT WorkerGlobalScope
String origin() const;
DEFINE_ATTRIBUTE_EVENT_LISTENER(error, kError);
DEFINE_ATTRIBUTE_EVENT_LISTENER(languagechange, kLanguagechange);
DEFINE_ATTRIBUTE_EVENT_LISTENER(rejectionhandled, kRejectionhandled);
DEFINE_ATTRIBUTE_EVENT_LISTENER(unhandledrejection, kUnhandledrejection);
......
......@@ -36,7 +36,7 @@
// TODO(foolip): onerror should be an OnErrorEventHandler.
attribute EventHandler onerror;
// attribute EventHandler onlanguagechange;
attribute EventHandler onlanguagechange;
// attribute EventHandler onoffline;
// attribute EventHandler ononline;
......
......@@ -25,11 +25,20 @@
*/
#include "third_party/blink/renderer/core/workers/worker_navigator.h"
#include "third_party/blink/public/platform/web_worker_fetch_context.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/loader/worker_fetch_context.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
namespace blink {
WorkerNavigator::WorkerNavigator(const String& user_agent)
: user_agent_(user_agent) {}
WorkerNavigator::WorkerNavigator(const String& user_agent,
ExecutionContext* context)
: NavigatorLanguage(context), user_agent_(user_agent) {}
WorkerNavigator::~WorkerNavigator() = default;
......@@ -37,8 +46,27 @@ String WorkerNavigator::userAgent() const {
return user_agent_;
}
String WorkerNavigator::GetAcceptLanguages() {
WorkerOrWorkletGlobalScope* global_scope =
To<WorkerOrWorkletGlobalScope>(context_.Get());
WebWorkerFetchContext* worker_fetch_context =
static_cast<WorkerFetchContext*>(
(&global_scope->EnsureFetcher()->Context()))
->GetWebWorkerFetchContext();
return worker_fetch_context->GetAcceptLanguages();
}
void WorkerNavigator::NotifyUpdate() {
SetLanguagesDirty();
WorkerOrWorkletGlobalScope* global_scope =
To<WorkerOrWorkletGlobalScope>(context_.Get());
global_scope->DispatchEvent(
*Event::Create(event_type_names::kLanguagechange));
}
void WorkerNavigator::Trace(blink::Visitor* visitor) {
ScriptWrappable::Trace(visitor);
NavigatorLanguage::Trace(visitor);
Supplementable<WorkerNavigator>::Trace(visitor);
}
......
......@@ -26,10 +26,13 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_NAVIGATOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_NAVIGATOR_H_
#include "third_party/blink/public/platform/web_worker_fetch_context.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/navigator_concurrent_hardware.h"
#include "third_party/blink/renderer/core/frame/navigator_device_memory.h"
#include "third_party/blink/renderer/core/frame/navigator_id.h"
#include "third_party/blink/renderer/core/frame/navigator_language.h"
#include "third_party/blink/renderer/core/frame/navigator_on_line.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
......@@ -40,24 +43,34 @@ namespace blink {
class CORE_EXPORT WorkerNavigator final
: public ScriptWrappable,
public AcceptLanguagesWatcher,
public NavigatorConcurrentHardware,
public NavigatorDeviceMemory,
public NavigatorID,
public NavigatorLanguage,
public NavigatorOnLine,
public Supplementable<WorkerNavigator> {
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(WorkerNavigator);
public:
static WorkerNavigator* Create(const String& user_agent) {
return MakeGarbageCollected<WorkerNavigator>(user_agent);
static WorkerNavigator* Create(const String& user_agent,
ExecutionContext* context) {
return MakeGarbageCollected<WorkerNavigator>(user_agent, context);
}
explicit WorkerNavigator(const String&);
explicit WorkerNavigator(const String&, ExecutionContext* context);
~WorkerNavigator() override;
// NavigatorID override
String userAgent() const override;
// NavigatorLanguage override
String GetAcceptLanguages() override;
// AcceptLanguagesWatcher override
void NotifyUpdate() override;
void Trace(blink::Visitor*) override;
private:
......
......@@ -36,5 +36,5 @@
WorkerNavigator implements NavigatorConcurrentHardware;
WorkerNavigator implements NavigatorDeviceMemory;
WorkerNavigator implements NavigatorID;
// TODO(foolip): WorkerNavigator implements NavigatorLanguage;
WorkerNavigator implements NavigatorLanguage;
WorkerNavigator implements NavigatorOnLine;
......@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/loader/worker_fetch_context.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
......@@ -108,7 +109,7 @@ void WorkerOrWorkletGlobalScope::InitializeWebFetchContextIfNeeded() {
return;
DCHECK(!subresource_filter_);
web_worker_fetch_context_->InitializeOnWorkerThread();
web_worker_fetch_context_->InitializeOnWorkerThread(navigator());
std::unique_ptr<blink::WebDocumentSubresourceFilter> web_filter =
web_worker_fetch_context_->TakeSubresourceFilter();
if (web_filter) {
......
......@@ -17,6 +17,7 @@
#include "third_party/blink/renderer/core/frame/web_feature_forward.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/workers/worker_clients.h"
#include "third_party/blink/renderer/core/workers/worker_navigator.h"
#include "third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/bit_vector.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
......@@ -91,6 +92,9 @@ class CORE_EXPORT WorkerOrWorkletGlobalScope : public EventTargetWithInlineData,
// WorkletGlobalScope for the main thread) or after Dispose() is called.
virtual WorkerThread* GetThread() const = 0;
// Returns nullptr if this global scope is a WorkletGlobalScope
virtual WorkerNavigator* navigator() const { return nullptr; }
ResourceFetcher* Fetcher() const override;
ResourceFetcher* EnsureFetcher();
......
......@@ -41,6 +41,7 @@
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h"
#include "third_party/blink/renderer/core/workers/worker_backing_thread_startup_data.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
......
......@@ -4160,6 +4160,8 @@ crbug.com/655458 virtual/omt-worker-fetch/external/wpt/workers/constructors/Shar
crbug.com/655458 virtual/omt-worker-fetch/external/wpt/workers/constructors/SharedWorker/unresolvable-url.html [ Failure ]
crbug.com/655458 virtual/omt-worker-fetch/external/wpt/workers/semantics/multiple-workers/007.html [ Timeout ]
crbug.com/910709 navigator_language/worker_navigator_language.html [ Timeout ]
# Off-the-main-thread classic worker script fetch.
# This fails because running a worker on an opaque origin is blocked.
crbug.com/835717 virtual/omt-worker-fetch/external/wpt/workers/opaque-origin.html [ Timeout ]
......
This is a testharness.js-based test.
Found 161 tests; 151 PASS, 10 FAIL, 0 TIMEOUT, 0 NOTRUN.
Found 161 tests; 157 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN.
PASS EventTarget interface: existence and properties of interface object
PASS EventTarget interface object length
PASS EventTarget interface object name
......@@ -21,7 +21,7 @@ PASS WorkerGlobalScope interface: attribute location
PASS WorkerGlobalScope interface: attribute navigator
PASS WorkerGlobalScope interface: operation importScripts(USVString)
PASS WorkerGlobalScope interface: attribute onerror
FAIL WorkerGlobalScope interface: attribute onlanguagechange assert_true: The prototype object must have a property "onlanguagechange" expected true got false
PASS WorkerGlobalScope interface: attribute onlanguagechange
FAIL WorkerGlobalScope interface: attribute onoffline assert_true: The prototype object must have a property "onoffline" expected true got false
FAIL WorkerGlobalScope interface: attribute ononline assert_true: The prototype object must have a property "ononline" expected true got false
PASS WorkerGlobalScope interface: attribute onrejectionhandled
......@@ -72,7 +72,7 @@ PASS WorkerGlobalScope interface: self must inherit property "navigator" with th
PASS WorkerGlobalScope interface: self must inherit property "importScripts(USVString)" with the proper type
PASS WorkerGlobalScope interface: calling importScripts(USVString) on self with too few arguments must throw TypeError
PASS WorkerGlobalScope interface: self must inherit property "onerror" with the proper type
FAIL WorkerGlobalScope interface: self must inherit property "onlanguagechange" with the proper type assert_inherits: property "onlanguagechange" not found in prototype chain
PASS WorkerGlobalScope interface: self must inherit property "onlanguagechange" with the proper type
FAIL WorkerGlobalScope interface: self must inherit property "onoffline" with the proper type assert_inherits: property "onoffline" not found in prototype chain
FAIL WorkerGlobalScope interface: self must inherit property "ononline" with the proper type assert_inherits: property "ononline" not found in prototype chain
PASS WorkerGlobalScope interface: self must inherit property "onrejectionhandled" with the proper type
......@@ -115,8 +115,8 @@ PASS WorkerNavigator interface: member productSub
PASS WorkerNavigator interface: attribute userAgent
PASS WorkerNavigator interface: member vendor
PASS WorkerNavigator interface: member vendorSub
FAIL WorkerNavigator interface: attribute language assert_true: The prototype object must have a property "language" expected true got false
FAIL WorkerNavigator interface: attribute languages assert_true: The prototype object must have a property "languages" expected true got false
PASS WorkerNavigator interface: attribute language
PASS WorkerNavigator interface: attribute languages
PASS WorkerNavigator interface: attribute onLine
PASS WorkerNavigator interface: attribute hardwareConcurrency
PASS WorkerNavigator must be primary interface of self.navigator
......@@ -130,8 +130,8 @@ PASS WorkerNavigator interface: self.navigator must not have property "productSu
PASS WorkerNavigator interface: self.navigator must inherit property "userAgent" with the proper type
PASS WorkerNavigator interface: self.navigator must not have property "vendor"
PASS WorkerNavigator interface: self.navigator must not have property "vendorSub"
FAIL WorkerNavigator interface: self.navigator must inherit property "language" with the proper type assert_inherits: property "language" not found in prototype chain
FAIL WorkerNavigator interface: self.navigator must inherit property "languages" with the proper type assert_inherits: property "languages" not found in prototype chain
PASS WorkerNavigator interface: self.navigator must inherit property "language" with the proper type
PASS WorkerNavigator interface: self.navigator must inherit property "languages" with the proper type
PASS WorkerNavigator interface: self.navigator must inherit property "onLine" with the proper type
PASS WorkerNavigator interface: self.navigator must inherit property "hardwareConcurrency" with the proper type
PASS WorkerLocation interface: existence and properties of interface object
......
......@@ -2,6 +2,7 @@ Tests emulation of the user agent.
navigator.userAgent == Test UA
User-Agent: Test UA
navigator.language == ko
workerNavigator.language == ko
Accept-Language: ko, en;q=0.9, zh-CN;q=0.8, zh-HK;q=0.7, en-US;q=0.6, en-GB;q=0.5
accept-language: ko
navigator.platform == new_platform
......
......@@ -9,6 +9,18 @@
// Accept Language
await dp.Emulation.setUserAgentOverride({userAgent: '', acceptLanguage: 'ko, en, zh-CN, zh-HK, en-US, en-GB'});
testRunner.log('navigator.language == ' + await session.evaluate('navigator.language'));
// Worker Accept Language
await dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false});
await session.evaluate(`var w = new Worker('${testRunner.url('resources/worker.js')}')`);
let event = await dp.Target.onceAttachedToTarget();
const worker = new WorkerProtocol(dp, event.params.sessionId);
await worker.dp.Emulation.setUserAgentOverride({userAgent: '', acceptLanguage: 'ko, en, zh-CN, zh-HK, en-US, en-GB'});
testRunner.log('workerNavigator.language == ' + await session.evaluateAsync(`
w.postMessage('ping!');
new Promise(resolve => w.onmessage = e => resolve(e.data.language))`));
await dp.Target.onceDetachedFromTarget();
await printHeader('Accept-Language');
// Do not override explicit Accept-Language header.
......
onmessage = function(e) {
postMessage({'language': navigator.language});
close();
};
......@@ -3446,6 +3446,7 @@ interface WorkerGlobalScope : EventTarget
getter location
getter navigator
getter onerror
getter onlanguagechange
getter onrejectionhandled
getter onunhandledrejection
getter origin
......@@ -3465,6 +3466,7 @@ interface WorkerGlobalScope : EventTarget
method setInterval
method setTimeout
setter onerror
setter onlanguagechange
setter onrejectionhandled
setter onunhandledrejection
setter origin
......@@ -3490,6 +3492,8 @@ interface WorkerNavigator
getter connection
getter deviceMemory
getter hardwareConcurrency
getter language
getter languages
getter locks
getter onLine
getter permissions
......
onmessage = function(evt)
{
postMessage(navigator.language);
}
onlanguagechange = function(evt)
{
postMessage('language event fired');
}
<!DOCTYPE html>
<html>
<body>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script>
async_test(function() {
var worker = new Worker("resources/worker_language.js");
worker.onmessage = this.step_func_done(function(e) {
assert_equals(e.data, 'klingon');
});
testRunner.setAcceptLanguages('klingon');
worker.postMessage("langauge changed");
done();
}, "Test changing the language on worker threads.");
async_test(function() {
var worker = new Worker("resources/worker_language_event.js");
worker.onmessage = this.step_func_done(function(e) {
assert_equals(e.data, 'language event fired');
});
testRunner.setAcceptLanguages('fr-FR');
done();
}, "Test the language change event fires on worker threads.");
async_test(function() {
var worker = new Worker("resources/worker_language.js");
var previous = navigator.languages
worker.onmessage = this.step_func_done(function(e) {
assert_equals(e.data, previous);
});
worker.postMessage("same language");
worker.onmessage = this.step_func_done(function(e) {
assert_not_equals(e.data, previous);
});
testRunner.setAcceptLanguages('fr-FR');
worker.postMessage("different language");
done();
}, "Test caching behavior on worker threads");
</script>
</body>
</html>
......@@ -2447,6 +2447,7 @@ interface WorkerGlobalScope : EventTarget
getter location
getter navigator
getter onerror
getter onlanguagechange
getter onrejectionhandled
getter onunhandledrejection
getter origin
......@@ -2466,6 +2467,7 @@ interface WorkerGlobalScope : EventTarget
method setInterval
method setTimeout
setter onerror
setter onlanguagechange
setter onrejectionhandled
setter onunhandledrejection
setter origin
......@@ -2491,6 +2493,8 @@ interface WorkerNavigator
getter connection
getter deviceMemory
getter hardwareConcurrency
getter language
getter languages
getter locks
getter onLine
getter permissions
......
......@@ -2491,6 +2491,7 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] getter location
[Worker] getter navigator
[Worker] getter onerror
[Worker] getter onlanguagechange
[Worker] getter onrejectionhandled
[Worker] getter onunhandledrejection
[Worker] getter origin
......@@ -2510,6 +2511,7 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] method setInterval
[Worker] method setTimeout
[Worker] setter onerror
[Worker] setter onlanguagechange
[Worker] setter onrejectionhandled
[Worker] setter onunhandledrejection
[Worker] setter origin
......@@ -2535,6 +2537,8 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] getter connection
[Worker] getter deviceMemory
[Worker] getter hardwareConcurrency
[Worker] getter language
[Worker] getter languages
[Worker] getter locks
[Worker] getter onLine
[Worker] getter permissions
......
......@@ -2378,6 +2378,7 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] getter location
[Worker] getter navigator
[Worker] getter onerror
[Worker] getter onlanguagechange
[Worker] getter onrejectionhandled
[Worker] getter onunhandledrejection
[Worker] getter origin
......@@ -2397,6 +2398,7 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] method setInterval
[Worker] method setTimeout
[Worker] setter onerror
[Worker] setter onlanguagechange
[Worker] setter onrejectionhandled
[Worker] setter onunhandledrejection
[Worker] setter origin
......@@ -2422,6 +2424,8 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] getter connection
[Worker] getter deviceMemory
[Worker] getter hardwareConcurrency
[Worker] getter language
[Worker] getter languages
[Worker] getter locks
[Worker] getter onLine
[Worker] getter permissions
......
......@@ -3476,6 +3476,7 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] getter location
[Worker] getter navigator
[Worker] getter onerror
[Worker] getter onlanguagechange
[Worker] getter onrejectionhandled
[Worker] getter onunhandledrejection
[Worker] getter origin
......@@ -3495,6 +3496,7 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] method setInterval
[Worker] method setTimeout
[Worker] setter onerror
[Worker] setter onlanguagechange
[Worker] setter onrejectionhandled
[Worker] setter onunhandledrejection
[Worker] setter origin
......@@ -3520,6 +3522,8 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] getter connection
[Worker] getter deviceMemory
[Worker] getter hardwareConcurrency
[Worker] getter language
[Worker] getter languages
[Worker] getter locks
[Worker] getter onLine
[Worker] getter permissions
......
......@@ -3348,6 +3348,7 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] getter location
[Worker] getter navigator
[Worker] getter onerror
[Worker] getter onlanguagechange
[Worker] getter onrejectionhandled
[Worker] getter onunhandledrejection
[Worker] getter origin
......@@ -3367,6 +3368,7 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] method setInterval
[Worker] method setTimeout
[Worker] setter onerror
[Worker] setter onlanguagechange
[Worker] setter onrejectionhandled
[Worker] setter onunhandledrejection
[Worker] setter origin
......@@ -3392,6 +3394,8 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] getter connection
[Worker] getter deviceMemory
[Worker] getter hardwareConcurrency
[Worker] getter language
[Worker] getter languages
[Worker] getter locks
[Worker] getter onLine
[Worker] getter permissions
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment