blob: a3426face606def89b09f448fb749c2494592cf3 [file] [log] [blame]
// Copyright 2022 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/web/window_or_worker_global_scope.h"
#include <utility>
#include "base/bind.h"
#include "cobalt/script/environment_settings.h"
#include "cobalt/web/csp_delegate_factory.h"
#include "cobalt/web/error_event.h"
#include "cobalt/web/error_event_init.h"
#include "cobalt/web/event_target.h"
namespace cobalt {
namespace dom {
class Window;
} // namespace dom
namespace worker {
class DedicatedWorkerGlobalScope;
class ServiceWorkerGlobalScope;
} // namespace worker
namespace web {
WindowOrWorkerGlobalScope::WindowOrWorkerGlobalScope(
script::EnvironmentSettings* settings, const Options& options)
// Global scope object EventTargets require special handling for onerror
// events, see EventTarget constructor for more details.
: EventTarget(settings, kUnpackOnErrorEvents),
options_(options),
caches_(new CacheStorage()),
crypto_(new Crypto()),
window_timers_(this, options.stat_tracker, debugger_hooks(),
options.initial_state),
preflight_cache_(new loader::CORSPreflightCache()) {
csp_delegate_ = CspDelegateFactory::Create(
this, options.csp_options,
base::Bind(&WindowOrWorkerGlobalScope::OnCspPolicyChanged,
base::Unretained(this)));
environment_settings()
->context()
->global_environment()
->SetReportEvalCallback(base::Bind(&web::CspDelegate::ReportEval,
base::Unretained(csp_delegate())));
environment_settings()
->context()
->global_environment()
->SetReportErrorCallback(
base::Bind(&WindowOrWorkerGlobalScope::ReportScriptError,
base::Unretained(this)));
}
WindowOrWorkerGlobalScope::~WindowOrWorkerGlobalScope() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
bool WindowOrWorkerGlobalScope::IsWindow() {
return GetWrappableType() == base::GetTypeId<dom::Window>();
}
bool WindowOrWorkerGlobalScope::IsWorker() {
return IsDedicatedWorker() || IsServiceWorker();
}
bool WindowOrWorkerGlobalScope::IsDedicatedWorker() {
return GetWrappableType() ==
base::GetTypeId<worker::DedicatedWorkerGlobalScope>();
}
bool WindowOrWorkerGlobalScope::IsServiceWorker() {
return GetWrappableType() ==
base::GetTypeId<worker::ServiceWorkerGlobalScope>();
}
void WindowOrWorkerGlobalScope::OnCspPolicyChanged() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(csp_delegate());
DCHECK(environment_settings()->context()->global_environment());
std::string eval_disabled_message;
bool allow_eval = csp_delegate()->AllowEval(&eval_disabled_message);
if (allow_eval) {
environment_settings()->context()->global_environment()->EnableEval();
} else {
environment_settings()->context()->global_environment()->DisableEval(
eval_disabled_message);
}
}
int WindowOrWorkerGlobalScope::SetTimeout(
const WindowTimers::TimerCallbackArg& handler, int timeout) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return window_timers_.SetTimeout(handler, timeout);
}
void WindowOrWorkerGlobalScope::ClearTimeout(int handle) {
window_timers_.ClearTimeout(handle);
}
int WindowOrWorkerGlobalScope::SetInterval(
const WindowTimers::TimerCallbackArg& handler, int timeout) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return window_timers_.SetInterval(handler, timeout);
}
void WindowOrWorkerGlobalScope::ClearInterval(int handle) {
window_timers_.ClearInterval(handle);
}
void WindowOrWorkerGlobalScope::DestroyTimers() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
window_timers_.DisableCallbacks();
}
scoped_refptr<CacheStorage> WindowOrWorkerGlobalScope::caches() const {
return caches_;
}
scoped_refptr<Crypto> WindowOrWorkerGlobalScope::crypto() const {
return crypto_;
}
bool WindowOrWorkerGlobalScope::ReportScriptError(
const script::ErrorReport& error_report) {
// Runtime script errors: when the user agent is required to report an error
// for a particular script, it must run these steps, after which the error is
// either handled or not handled:
// https://www.w3.org/TR/html50/webappapis.html#runtime-script-errors
// 1. If target is in error reporting mode, then abort these steps; the error
// is not handled.
if (is_reporting_script_error_) {
return false;
}
// 2. Let target be in error reporting mode.
is_reporting_script_error_ = true;
// 7. Let event be a new trusted ErrorEvent object that does not bubble but is
// cancelable, and which has the event name error.
// NOTE: Cobalt does not currently support trusted events.
web::ErrorEventInit error;
error.set_bubbles(false);
error.set_cancelable(true);
if (error_report.is_muted) {
// 6. If script has muted errors, then set message to "Script error.", set
// location to the empty string, set line and col to 0, and set error
// object to null.
error.set_message("Script error.");
error.set_filename("");
error.set_lineno(0);
error.set_colno(0);
error.set_error(NULL);
} else {
// 8. Initialize event's message attribute to message.
error.set_message(error_report.message);
// 9. Initialize event's filename attribute to location.
error.set_filename(error_report.filename);
// 10. Initialize event's lineno attribute to line.
error.set_lineno(error_report.line_number);
// 11. Initialize event's colno attribute to col.
error.set_colno(error_report.column_number);
// 12. Initialize event's error attribute to error object.
error.set_error(error_report.error ? error_report.error.get() : NULL);
}
scoped_refptr<web::ErrorEvent> error_event(
new web::ErrorEvent(environment_settings(), error));
// 13. Dispatch event at target.
DispatchEvent(error_event);
// 14. Let target no longer be in error reporting mode.
is_reporting_script_error_ = false;
// 15. If event was canceled, then the error is handled. Otherwise, the error
// is not handled.
return error_event->default_prevented();
}
} // namespace web
} // namespace cobalt