blob: d38455d8be18de6c5ce7e3239e62f2a4d5aca07a [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
dan sinclaird7ac26c2017-10-25 20:30:02 -04007#include "fpdfsdk/javascript/cjs_global.h"
Tom Sepez37458412015-10-06 11:33:46 -07008
Dan Sinclair4b172c42017-10-23 11:22:31 -04009#include <map>
10#include <memory>
Tom Sepeza7757232017-04-18 11:10:39 -070011#include <utility>
Dan Sinclair3ebd1212016-03-09 09:59:23 -050012#include <vector>
13
Dan Sinclaircfb19442017-04-20 13:13:04 -040014#include "core/fxcrt/fx_extension.h"
Dan Sinclairf766ad22016-03-14 13:51:24 -040015#include "fpdfsdk/javascript/JS_Define.h"
Dan Sinclairf766ad22016-03-14 13:51:24 -040016#include "fpdfsdk/javascript/JS_GlobalData.h"
Dan Sinclair4b172c42017-10-23 11:22:31 -040017#include "fpdfsdk/javascript/JS_KeyValue.h"
Dan Sinclairf766ad22016-03-14 13:51:24 -040018#include "fpdfsdk/javascript/JS_Object.h"
19#include "fpdfsdk/javascript/JS_Value.h"
Tom Sepezd6ae2af2017-02-16 11:49:55 -080020#include "fpdfsdk/javascript/cjs_event_context.h"
dan sinclair8b6acdd2017-10-25 20:35:19 -040021#include "fpdfsdk/javascript/cjs_eventhandler.h"
Dan Sinclairf766ad22016-03-14 13:51:24 -040022#include "fpdfsdk/javascript/resource.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070023
Dan Sinclair4b172c42017-10-23 11:22:31 -040024namespace {
25
Dan Sinclair8f524d62017-10-25 13:30:31 -040026WideString PropFromV8Prop(v8::Local<v8::String> property) {
27 v8::String::Utf8Value utf8_value(property);
28 return WideString::FromUTF8(ByteStringView(*utf8_value, utf8_value.length()));
29}
30
Dan Sinclair4b172c42017-10-23 11:22:31 -040031template <class Alt>
32void JSSpecialPropQuery(const char*,
33 v8::Local<v8::String> property,
34 const v8::PropertyCallbackInfo<v8::Integer>& info) {
35 CJS_Runtime* pRuntime =
36 CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
37 if (!pRuntime)
38 return;
39
40 CJS_Object* pJSObj =
41 static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
42 if (!pJSObj)
43 return;
44
45 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
Dan Sinclair8f524d62017-10-25 13:30:31 -040046 CJS_Return result = pObj->QueryProperty(PropFromV8Prop(property).c_str());
47 info.GetReturnValue().Set(!result.HasError() ? 4 : 0);
Dan Sinclair4b172c42017-10-23 11:22:31 -040048}
49
50template <class Alt>
51void JSSpecialPropGet(const char* class_name,
52 v8::Local<v8::String> property,
53 const v8::PropertyCallbackInfo<v8::Value>& info) {
54 CJS_Runtime* pRuntime =
55 CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
56 if (!pRuntime)
57 return;
58
59 CJS_Object* pJSObj =
60 static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
61 if (!pJSObj)
62 return;
63
64 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
Dan Sinclair8f524d62017-10-25 13:30:31 -040065 CJS_Return result =
66 pObj->GetProperty(pRuntime, PropFromV8Prop(property).c_str());
67 if (result.HasError()) {
68 pRuntime->Error(
69 JSFormatErrorString(class_name, "GetProperty", result.Error()));
Dan Sinclair4b172c42017-10-23 11:22:31 -040070 return;
71 }
Dan Sinclair8f524d62017-10-25 13:30:31 -040072
73 if (result.HasReturn())
74 info.GetReturnValue().Set(result.Return());
Dan Sinclair4b172c42017-10-23 11:22:31 -040075}
76
77template <class Alt>
78void JSSpecialPropPut(const char* class_name,
79 v8::Local<v8::String> property,
80 v8::Local<v8::Value> value,
81 const v8::PropertyCallbackInfo<v8::Value>& info) {
82 CJS_Runtime* pRuntime =
83 CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
84 if (!pRuntime)
85 return;
86
87 CJS_Object* pJSObj =
88 static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
89 if (!pJSObj)
90 return;
91
92 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
Dan Sinclair8f524d62017-10-25 13:30:31 -040093 CJS_Return result =
94 pObj->SetProperty(pRuntime, PropFromV8Prop(property).c_str(), value);
95 if (result.HasError()) {
96 pRuntime->Error(
97 JSFormatErrorString(class_name, "PutProperty", result.Error()));
98 }
Dan Sinclair4b172c42017-10-23 11:22:31 -040099}
100
101template <class Alt>
102void JSSpecialPropDel(const char* class_name,
103 v8::Local<v8::String> property,
104 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
105 CJS_Runtime* pRuntime =
106 CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
107 if (!pRuntime)
108 return;
109
110 CJS_Object* pJSObj =
111 static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
112 if (!pJSObj)
113 return;
114
115 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
Dan Sinclair8f524d62017-10-25 13:30:31 -0400116 CJS_Return result =
117 pObj->DelProperty(pRuntime, PropFromV8Prop(property).c_str());
118 if (result.HasError()) {
119 // TODO(dsinclair): Should this set the pRuntime->Error result?
120 // ByteString cbName;
121 // cbName.Format("%s.%s", class_name, "DelProperty");
Dan Sinclair4b172c42017-10-23 11:22:31 -0400122 }
123}
124
125struct JSGlobalData {
126 JSGlobalData();
127 ~JSGlobalData();
128
129 JS_GlobalDataType nType;
130 double dData;
131 bool bData;
132 ByteString sData;
133 v8::Global<v8::Object> pData;
134 bool bPersistent;
135 bool bDeleted;
136};
137
138class JSGlobalAlternate : public CJS_EmbedObj {
139 public:
140 explicit JSGlobalAlternate(CJS_Object* pJSObject);
141 ~JSGlobalAlternate() override;
142
Dan Sinclair8f524d62017-10-25 13:30:31 -0400143 CJS_Return setPersistent(CJS_Runtime* pRuntime,
144 const std::vector<v8::Local<v8::Value>>& params);
145 CJS_Return QueryProperty(const wchar_t* propname);
146 CJS_Return GetProperty(CJS_Runtime* pRuntime, const wchar_t* propname);
147 CJS_Return SetProperty(CJS_Runtime* pRuntime,
148 const wchar_t* propname,
149 v8::Local<v8::Value> vp);
150 CJS_Return DelProperty(CJS_Runtime* pRuntime, const wchar_t* propname);
Dan Sinclair4b172c42017-10-23 11:22:31 -0400151 void Initial(CPDFSDK_FormFillEnvironment* pFormFillEnv);
152
153 private:
154 void UpdateGlobalPersistentVariables();
155 void CommitGlobalPersisitentVariables(CJS_Runtime* pRuntime);
156 void DestroyGlobalPersisitentVariables();
Dan Sinclair8f524d62017-10-25 13:30:31 -0400157 CJS_Return SetGlobalVariables(const ByteString& propname,
158 JS_GlobalDataType nType,
159 double dData,
160 bool bData,
161 const ByteString& sData,
162 v8::Local<v8::Object> pData,
163 bool bDefaultPersistent);
Dan Sinclair4b172c42017-10-23 11:22:31 -0400164 void ObjectToArray(CJS_Runtime* pRuntime,
165 v8::Local<v8::Object> pObj,
166 CJS_GlobalVariableArray& array);
167 void PutObjectProperty(v8::Local<v8::Object> obj, CJS_KeyValue* pData);
168
169 std::map<ByteString, std::unique_ptr<JSGlobalData>> m_MapGlobal;
170 WideString m_sFilePath;
171 CJS_GlobalData* m_pGlobalData;
172 CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv;
173};
174
175} // namespace
176
Dan Sinclairc94a7932017-10-26 16:48:57 -0400177const JSMethodSpec CJS_Global::MethodSpecs[] = {
Tom Sepez9b99b632017-02-21 15:05:57 -0800178 {"setPersistent", setPersistent_static},
Tom Sepez04557b82017-02-16 09:43:10 -0800179 {0, 0}};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700180
Dan Sinclairef299532017-10-26 16:48:30 -0400181int CJS_Global::ObjDefnID = -1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700182
Dan Sinclair4b172c42017-10-23 11:22:31 -0400183// static
184void CJS_Global::setPersistent_static(
185 const v8::FunctionCallbackInfo<v8::Value>& info) {
186 JSMethod<JSGlobalAlternate, &JSGlobalAlternate::setPersistent>(
187 "setPersistent", "global", info);
188}
189
Dan Sinclairef299532017-10-26 16:48:30 -0400190// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400191void CJS_Global::queryprop_static(
192 v8::Local<v8::String> property,
193 const v8::PropertyCallbackInfo<v8::Integer>& info) {
194 JSSpecialPropQuery<JSGlobalAlternate>("global", property, info);
195}
196
Dan Sinclairef299532017-10-26 16:48:30 -0400197// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400198void CJS_Global::getprop_static(
199 v8::Local<v8::String> property,
200 const v8::PropertyCallbackInfo<v8::Value>& info) {
201 JSSpecialPropGet<JSGlobalAlternate>("global", property, info);
202}
203
Dan Sinclairef299532017-10-26 16:48:30 -0400204// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400205void CJS_Global::putprop_static(
206 v8::Local<v8::String> property,
207 v8::Local<v8::Value> value,
208 const v8::PropertyCallbackInfo<v8::Value>& info) {
209 JSSpecialPropPut<JSGlobalAlternate>("global", property, value, info);
210}
211
Dan Sinclairef299532017-10-26 16:48:30 -0400212// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400213void CJS_Global::delprop_static(
214 v8::Local<v8::String> property,
215 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
216 JSSpecialPropDel<JSGlobalAlternate>("global", property, info);
217}
218
Dan Sinclairef299532017-10-26 16:48:30 -0400219// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400220void CJS_Global::DefineAllProperties(CFXJS_Engine* pEngine) {
221 pEngine->DefineObjAllProperties(
Dan Sinclairef299532017-10-26 16:48:30 -0400222 ObjDefnID, CJS_Global::queryprop_static, CJS_Global::getprop_static,
Dan Sinclair89d26c82017-10-26 12:21:28 -0400223 CJS_Global::putprop_static, CJS_Global::delprop_static);
224}
225
Dan Sinclairef299532017-10-26 16:48:30 -0400226// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400227void CJS_Global::DefineJSObjects(CFXJS_Engine* pEngine, FXJSOBJTYPE eObjType) {
Dan Sinclairef299532017-10-26 16:48:30 -0400228 ObjDefnID = pEngine->DefineObj("global", eObjType,
229 JSConstructor<CJS_Global, JSGlobalAlternate>,
230 JSDestructor<CJS_Global>);
231 DefineMethods(pEngine, ObjDefnID, MethodSpecs);
Dan Sinclair89d26c82017-10-26 12:21:28 -0400232 DefineAllProperties(pEngine);
233}
234
Dan Sinclairef299532017-10-26 16:48:30 -0400235void CJS_Global::InitInstance(IJS_Runtime* pIRuntime) {
236 CJS_Runtime* pRuntime = static_cast<CJS_Runtime*>(pIRuntime);
237 JSGlobalAlternate* pGlobal =
238 static_cast<JSGlobalAlternate*>(GetEmbedObject());
239 pGlobal->Initial(pRuntime->GetFormFillEnv());
240}
241
weili625ad662016-06-15 11:21:33 -0700242JSGlobalData::JSGlobalData()
weili47228ac2016-07-20 10:35:31 -0700243 : nType(JS_GlobalDataType::NUMBER),
weili625ad662016-06-15 11:21:33 -0700244 dData(0),
tsepez4cf55152016-11-02 14:37:54 -0700245 bData(false),
weili625ad662016-06-15 11:21:33 -0700246 sData(""),
tsepez4cf55152016-11-02 14:37:54 -0700247 bPersistent(false),
248 bDeleted(false) {}
weili625ad662016-06-15 11:21:33 -0700249
250JSGlobalData::~JSGlobalData() {
251 pData.Reset();
252}
253
Tom Sepez7dc5cc12015-08-17 12:15:26 -0700254JSGlobalAlternate::JSGlobalAlternate(CJS_Object* pJSObject)
dsinclair8779fa82016-10-12 12:05:44 -0700255 : CJS_EmbedObj(pJSObject), m_pFormFillEnv(nullptr) {}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700256
Tom Sepez7dc5cc12015-08-17 12:15:26 -0700257JSGlobalAlternate::~JSGlobalAlternate() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700258 DestroyGlobalPersisitentVariables();
Tom Sepezf4583622015-09-14 15:06:53 -0700259 m_pGlobalData->Release();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700260}
261
dsinclair8779fa82016-10-12 12:05:44 -0700262void JSGlobalAlternate::Initial(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
Tom Sepez77f6d0f2017-02-23 12:14:10 -0800263 m_pFormFillEnv.Reset(pFormFillEnv);
dsinclair8779fa82016-10-12 12:05:44 -0700264 m_pGlobalData = CJS_GlobalData::GetRetainedInstance(pFormFillEnv);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700265 UpdateGlobalPersistentVariables();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700266}
Tom Sepezbdeeb8a2015-05-27 12:25:00 -0700267
Dan Sinclair8f524d62017-10-25 13:30:31 -0400268CJS_Return JSGlobalAlternate::QueryProperty(const wchar_t* propname) {
269 return CJS_Return(WideString(propname) != L"setPersistent");
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700270}
271
Dan Sinclair8f524d62017-10-25 13:30:31 -0400272CJS_Return JSGlobalAlternate::DelProperty(CJS_Runtime* pRuntime,
273 const wchar_t* propname) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400274 auto it = m_MapGlobal.find(ByteString::FromUnicode(propname));
Tom Sepeza7757232017-04-18 11:10:39 -0700275 if (it == m_MapGlobal.end())
Dan Sinclair8f524d62017-10-25 13:30:31 -0400276 return CJS_Return(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700277
tsepez4cf55152016-11-02 14:37:54 -0700278 it->second->bDeleted = true;
Dan Sinclair8f524d62017-10-25 13:30:31 -0400279 return CJS_Return(true);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700280}
281
Dan Sinclair8f524d62017-10-25 13:30:31 -0400282CJS_Return JSGlobalAlternate::GetProperty(CJS_Runtime* pRuntime,
283 const wchar_t* propname) {
dan sinclaircbe23db2017-10-19 14:29:33 -0400284 auto it = m_MapGlobal.find(ByteString::FromUnicode(propname));
dan sinclair5daf07a2017-10-24 21:46:57 -0400285 if (it == m_MapGlobal.end())
Dan Sinclair8f524d62017-10-25 13:30:31 -0400286 return CJS_Return(true);
dan sinclaircbe23db2017-10-19 14:29:33 -0400287
288 JSGlobalData* pData = it->second.get();
dan sinclair5daf07a2017-10-24 21:46:57 -0400289 if (pData->bDeleted)
Dan Sinclair8f524d62017-10-25 13:30:31 -0400290 return CJS_Return(true);
dan sinclaircbe23db2017-10-19 14:29:33 -0400291
292 switch (pData->nType) {
293 case JS_GlobalDataType::NUMBER:
Dan Sinclair8f524d62017-10-25 13:30:31 -0400294 return CJS_Return(pRuntime->NewNumber(pData->dData));
dan sinclaircbe23db2017-10-19 14:29:33 -0400295 case JS_GlobalDataType::BOOLEAN:
Dan Sinclair8f524d62017-10-25 13:30:31 -0400296 return CJS_Return(pRuntime->NewBoolean(pData->bData));
dan sinclaircbe23db2017-10-19 14:29:33 -0400297 case JS_GlobalDataType::STRING:
Dan Sinclair8f524d62017-10-25 13:30:31 -0400298 return CJS_Return(pRuntime->NewString(
Dan Sinclaire4974922017-10-24 09:36:16 -0400299 WideString::FromLocal(pData->sData.c_str()).c_str()));
Dan Sinclair8f524d62017-10-25 13:30:31 -0400300 case JS_GlobalDataType::OBJECT:
301 return CJS_Return(
302 v8::Local<v8::Object>::New(pRuntime->GetIsolate(), pData->pData));
dan sinclaircbe23db2017-10-19 14:29:33 -0400303 case JS_GlobalDataType::NULLOBJ:
Dan Sinclair8f524d62017-10-25 13:30:31 -0400304 return CJS_Return(pRuntime->NewNull());
dan sinclaircbe23db2017-10-19 14:29:33 -0400305 default:
306 break;
307 }
Dan Sinclair8f524d62017-10-25 13:30:31 -0400308 return CJS_Return(false);
dan sinclaircbe23db2017-10-19 14:29:33 -0400309}
310
Dan Sinclair8f524d62017-10-25 13:30:31 -0400311CJS_Return JSGlobalAlternate::SetProperty(CJS_Runtime* pRuntime,
312 const wchar_t* propname,
313 v8::Local<v8::Value> vp) {
dan sinclaircbe23db2017-10-19 14:29:33 -0400314 ByteString sPropName = ByteString::FromUnicode(propname);
dan sinclair80435cb2017-10-24 21:40:24 -0400315 if (vp->IsNumber()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400316 return SetGlobalVariables(sPropName, JS_GlobalDataType::NUMBER,
dan sinclair80435cb2017-10-24 21:40:24 -0400317 pRuntime->ToDouble(vp), false, "",
Dan Sinclair3cac3602017-10-24 15:15:27 -0400318 v8::Local<v8::Object>(), false);
319 }
dan sinclair80435cb2017-10-24 21:40:24 -0400320 if (vp->IsBoolean()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400321 return SetGlobalVariables(sPropName, JS_GlobalDataType::BOOLEAN, 0,
dan sinclair80435cb2017-10-24 21:40:24 -0400322 pRuntime->ToBoolean(vp), "",
Dan Sinclair3cac3602017-10-24 15:15:27 -0400323 v8::Local<v8::Object>(), false);
324 }
dan sinclair80435cb2017-10-24 21:40:24 -0400325 if (vp->IsString()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400326 return SetGlobalVariables(
327 sPropName, JS_GlobalDataType::STRING, 0, false,
dan sinclair80435cb2017-10-24 21:40:24 -0400328 ByteString::FromUnicode(pRuntime->ToWideString(vp)),
Dan Sinclair3cac3602017-10-24 15:15:27 -0400329 v8::Local<v8::Object>(), false);
330 }
dan sinclair80435cb2017-10-24 21:40:24 -0400331 if (vp->IsObject()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400332 return SetGlobalVariables(sPropName, JS_GlobalDataType::OBJECT, 0, false,
dan sinclair80435cb2017-10-24 21:40:24 -0400333 "", pRuntime->ToObject(vp), false);
Dan Sinclair3cac3602017-10-24 15:15:27 -0400334 }
dan sinclair80435cb2017-10-24 21:40:24 -0400335 if (vp->IsNull()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400336 return SetGlobalVariables(sPropName, JS_GlobalDataType::NULLOBJ, 0, false,
337 "", v8::Local<v8::Object>(), false);
338 }
dan sinclair80435cb2017-10-24 21:40:24 -0400339 if (vp->IsUndefined()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400340 DelProperty(pRuntime, propname);
Dan Sinclair8f524d62017-10-25 13:30:31 -0400341 return CJS_Return(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700342 }
Dan Sinclair8f524d62017-10-25 13:30:31 -0400343 return CJS_Return(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700344}
345
Dan Sinclair8f524d62017-10-25 13:30:31 -0400346CJS_Return JSGlobalAlternate::setPersistent(
dan sinclair80435cb2017-10-24 21:40:24 -0400347 CJS_Runtime* pRuntime,
Dan Sinclair8f524d62017-10-25 13:30:31 -0400348 const std::vector<v8::Local<v8::Value>>& params) {
349 if (params.size() != 2)
350 return CJS_Return(JSGetStringFromID(IDS_STRING_JSPARAMERROR));
351
Dan Sinclair1b2a18e2017-10-24 13:56:29 -0400352 auto it = m_MapGlobal.find(
dan sinclair80435cb2017-10-24 21:40:24 -0400353 ByteString::FromUnicode(pRuntime->ToWideString(params[0])));
Dan Sinclair8f524d62017-10-25 13:30:31 -0400354 if (it == m_MapGlobal.end() || it->second->bDeleted)
355 return CJS_Return(JSGetStringFromID(IDS_STRING_JSNOGLOBAL));
356
dan sinclair80435cb2017-10-24 21:40:24 -0400357 it->second->bPersistent = pRuntime->ToBoolean(params[1]);
Dan Sinclair8f524d62017-10-25 13:30:31 -0400358 return CJS_Return(true);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700359}
360
Tom Sepez7dc5cc12015-08-17 12:15:26 -0700361void JSGlobalAlternate::UpdateGlobalPersistentVariables() {
tsepezb4694242016-08-15 16:44:55 -0700362 CJS_Runtime* pRuntime =
363 static_cast<CJS_Runtime*>(CFXJS_Engine::CurrentEngineFromIsolate(
364 m_pJSObject->ToV8Object()->GetIsolate()));
365
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700366 for (int i = 0, sz = m_pGlobalData->GetSize(); i < sz; i++) {
367 CJS_GlobalData_Element* pData = m_pGlobalData->GetAt(i);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700368 switch (pData->data.nType) {
weili47228ac2016-07-20 10:35:31 -0700369 case JS_GlobalDataType::NUMBER:
370 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::NUMBER,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700371 pData->data.dData, false, "",
372 v8::Local<v8::Object>(), pData->bPersistent == 1);
tsepeze6cf0132017-01-18 14:38:18 -0800373 pRuntime->PutObjectProperty(m_pJSObject->ToV8Object(),
374 pData->data.sKey.UTF8Decode(),
375 pRuntime->NewNumber(pData->data.dData));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700376 break;
weili47228ac2016-07-20 10:35:31 -0700377 case JS_GlobalDataType::BOOLEAN:
378 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::BOOLEAN, 0,
tsepeze6cf0132017-01-18 14:38:18 -0800379 pData->data.bData == 1, "", v8::Local<v8::Object>(),
380 pData->bPersistent == 1);
381 pRuntime->PutObjectProperty(
382 m_pJSObject->ToV8Object(), pData->data.sKey.UTF8Decode(),
383 pRuntime->NewBoolean(pData->data.bData == 1));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700384 break;
weili47228ac2016-07-20 10:35:31 -0700385 case JS_GlobalDataType::STRING:
386 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::STRING, 0,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700387 false, pData->data.sData, v8::Local<v8::Object>(),
388 pData->bPersistent == 1);
tsepeze6cf0132017-01-18 14:38:18 -0800389 pRuntime->PutObjectProperty(
390 m_pJSObject->ToV8Object(), pData->data.sKey.UTF8Decode(),
Ryan Harrison275e2602017-09-18 14:23:18 -0400391 pRuntime->NewString(pData->data.sData.UTF8Decode().AsStringView()));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700392 break;
weili47228ac2016-07-20 10:35:31 -0700393 case JS_GlobalDataType::OBJECT: {
tsepezb4694242016-08-15 16:44:55 -0700394 v8::Local<v8::Object> pObj = pRuntime->NewFxDynamicObj(-1);
Tom Sepez63b2fc72017-08-14 16:24:29 -0700395 if (!pObj.IsEmpty()) {
396 PutObjectProperty(pObj, &pData->data);
397 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::OBJECT, 0,
398 false, "", pObj, pData->bPersistent == 1);
399 pRuntime->PutObjectProperty(m_pJSObject->ToV8Object(),
400 pData->data.sKey.UTF8Decode(), pObj);
401 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700402 } break;
weili47228ac2016-07-20 10:35:31 -0700403 case JS_GlobalDataType::NULLOBJ:
404 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::NULLOBJ, 0,
405 false, "", v8::Local<v8::Object>(),
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700406 pData->bPersistent == 1);
tsepeze6cf0132017-01-18 14:38:18 -0800407 pRuntime->PutObjectProperty(m_pJSObject->ToV8Object(),
408 pData->data.sKey.UTF8Decode(),
409 pRuntime->NewNull());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700410 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700411 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700412 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700413}
414
Tom Sepezb1670b52017-02-16 17:01:00 -0800415void JSGlobalAlternate::CommitGlobalPersisitentVariables(
416 CJS_Runtime* pRuntime) {
Tom Sepeza7757232017-04-18 11:10:39 -0700417 for (const auto& iter : m_MapGlobal) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400418 ByteString name = iter.first;
Tom Sepeza7757232017-04-18 11:10:39 -0700419 JSGlobalData* pData = iter.second.get();
Tom Sepez09d33bc2015-08-19 09:49:24 -0700420 if (pData->bDeleted) {
421 m_pGlobalData->DeleteGlobalVariable(name);
Tom Sepeza7757232017-04-18 11:10:39 -0700422 continue;
423 }
424 switch (pData->nType) {
425 case JS_GlobalDataType::NUMBER:
426 m_pGlobalData->SetGlobalVariableNumber(name, pData->dData);
427 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
428 break;
429 case JS_GlobalDataType::BOOLEAN:
430 m_pGlobalData->SetGlobalVariableBoolean(name, pData->bData);
431 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
432 break;
433 case JS_GlobalDataType::STRING:
434 m_pGlobalData->SetGlobalVariableString(name, pData->sData);
435 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
436 break;
437 case JS_GlobalDataType::OBJECT: {
438 CJS_GlobalVariableArray array;
439 v8::Local<v8::Object> obj = v8::Local<v8::Object>::New(
440 GetJSObject()->GetIsolate(), pData->pData);
441 ObjectToArray(pRuntime, obj, array);
442 m_pGlobalData->SetGlobalVariableObject(name, array);
443 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
444 } break;
445 case JS_GlobalDataType::NULLOBJ:
446 m_pGlobalData->SetGlobalVariableNull(name);
447 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
448 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700449 }
450 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700451}
452
Tom Sepezb1670b52017-02-16 17:01:00 -0800453void JSGlobalAlternate::ObjectToArray(CJS_Runtime* pRuntime,
Tom Sepez67fd5df2015-10-08 12:24:19 -0700454 v8::Local<v8::Object> pObj,
Tom Sepez7dc5cc12015-08-17 12:15:26 -0700455 CJS_GlobalVariableArray& array) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400456 std::vector<WideString> pKeyList = pRuntime->GetObjectPropertyNames(pObj);
tsepezd0b6ed12016-08-11 19:50:57 -0700457 for (const auto& ws : pKeyList) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400458 ByteString sKey = ws.UTF8Encode();
tsepezb4694242016-08-15 16:44:55 -0700459 v8::Local<v8::Value> v = pRuntime->GetObjectProperty(pObj, ws);
Dan Sinclair3cac3602017-10-24 15:15:27 -0400460 if (v->IsNumber()) {
461 CJS_KeyValue* pObjElement = new CJS_KeyValue;
462 pObjElement->nType = JS_GlobalDataType::NUMBER;
463 pObjElement->sKey = sKey;
464 pObjElement->dData = pRuntime->ToDouble(v);
465 array.Add(pObjElement);
466 continue;
467 }
468 if (v->IsBoolean()) {
469 CJS_KeyValue* pObjElement = new CJS_KeyValue;
470 pObjElement->nType = JS_GlobalDataType::BOOLEAN;
471 pObjElement->sKey = sKey;
472 pObjElement->dData = pRuntime->ToBoolean(v);
473 array.Add(pObjElement);
474 continue;
475 }
476 if (v->IsString()) {
477 ByteString sValue = ByteString::FromUnicode(pRuntime->ToWideString(v));
478 CJS_KeyValue* pObjElement = new CJS_KeyValue;
479 pObjElement->nType = JS_GlobalDataType::STRING;
480 pObjElement->sKey = sKey;
481 pObjElement->sData = sValue;
482 array.Add(pObjElement);
483 continue;
484 }
485 if (v->IsObject()) {
486 CJS_KeyValue* pObjElement = new CJS_KeyValue;
487 pObjElement->nType = JS_GlobalDataType::OBJECT;
488 pObjElement->sKey = sKey;
489 ObjectToArray(pRuntime, pRuntime->ToObject(v), pObjElement->objData);
490 array.Add(pObjElement);
491 continue;
492 }
493 if (v->IsNull()) {
494 CJS_KeyValue* pObjElement = new CJS_KeyValue;
495 pObjElement->nType = JS_GlobalDataType::NULLOBJ;
496 pObjElement->sKey = sKey;
497 array.Add(pObjElement);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700498 }
499 }
500}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700501
Tom Sepez7dc5cc12015-08-17 12:15:26 -0700502void JSGlobalAlternate::PutObjectProperty(v8::Local<v8::Object> pObj,
503 CJS_KeyValue* pData) {
tsepezb4694242016-08-15 16:44:55 -0700504 CJS_Runtime* pRuntime = CJS_Runtime::CurrentRuntimeFromIsolate(
505 m_pJSObject->ToV8Object()->GetIsolate());
506
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700507 for (int i = 0, sz = pData->objData.Count(); i < sz; i++) {
508 CJS_KeyValue* pObjData = pData->objData.GetAt(i);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700509 switch (pObjData->nType) {
weili47228ac2016-07-20 10:35:31 -0700510 case JS_GlobalDataType::NUMBER:
tsepeze6cf0132017-01-18 14:38:18 -0800511 pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
512 pRuntime->NewNumber(pObjData->dData));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700513 break;
weili47228ac2016-07-20 10:35:31 -0700514 case JS_GlobalDataType::BOOLEAN:
tsepeze6cf0132017-01-18 14:38:18 -0800515 pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
516 pRuntime->NewBoolean(pObjData->bData == 1));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700517 break;
weili47228ac2016-07-20 10:35:31 -0700518 case JS_GlobalDataType::STRING:
tsepeze6cf0132017-01-18 14:38:18 -0800519 pRuntime->PutObjectProperty(
520 pObj, pObjData->sKey.UTF8Decode(),
Ryan Harrison275e2602017-09-18 14:23:18 -0400521 pRuntime->NewString(pObjData->sData.UTF8Decode().AsStringView()));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700522 break;
weili47228ac2016-07-20 10:35:31 -0700523 case JS_GlobalDataType::OBJECT: {
tsepezb4694242016-08-15 16:44:55 -0700524 v8::Local<v8::Object> pNewObj = pRuntime->NewFxDynamicObj(-1);
Tom Sepez63b2fc72017-08-14 16:24:29 -0700525 if (!pNewObj.IsEmpty()) {
526 PutObjectProperty(pNewObj, pObjData);
527 pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
528 pNewObj);
529 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700530 } break;
weili47228ac2016-07-20 10:35:31 -0700531 case JS_GlobalDataType::NULLOBJ:
tsepeze6cf0132017-01-18 14:38:18 -0800532 pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
533 pRuntime->NewNull());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700534 break;
535 }
536 }
537}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700538
Tom Sepez7dc5cc12015-08-17 12:15:26 -0700539void JSGlobalAlternate::DestroyGlobalPersisitentVariables() {
Tom Sepeza7757232017-04-18 11:10:39 -0700540 m_MapGlobal.clear();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700541}
542
Dan Sinclair8f524d62017-10-25 13:30:31 -0400543CJS_Return JSGlobalAlternate::SetGlobalVariables(const ByteString& propname,
544 JS_GlobalDataType nType,
545 double dData,
546 bool bData,
547 const ByteString& sData,
548 v8::Local<v8::Object> pData,
549 bool bDefaultPersistent) {
tsepezb4c9f3f2016-04-13 15:41:21 -0700550 if (propname.IsEmpty())
Dan Sinclair8f524d62017-10-25 13:30:31 -0400551 return CJS_Return(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700552
Tom Sepeza7757232017-04-18 11:10:39 -0700553 auto it = m_MapGlobal.find(propname);
554 if (it != m_MapGlobal.end()) {
555 JSGlobalData* pTemp = it->second.get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700556 if (pTemp->bDeleted || pTemp->nType != nType) {
557 pTemp->dData = 0;
558 pTemp->bData = 0;
559 pTemp->sData = "";
560 pTemp->nType = nType;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700561 }
tsepez4cf55152016-11-02 14:37:54 -0700562 pTemp->bDeleted = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700563 switch (nType) {
Tom Sepeza7757232017-04-18 11:10:39 -0700564 case JS_GlobalDataType::NUMBER:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700565 pTemp->dData = dData;
Tom Sepeza7757232017-04-18 11:10:39 -0700566 break;
567 case JS_GlobalDataType::BOOLEAN:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700568 pTemp->bData = bData;
Tom Sepeza7757232017-04-18 11:10:39 -0700569 break;
570 case JS_GlobalDataType::STRING:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700571 pTemp->sData = sData;
Tom Sepeza7757232017-04-18 11:10:39 -0700572 break;
573 case JS_GlobalDataType::OBJECT:
Tom Sepez371379d2015-11-06 08:29:39 -0800574 pTemp->pData.Reset(pData->GetIsolate(), pData);
Tom Sepeza7757232017-04-18 11:10:39 -0700575 break;
weili47228ac2016-07-20 10:35:31 -0700576 case JS_GlobalDataType::NULLOBJ:
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700577 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700578 default:
Dan Sinclair8f524d62017-10-25 13:30:31 -0400579 return CJS_Return(false);
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700580 }
Dan Sinclair8f524d62017-10-25 13:30:31 -0400581 return CJS_Return(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700582 }
583
Tom Sepeza7757232017-04-18 11:10:39 -0700584 auto pNewData = pdfium::MakeUnique<JSGlobalData>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700585 switch (nType) {
Tom Sepeza7757232017-04-18 11:10:39 -0700586 case JS_GlobalDataType::NUMBER:
weili47228ac2016-07-20 10:35:31 -0700587 pNewData->nType = JS_GlobalDataType::NUMBER;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700588 pNewData->dData = dData;
589 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700590 break;
591 case JS_GlobalDataType::BOOLEAN:
weili47228ac2016-07-20 10:35:31 -0700592 pNewData->nType = JS_GlobalDataType::BOOLEAN;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700593 pNewData->bData = bData;
594 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700595 break;
596 case JS_GlobalDataType::STRING:
weili47228ac2016-07-20 10:35:31 -0700597 pNewData->nType = JS_GlobalDataType::STRING;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700598 pNewData->sData = sData;
599 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700600 break;
601 case JS_GlobalDataType::OBJECT:
weili47228ac2016-07-20 10:35:31 -0700602 pNewData->nType = JS_GlobalDataType::OBJECT;
Tom Sepez371379d2015-11-06 08:29:39 -0800603 pNewData->pData.Reset(pData->GetIsolate(), pData);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700604 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700605 break;
606 case JS_GlobalDataType::NULLOBJ:
weili47228ac2016-07-20 10:35:31 -0700607 pNewData->nType = JS_GlobalDataType::NULLOBJ;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700608 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700609 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700610 default:
Dan Sinclair8f524d62017-10-25 13:30:31 -0400611 return CJS_Return(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700612 }
Tom Sepeza7757232017-04-18 11:10:39 -0700613 m_MapGlobal[propname] = std::move(pNewData);
Dan Sinclair8f524d62017-10-25 13:30:31 -0400614 return CJS_Return(true);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700615}