blob: 4e20acf894c5d2c058784c5777d195a3d5ffa6e9 [file] [log] [blame]
/*
* Copyright (C) 2008, 2009, 2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "third_party/blink/renderer/bindings/core/v8/remote_window_proxy.h"
#include <algorithm>
#include <utility>
#include "third_party/blink/renderer/bindings/core/v8/v8_window.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "v8/include/v8.h"
namespace blink {
RemoteWindowProxy::RemoteWindowProxy(v8::Isolate* isolate,
RemoteFrame& frame,
scoped_refptr<DOMWrapperWorld> world)
: WindowProxy(isolate, frame, std::move(world)) {}
void RemoteWindowProxy::DisposeContext(Lifecycle next_status,
FrameReuseStatus) {
DCHECK(next_status == Lifecycle::kForciblyPurgeV8Memory ||
next_status == Lifecycle::kGlobalObjectIsDetached ||
next_status == Lifecycle::kFrameIsDetached);
// If the current lifecycle is kForciblyPurgeV8Memory, the next state should
// be kGlobalObjectIsDetached. The necessary operations are already done in
// kForciblyPurgeMemory and thus can return here.
if (lifecycle_ == Lifecycle::kForciblyPurgeV8Memory) {
DCHECK(next_status == Lifecycle::kGlobalObjectIsDetached);
lifecycle_ = next_status;
return;
}
if (lifecycle_ != Lifecycle::kContextIsInitialized)
return;
if ((next_status == Lifecycle::kForciblyPurgeV8Memory ||
next_status == Lifecycle::kGlobalObjectIsDetached) &&
!global_proxy_.IsEmpty()) {
global_proxy_.Get().SetWrapperClassId(0);
V8DOMWrapper::ClearNativeInfo(GetIsolate(),
global_proxy_.NewLocal(GetIsolate()));
#if DCHECK_IS_ON()
DidDetachGlobalObject();
#endif
}
if (next_status == Lifecycle::kFrameIsDetached) {
// The context's frame is detached from the DOM, so there shouldn't be a
// strong reference to the context.
global_proxy_.SetPhantom();
}
DCHECK_EQ(lifecycle_, Lifecycle::kContextIsInitialized);
lifecycle_ = next_status;
}
void RemoteWindowProxy::Initialize() {
TRACE_EVENT1("v8", "RemoteWindowProxy::initialize", "isMainWindow",
GetFrame()->IsMainFrame());
SCOPED_BLINK_UMA_HISTOGRAM_TIMER(
GetFrame()->IsMainFrame()
? "Blink.Binding.InitializeMainRemoteWindowProxy"
: "Blink.Binding.InitializeNonMainRemoteWindowProxy");
ScriptForbiddenScope::AllowUserAgentScript allow_script;
v8::HandleScope handle_scope(GetIsolate());
CreateContext();
SetupWindowPrototypeChain();
}
void RemoteWindowProxy::CreateContext() {
// Create a new v8::Context with the window object as the global object
// (aka the inner global). Reuse the outer global proxy if it already exists.
v8::Local<v8::ObjectTemplate> global_template =
V8Window::DomTemplate(GetIsolate(), *world_)->InstanceTemplate();
CHECK(!global_template.IsEmpty());
v8::Local<v8::Object> global_proxy =
v8::Context::NewRemoteContext(GetIsolate(), global_template,
global_proxy_.NewLocal(GetIsolate()))
.ToLocalChecked();
if (global_proxy_.IsEmpty())
global_proxy_.Set(GetIsolate(), global_proxy);
else
DCHECK(global_proxy_.Get() == global_proxy);
CHECK(!global_proxy_.IsEmpty());
#if DCHECK_IS_ON()
DidAttachGlobalObject();
#endif
DCHECK(lifecycle_ == Lifecycle::kContextIsUninitialized ||
lifecycle_ == Lifecycle::kGlobalObjectIsDetached);
lifecycle_ = Lifecycle::kContextIsInitialized;
}
void RemoteWindowProxy::SetupWindowPrototypeChain() {
// Associate the window wrapper object and its prototype chain with the
// corresponding native DOMWindow object.
DOMWindow* window = GetFrame()->DomWindow();
const WrapperTypeInfo* wrapper_type_info = window->GetWrapperTypeInfo();
// The global proxy object. Note this is not the global object.
v8::Local<v8::Object> global_proxy = global_proxy_.NewLocal(GetIsolate());
V8DOMWrapper::SetNativeInfo(GetIsolate(), global_proxy, wrapper_type_info,
window);
// Mark the handle to be traced by Oilpan, since the global proxy has a
// reference to the DOMWindow.
global_proxy_.Get().SetWrapperClassId(wrapper_type_info->wrapper_class_id);
// The global object, aka window wrapper object.
v8::Local<v8::Object> window_wrapper =
global_proxy->GetPrototype().As<v8::Object>();
v8::Local<v8::Object> associated_wrapper =
AssociateWithWrapper(window, wrapper_type_info, window_wrapper);
DCHECK(associated_wrapper == window_wrapper);
}
} // namespace blink