blob: a6da9c494a44c2c1b190fece06258cd81729f62e [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
dsinclair64376be2016-03-31 20:03:24 -07007#include "fpdfsdk/javascript/cjs_runtime.h"
Tom Sepez37458412015-10-06 11:33:46 -07008
tsepez41a53ad2016-03-28 16:59:30 -07009#include <algorithm>
10
dsinclair735606d2016-10-05 15:47:02 -070011#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
tonikitoo618cb1f2016-08-18 20:10:17 -070012#include "fpdfsdk/javascript/Annot.h"
Dan Sinclairf766ad22016-03-14 13:51:24 -040013#include "fpdfsdk/javascript/Consts.h"
14#include "fpdfsdk/javascript/Document.h"
15#include "fpdfsdk/javascript/Field.h"
16#include "fpdfsdk/javascript/Icon.h"
Dan Sinclairf766ad22016-03-14 13:51:24 -040017#include "fpdfsdk/javascript/JS_Define.h"
18#include "fpdfsdk/javascript/JS_EventHandler.h"
19#include "fpdfsdk/javascript/JS_GlobalData.h"
20#include "fpdfsdk/javascript/JS_Object.h"
21#include "fpdfsdk/javascript/JS_Value.h"
22#include "fpdfsdk/javascript/PublicMethods.h"
23#include "fpdfsdk/javascript/app.h"
Tom Sepezd6ae2af2017-02-16 11:49:55 -080024#include "fpdfsdk/javascript/cjs_event_context.h"
Dan Sinclairf766ad22016-03-14 13:51:24 -040025#include "fpdfsdk/javascript/color.h"
26#include "fpdfsdk/javascript/console.h"
27#include "fpdfsdk/javascript/event.h"
28#include "fpdfsdk/javascript/global.h"
29#include "fpdfsdk/javascript/report.h"
30#include "fpdfsdk/javascript/util.h"
dsinclairf34518b2016-09-13 12:03:48 -070031#include "public/fpdf_formfill.h"
Lei Zhangcd2bb302015-12-22 13:49:44 -080032#include "third_party/base/stl_util.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070033
Tom Sepez40e9ff32015-11-30 12:39:54 -080034#ifdef PDF_ENABLE_XFA
dsinclair43554682016-09-29 17:29:48 -070035#include "fxjs/cfxjse_value.h"
Tom Sepez40e9ff32015-11-30 12:39:54 -080036#endif // PDF_ENABLE_XFA
37
Tom Sepez67fd5df2015-10-08 12:24:19 -070038// static
Tom Sepez452b4f32015-10-13 09:27:27 -070039void IJS_Runtime::Initialize(unsigned int slot, void* isolate) {
40 FXJS_Initialize(slot, reinterpret_cast<v8::Isolate*>(isolate));
41}
42
43// static
thestig2d6dda12016-06-28 07:39:09 -070044void IJS_Runtime::Destroy() {
45 FXJS_Release();
46}
47
48// static
dsinclair82e17672016-10-11 12:38:01 -070049IJS_Runtime* IJS_Runtime::Create(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
50 return new CJS_Runtime(pFormFillEnv);
Tom Sepez37458412015-10-06 11:33:46 -070051}
52
Tom Sepez67fd5df2015-10-08 12:24:19 -070053// static
tsepezb4694242016-08-15 16:44:55 -070054CJS_Runtime* CJS_Runtime::CurrentRuntimeFromIsolate(v8::Isolate* pIsolate) {
55 return static_cast<CJS_Runtime*>(
56 CFXJS_Engine::CurrentEngineFromIsolate(pIsolate));
57}
58
dsinclair82e17672016-10-11 12:38:01 -070059CJS_Runtime::CJS_Runtime(CPDFSDK_FormFillEnvironment* pFormFillEnv)
60 : m_pFormFillEnv(pFormFillEnv),
tsepeza4941912016-08-15 11:40:12 -070061 m_bBlocking(false),
Jochen Eisinger29007842015-08-05 09:02:13 +020062 m_isolateManaged(false) {
tsepezb4694242016-08-15 16:44:55 -070063 v8::Isolate* pIsolate = nullptr;
dsinclair8837c912016-11-01 11:22:37 -070064
dsinclair82e17672016-10-11 12:38:01 -070065 IPDF_JSPLATFORM* pPlatform = m_pFormFillEnv->GetFormFillInfo()->m_pJsPlatform;
Tom Sepez51da0932015-11-25 16:05:49 -080066 if (pPlatform->version <= 2) {
67 unsigned int embedderDataSlot = 0;
68 v8::Isolate* pExternalIsolate = nullptr;
69 if (pPlatform->version == 2) {
70 pExternalIsolate = reinterpret_cast<v8::Isolate*>(pPlatform->m_isolate);
71 embedderDataSlot = pPlatform->m_v8EmbedderSlot;
dsinclaird71bae02016-06-09 14:21:20 -070072 }
73 FXJS_Initialize(embedderDataSlot, pExternalIsolate);
74 }
tsepezb4694242016-08-15 16:44:55 -070075 m_isolateManaged = FXJS_GetIsolate(&pIsolate);
76 SetIsolate(pIsolate);
Tom Sepezd2cc1b92015-04-30 15:19:03 -070077
dsinclair8837c912016-11-01 11:22:37 -070078#ifdef PDF_ENABLE_XFA
tsepezb4694242016-08-15 16:44:55 -070079 v8::Isolate::Scope isolate_scope(pIsolate);
80 v8::HandleScope handle_scope(pIsolate);
Tom Sepez51da0932015-11-25 16:05:49 -080081#endif
dsinclaird71bae02016-06-09 14:21:20 -070082
Lei Zhang3fa115b2015-10-08 12:04:47 -070083 if (m_isolateManaged || FXJS_GlobalIsolateRefCount() == 0)
84 DefineJSObjects();
85
Tom Sepezd6ae2af2017-02-16 11:49:55 -080086 IJS_EventContext* pContext = NewEventContext();
tsepezb4694242016-08-15 16:44:55 -070087 InitializeEngine();
Tom Sepezd6ae2af2017-02-16 11:49:55 -080088 ReleaseEventContext(pContext);
dsinclair82e17672016-10-11 12:38:01 -070089 SetFormFillEnvToDocument();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070090}
91
Nico Weber9d8ec5a2015-08-04 13:00:21 -070092CJS_Runtime::~CJS_Runtime() {
tsepez1c620542016-09-12 09:47:52 -070093 NotifyObservedPtrs();
tsepezb4694242016-08-15 16:44:55 -070094 ReleaseEngine();
95 if (m_isolateManaged) {
96 GetIsolate()->Dispose();
97 SetIsolate(nullptr);
98 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070099}
100
Tom Sepez142165e2015-09-11 13:21:50 -0700101void CJS_Runtime::DefineJSObjects() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700102 v8::Isolate::Scope isolate_scope(GetIsolate());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700103 v8::HandleScope handle_scope(GetIsolate());
104 v8::Local<v8::Context> context = v8::Context::New(GetIsolate());
105 v8::Context::Scope context_scope(context);
Tom Sepez570875c2015-09-11 08:35:03 -0700106
107 // The call order determines the "ObjDefID" assigned to each class.
108 // ObjDefIDs 0 - 2
tsepezb4694242016-08-15 16:44:55 -0700109 CJS_Border::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
110 CJS_Display::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
111 CJS_Font::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700112
Tom Sepez570875c2015-09-11 08:35:03 -0700113 // ObjDefIDs 3 - 5
tsepezb4694242016-08-15 16:44:55 -0700114 CJS_Highlight::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
115 CJS_Position::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
116 CJS_ScaleHow::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700117
Tom Sepez570875c2015-09-11 08:35:03 -0700118 // ObjDefIDs 6 - 8
tsepezb4694242016-08-15 16:44:55 -0700119 CJS_ScaleWhen::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
120 CJS_Style::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
121 CJS_Zoomtype::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700122
Tom Sepez570875c2015-09-11 08:35:03 -0700123 // ObjDefIDs 9 - 11
tsepezb4694242016-08-15 16:44:55 -0700124 CJS_App::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
125 CJS_Color::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
126 CJS_Console::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700127
Tom Sepez570875c2015-09-11 08:35:03 -0700128 // ObjDefIDs 12 - 14
tsepezb4694242016-08-15 16:44:55 -0700129 CJS_Document::DefineJSObjects(this, FXJSOBJTYPE_GLOBAL);
130 CJS_Event::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
131 CJS_Field::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700132
Tom Sepez570875c2015-09-11 08:35:03 -0700133 // ObjDefIDs 15 - 17
tsepezb4694242016-08-15 16:44:55 -0700134 CJS_Global::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
135 CJS_Icon::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC);
136 CJS_Util::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
Tom Sepez570875c2015-09-11 08:35:03 -0700137
Tom Sepez142165e2015-09-11 13:21:50 -0700138 // ObjDefIDs 18 - 20 (these can't fail, return void).
tsepezb4694242016-08-15 16:44:55 -0700139 CJS_PublicMethods::DefineJSObjects(this);
Tom Sepez67fd5df2015-10-08 12:24:19 -0700140 CJS_GlobalConsts::DefineJSObjects(this);
141 CJS_GlobalArrays::DefineJSObjects(this);
Tom Sepez570875c2015-09-11 08:35:03 -0700142
tonikitoo618cb1f2016-08-18 20:10:17 -0700143 // ObjDefIDs 21 - 23.
tsepezb4694242016-08-15 16:44:55 -0700144 CJS_TimerObj::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC);
145 CJS_PrintParamsObj::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC);
tonikitoo618cb1f2016-08-18 20:10:17 -0700146 CJS_Annot::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700147}
148
Tom Sepezd6ae2af2017-02-16 11:49:55 -0800149IJS_EventContext* CJS_Runtime::NewEventContext() {
150 m_EventContextArray.push_back(
151 std::unique_ptr<CJS_EventContext>(new CJS_EventContext(this)));
152 return m_EventContextArray.back().get();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700153}
154
Tom Sepezd6ae2af2017-02-16 11:49:55 -0800155void CJS_Runtime::ReleaseEventContext(IJS_EventContext* pContext) {
156 auto it = std::find(m_EventContextArray.begin(), m_EventContextArray.end(),
157 pdfium::FakeUniquePtr<CJS_EventContext>(
158 static_cast<CJS_EventContext*>(pContext)));
159 if (it != m_EventContextArray.end())
160 m_EventContextArray.erase(it);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700161}
162
Tom Sepezb1670b52017-02-16 17:01:00 -0800163CJS_EventContext* CJS_Runtime::GetCurrentEventContext() const {
Tom Sepezd6ae2af2017-02-16 11:49:55 -0800164 return m_EventContextArray.empty() ? nullptr
165 : m_EventContextArray.back().get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700166}
167
dsinclair82e17672016-10-11 12:38:01 -0700168void CJS_Runtime::SetFormFillEnvToDocument() {
tsepezb4694242016-08-15 16:44:55 -0700169 v8::Isolate::Scope isolate_scope(GetIsolate());
170 v8::HandleScope handle_scope(GetIsolate());
171 v8::Local<v8::Context> context = NewLocalContext();
172 v8::Context::Scope context_scope(context);
173
tsepezb4694242016-08-15 16:44:55 -0700174 v8::Local<v8::Object> pThis = GetThisObj();
175 if (pThis.IsEmpty())
176 return;
177
178 if (CFXJS_Engine::GetObjDefnID(pThis) != CJS_Document::g_nObjDefnID)
179 return;
180
181 CJS_Document* pJSDocument =
182 static_cast<CJS_Document*>(GetObjectPrivate(pThis));
183 if (!pJSDocument)
184 return;
185
186 Document* pDocument = static_cast<Document*>(pJSDocument->GetEmbedObject());
187 if (!pDocument)
188 return;
189
Tom Sepez77f6d0f2017-02-23 12:14:10 -0800190 pDocument->SetFormFillEnv(m_pFormFillEnv.Get());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700191}
192
dsinclair82e17672016-10-11 12:38:01 -0700193CPDFSDK_FormFillEnvironment* CJS_Runtime::GetFormFillEnv() const {
Tom Sepez77f6d0f2017-02-23 12:14:10 -0800194 return m_pFormFillEnv.Get();
weili625ad662016-06-15 11:21:33 -0700195}
196
tsepezb4694242016-08-15 16:44:55 -0700197int CJS_Runtime::ExecuteScript(const CFX_WideString& script,
198 CFX_WideString* info) {
Tom Sepez33420902015-10-13 15:00:10 -0700199 FXJSErr error = {};
tsepezb4694242016-08-15 16:44:55 -0700200 int nRet = Execute(script, &error);
Tom Sepez33420902015-10-13 15:00:10 -0700201 if (nRet < 0) {
202 info->Format(L"[ Line: %05d { %s } ] : %s", error.linnum - 1, error.srcline,
203 error.message);
204 }
205 return nRet;
206}
207
Tom Sepez5d0e8432015-09-22 15:50:03 -0700208bool CJS_Runtime::AddEventToSet(const FieldEvent& event) {
209 return m_FieldEventSet.insert(event).second;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700210}
211
Tom Sepez5d0e8432015-09-22 15:50:03 -0700212void CJS_Runtime::RemoveEventFromSet(const FieldEvent& event) {
213 m_FieldEventSet.erase(event);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700214}
215
Tom Sepez51da0932015-11-25 16:05:49 -0800216#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700217CFX_WideString ChangeObjName(const CFX_WideString& str) {
218 CFX_WideString sRet = str;
219 sRet.Replace(L"_", L".");
220 return sRet;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700221}
tsepez4cf55152016-11-02 14:37:54 -0700222bool CJS_Runtime::GetValueByName(const CFX_ByteStringC& utf8Name,
223 CFXJSE_Value* pValue) {
Dan Sinclair812e96c2017-03-13 16:43:37 -0400224 const char* name = utf8Name.c_str();
Bo Xufdc00a72014-10-28 23:03:33 -0700225
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700226 v8::Isolate::Scope isolate_scope(GetIsolate());
227 v8::HandleScope handle_scope(GetIsolate());
tsepezb4694242016-08-15 16:44:55 -0700228 v8::Local<v8::Context> context = NewLocalContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700229 v8::Context::Scope context_scope(context);
Bo Xufdc00a72014-10-28 23:03:33 -0700230
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700231 v8::Local<v8::Value> propvalue =
232 context->Global()->Get(v8::String::NewFromUtf8(
233 GetIsolate(), name, v8::String::kNormalString, utf8Name.GetLength()));
Bo Xufdc00a72014-10-28 23:03:33 -0700234
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700235 if (propvalue.IsEmpty()) {
dsinclairf27aeec2016-06-07 19:36:18 -0700236 pValue->SetUndefined();
tsepez4cf55152016-11-02 14:37:54 -0700237 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700238 }
dsinclair12a6b0c2016-05-26 11:14:08 -0700239 pValue->ForceSetValue(propvalue);
tsepez4cf55152016-11-02 14:37:54 -0700240 return true;
Bo Xufdc00a72014-10-28 23:03:33 -0700241}
tsepez4cf55152016-11-02 14:37:54 -0700242bool CJS_Runtime::SetValueByName(const CFX_ByteStringC& utf8Name,
243 CFXJSE_Value* pValue) {
dsinclair12a6b0c2016-05-26 11:14:08 -0700244 if (utf8Name.IsEmpty() || !pValue)
tsepez4cf55152016-11-02 14:37:54 -0700245 return false;
Dan Sinclair812e96c2017-03-13 16:43:37 -0400246 const char* name = utf8Name.c_str();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700247 v8::Isolate* pIsolate = GetIsolate();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700248 v8::Isolate::Scope isolate_scope(pIsolate);
249 v8::HandleScope handle_scope(pIsolate);
tsepezb4694242016-08-15 16:44:55 -0700250 v8::Local<v8::Context> context = NewLocalContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700251 v8::Context::Scope context_scope(context);
Bo Xufdc00a72014-10-28 23:03:33 -0700252
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700253 // v8::Local<v8::Context> tmpCotext =
254 // v8::Local<v8::Context>::New(GetIsolate(), m_context);
dsinclair12a6b0c2016-05-26 11:14:08 -0700255 v8::Local<v8::Value> propvalue =
256 v8::Local<v8::Value>::New(GetIsolate(), pValue->DirectGetValue());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700257 context->Global()->Set(
258 v8::String::NewFromUtf8(pIsolate, name, v8::String::kNormalString,
259 utf8Name.GetLength()),
260 propvalue);
tsepez4cf55152016-11-02 14:37:54 -0700261 return true;
Bo Xufdc00a72014-10-28 23:03:33 -0700262}
Tom Sepez51da0932015-11-25 16:05:49 -0800263#endif