blob: ea8694fe14b1a09875198e82fc6ba3d20c569ef3 [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 Sinclaire0345a42017-10-30 20:20:42 +00007#include "fxjs/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 Sinclaire0345a42017-10-30 20:20:42 +000015#include "fxjs/cjs_event_context.h"
16#include "fxjs/cjs_eventhandler.h"
Dan Sinclaira3254622017-10-30 20:24:14 +000017#include "fxjs/cjs_globaldata.h"
18#include "fxjs/cjs_keyvalue.h"
Dan Sinclaire0345a42017-10-30 20:20:42 +000019#include "fxjs/cjs_object.h"
Tom Sepez221f0b32018-06-04 22:11:27 +000020#include "fxjs/js_define.h"
Dan Sinclaire0345a42017-10-30 20:20:42 +000021#include "fxjs/js_resources.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070022
Dan Sinclair4b172c42017-10-23 11:22:31 -040023namespace {
24
Adam Klein4c451ba2018-01-17 21:06:27 +000025WideString PropFromV8Prop(v8::Isolate* pIsolate,
26 v8::Local<v8::String> property) {
27 v8::String::Utf8Value utf8_value(pIsolate, property);
Dan Sinclair8f524d62017-10-25 13:30:31 -040028 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) {
Tom Sepez82999fa2018-07-16 22:17:46 +000035 auto pObj = JSGetObject<Alt>(info.Holder());
Lei Zhang6aa21902018-07-12 13:15:11 +000036 if (!pObj)
Dan Sinclair4b172c42017-10-23 11:22:31 -040037 return;
38
Lei Zhang6aa21902018-07-12 13:15:11 +000039 CJS_Runtime* pRuntime = pObj->GetRuntime();
Tom Sepezddaa40f2018-06-06 18:30:15 +000040 if (!pRuntime)
41 return;
42
Tom Sepez3a6d0582018-08-17 19:28:52 +000043 CJS_Result result =
Lei Zhang6aa21902018-07-12 13:15:11 +000044 pObj->QueryProperty(PropFromV8Prop(info.GetIsolate(), property).c_str());
Tom Sepezddaa40f2018-06-06 18:30:15 +000045
Dan Sinclair8f524d62017-10-25 13:30:31 -040046 info.GetReturnValue().Set(!result.HasError() ? 4 : 0);
Dan Sinclair4b172c42017-10-23 11:22:31 -040047}
48
49template <class Alt>
50void JSSpecialPropGet(const char* class_name,
51 v8::Local<v8::String> property,
52 const v8::PropertyCallbackInfo<v8::Value>& info) {
Tom Sepez82999fa2018-07-16 22:17:46 +000053 auto pObj = JSGetObject<Alt>(info.Holder());
Lei Zhang6aa21902018-07-12 13:15:11 +000054 if (!pObj)
Dan Sinclair4b172c42017-10-23 11:22:31 -040055 return;
56
Lei Zhang6aa21902018-07-12 13:15:11 +000057 CJS_Runtime* pRuntime = pObj->GetRuntime();
Tom Sepezddaa40f2018-06-06 18:30:15 +000058 if (!pRuntime)
59 return;
60
Tom Sepez3a6d0582018-08-17 19:28:52 +000061 CJS_Result result = pObj->GetProperty(
Adam Klein4c451ba2018-01-17 21:06:27 +000062 pRuntime, PropFromV8Prop(info.GetIsolate(), property).c_str());
Tom Sepezddaa40f2018-06-06 18:30:15 +000063
Dan Sinclair8f524d62017-10-25 13:30:31 -040064 if (result.HasError()) {
65 pRuntime->Error(
66 JSFormatErrorString(class_name, "GetProperty", result.Error()));
Dan Sinclair4b172c42017-10-23 11:22:31 -040067 return;
68 }
Dan Sinclair8f524d62017-10-25 13:30:31 -040069 if (result.HasReturn())
70 info.GetReturnValue().Set(result.Return());
Dan Sinclair4b172c42017-10-23 11:22:31 -040071}
72
73template <class Alt>
74void JSSpecialPropPut(const char* class_name,
75 v8::Local<v8::String> property,
76 v8::Local<v8::Value> value,
77 const v8::PropertyCallbackInfo<v8::Value>& info) {
Tom Sepez82999fa2018-07-16 22:17:46 +000078 auto pObj = JSGetObject<Alt>(info.Holder());
Lei Zhang6aa21902018-07-12 13:15:11 +000079 if (!pObj)
Dan Sinclair4b172c42017-10-23 11:22:31 -040080 return;
81
Lei Zhang6aa21902018-07-12 13:15:11 +000082 CJS_Runtime* pRuntime = pObj->GetRuntime();
Tom Sepezddaa40f2018-06-06 18:30:15 +000083 if (!pRuntime)
84 return;
85
Tom Sepez3a6d0582018-08-17 19:28:52 +000086 CJS_Result result = pObj->SetProperty(
Adam Klein4c451ba2018-01-17 21:06:27 +000087 pRuntime, PropFromV8Prop(info.GetIsolate(), property).c_str(), value);
Tom Sepezddaa40f2018-06-06 18:30:15 +000088
Dan Sinclair8f524d62017-10-25 13:30:31 -040089 if (result.HasError()) {
90 pRuntime->Error(
91 JSFormatErrorString(class_name, "PutProperty", result.Error()));
92 }
Dan Sinclair4b172c42017-10-23 11:22:31 -040093}
94
95template <class Alt>
96void JSSpecialPropDel(const char* class_name,
97 v8::Local<v8::String> property,
98 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
Tom Sepez82999fa2018-07-16 22:17:46 +000099 auto pObj = JSGetObject<Alt>(info.Holder());
Lei Zhang6aa21902018-07-12 13:15:11 +0000100 if (!pObj)
Dan Sinclair4b172c42017-10-23 11:22:31 -0400101 return;
102
Lei Zhang6aa21902018-07-12 13:15:11 +0000103 CJS_Runtime* pRuntime = pObj->GetRuntime();
Tom Sepezddaa40f2018-06-06 18:30:15 +0000104 if (!pRuntime)
105 return;
106
Tom Sepez3a6d0582018-08-17 19:28:52 +0000107 CJS_Result result = pObj->DelProperty(
Adam Klein4c451ba2018-01-17 21:06:27 +0000108 pRuntime, PropFromV8Prop(info.GetIsolate(), property).c_str());
Dan Sinclair8f524d62017-10-25 13:30:31 -0400109 if (result.HasError()) {
110 // TODO(dsinclair): Should this set the pRuntime->Error result?
Henrique Nakashima11506302017-12-06 22:09:40 +0000111 // ByteString cbName =
112 // ByteString::Format("%s.%s", class_name, "DelProperty");
Dan Sinclair4b172c42017-10-23 11:22:31 -0400113 }
114}
115
Dan Sinclair4b172c42017-10-23 11:22:31 -0400116} // namespace
117
Dan Sinclairf7435522018-02-05 22:27:22 +0000118CJS_Global::JSGlobalData::JSGlobalData()
119 : nType(JS_GlobalDataType::NUMBER),
120 dData(0),
121 bData(false),
122 sData(""),
123 bPersistent(false),
124 bDeleted(false) {}
125
126CJS_Global::JSGlobalData::~JSGlobalData() {
127 pData.Reset();
128}
129
Dan Sinclairc94a7932017-10-26 16:48:57 -0400130const JSMethodSpec CJS_Global::MethodSpecs[] = {
Dan Sinclair909fa2d2017-12-12 01:53:28 +0000131 {"setPersistent", setPersistent_static}};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700132
Dan Sinclairef299532017-10-26 16:48:30 -0400133int CJS_Global::ObjDefnID = -1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700134
Dan Sinclair4b172c42017-10-23 11:22:31 -0400135// static
136void CJS_Global::setPersistent_static(
137 const v8::FunctionCallbackInfo<v8::Value>& info) {
Dan Sinclairf7435522018-02-05 22:27:22 +0000138 JSMethod<CJS_Global, &CJS_Global::setPersistent>("setPersistent", "global",
139 info);
Dan Sinclair4b172c42017-10-23 11:22:31 -0400140}
141
Dan Sinclairef299532017-10-26 16:48:30 -0400142// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400143void CJS_Global::queryprop_static(
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000144 v8::Local<v8::Name> property,
Dan Sinclair89d26c82017-10-26 12:21:28 -0400145 const v8::PropertyCallbackInfo<v8::Integer>& info) {
Lei Zhang9bad2352018-06-28 13:29:33 +0000146 ASSERT(property->IsString());
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000147 JSSpecialPropQuery<CJS_Global>(
148 "global",
Dan Elphickfd8dfdf2018-07-26 09:57:26 +0000149 v8::Local<v8::String>::New(info.GetIsolate(),
150 property->ToString(info.GetIsolate())),
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000151 info);
Dan Sinclair89d26c82017-10-26 12:21:28 -0400152}
153
Dan Sinclairef299532017-10-26 16:48:30 -0400154// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400155void CJS_Global::getprop_static(
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000156 v8::Local<v8::Name> property,
Dan Sinclair89d26c82017-10-26 12:21:28 -0400157 const v8::PropertyCallbackInfo<v8::Value>& info) {
Lei Zhang9bad2352018-06-28 13:29:33 +0000158 ASSERT(property->IsString());
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000159 JSSpecialPropGet<CJS_Global>(
160 "global",
Dan Elphickfd8dfdf2018-07-26 09:57:26 +0000161 v8::Local<v8::String>::New(info.GetIsolate(),
162 property->ToString(info.GetIsolate())),
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000163 info);
Dan Sinclair89d26c82017-10-26 12:21:28 -0400164}
165
Dan Sinclairef299532017-10-26 16:48:30 -0400166// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400167void CJS_Global::putprop_static(
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000168 v8::Local<v8::Name> property,
Dan Sinclair89d26c82017-10-26 12:21:28 -0400169 v8::Local<v8::Value> value,
170 const v8::PropertyCallbackInfo<v8::Value>& info) {
Lei Zhang9bad2352018-06-28 13:29:33 +0000171 ASSERT(property->IsString());
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000172 JSSpecialPropPut<CJS_Global>(
173 "global",
Dan Elphickfd8dfdf2018-07-26 09:57:26 +0000174 v8::Local<v8::String>::New(info.GetIsolate(),
175 property->ToString(info.GetIsolate())),
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000176 value, info);
Dan Sinclair89d26c82017-10-26 12:21:28 -0400177}
178
Dan Sinclairef299532017-10-26 16:48:30 -0400179// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400180void CJS_Global::delprop_static(
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000181 v8::Local<v8::Name> property,
Dan Sinclair89d26c82017-10-26 12:21:28 -0400182 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
Lei Zhang9bad2352018-06-28 13:29:33 +0000183 ASSERT(property->IsString());
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000184 JSSpecialPropDel<CJS_Global>(
185 "global",
Dan Elphickfd8dfdf2018-07-26 09:57:26 +0000186 v8::Local<v8::String>::New(info.GetIsolate(),
187 property->ToString(info.GetIsolate())),
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000188 info);
Dan Sinclair89d26c82017-10-26 12:21:28 -0400189}
190
Dan Sinclairef299532017-10-26 16:48:30 -0400191// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400192void CJS_Global::DefineAllProperties(CFXJS_Engine* pEngine) {
193 pEngine->DefineObjAllProperties(
Dan Sinclairef299532017-10-26 16:48:30 -0400194 ObjDefnID, CJS_Global::queryprop_static, CJS_Global::getprop_static,
Dan Sinclair89d26c82017-10-26 12:21:28 -0400195 CJS_Global::putprop_static, CJS_Global::delprop_static);
196}
197
Dan Sinclairef299532017-10-26 16:48:30 -0400198// static
Lei Zhangad1f7b42018-07-11 13:04:43 +0000199int CJS_Global::GetObjDefnID() {
200 return ObjDefnID;
201}
202
203// static
Dan Sinclairbef4d3e2017-10-26 16:49:38 -0400204void CJS_Global::DefineJSObjects(CFXJS_Engine* pEngine) {
205 ObjDefnID = pEngine->DefineObj("global", FXJSOBJTYPE_STATIC,
Dan Sinclair998fee32018-02-05 21:43:19 +0000206 JSConstructor<CJS_Global>, JSDestructor);
Tom Sepez8b4ddeb2018-06-11 15:55:17 +0000207 DefineMethods(pEngine, ObjDefnID, MethodSpecs);
Dan Sinclair89d26c82017-10-26 12:21:28 -0400208 DefineAllProperties(pEngine);
209}
210
Tom Sepez36aae4f2018-06-04 19:44:37 +0000211CJS_Global::CJS_Global(v8::Local<v8::Object> pObject, CJS_Runtime* pRuntime)
Tom Sepez83b259e2018-06-08 20:43:55 +0000212 : CJS_Object(pObject, pRuntime) {
213 Initial(GetRuntime()->GetFormFillEnv());
214}
Dan Sinclair998fee32018-02-05 21:43:19 +0000215
Dan Sinclairf7435522018-02-05 22:27:22 +0000216CJS_Global::~CJS_Global() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700217 DestroyGlobalPersisitentVariables();
Tom Sepezf4583622015-09-14 15:06:53 -0700218 m_pGlobalData->Release();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700219}
220
Dan Sinclairf7435522018-02-05 22:27:22 +0000221void CJS_Global::Initial(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
Tom Sepez77f6d0f2017-02-23 12:14:10 -0800222 m_pFormFillEnv.Reset(pFormFillEnv);
dsinclair8779fa82016-10-12 12:05:44 -0700223 m_pGlobalData = CJS_GlobalData::GetRetainedInstance(pFormFillEnv);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700224 UpdateGlobalPersistentVariables();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700225}
Tom Sepezbdeeb8a2015-05-27 12:25:00 -0700226
Tom Sepez3a6d0582018-08-17 19:28:52 +0000227CJS_Result CJS_Global::QueryProperty(const wchar_t* propname) {
Tom Sepez16999822018-06-08 18:23:05 +0000228 if (WideString(propname) != L"setPersistent")
Tom Sepez3a6d0582018-08-17 19:28:52 +0000229 return CJS_Result::Failure(JSMessage::kUnknownProperty);
230 return CJS_Result::Success();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700231}
232
Tom Sepez3a6d0582018-08-17 19:28:52 +0000233CJS_Result CJS_Global::DelProperty(CJS_Runtime* pRuntime,
Dan Sinclairf7435522018-02-05 22:27:22 +0000234 const wchar_t* propname) {
Tom Sepez34dab072018-08-08 17:49:02 +0000235 auto it = m_MapGlobal.find(WideString(propname).ToDefANSI());
Tom Sepeza7757232017-04-18 11:10:39 -0700236 if (it == m_MapGlobal.end())
Tom Sepez3a6d0582018-08-17 19:28:52 +0000237 return CJS_Result::Failure(JSMessage::kUnknownProperty);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700238
tsepez4cf55152016-11-02 14:37:54 -0700239 it->second->bDeleted = true;
Tom Sepez3a6d0582018-08-17 19:28:52 +0000240 return CJS_Result::Success();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700241}
242
Tom Sepez3a6d0582018-08-17 19:28:52 +0000243CJS_Result CJS_Global::GetProperty(CJS_Runtime* pRuntime,
Dan Sinclairf7435522018-02-05 22:27:22 +0000244 const wchar_t* propname) {
Tom Sepez34dab072018-08-08 17:49:02 +0000245 auto it = m_MapGlobal.find(WideString(propname).ToDefANSI());
dan sinclair5daf07a2017-10-24 21:46:57 -0400246 if (it == m_MapGlobal.end())
Tom Sepez3a6d0582018-08-17 19:28:52 +0000247 return CJS_Result::Success();
dan sinclaircbe23db2017-10-19 14:29:33 -0400248
249 JSGlobalData* pData = it->second.get();
dan sinclair5daf07a2017-10-24 21:46:57 -0400250 if (pData->bDeleted)
Tom Sepez3a6d0582018-08-17 19:28:52 +0000251 return CJS_Result::Success();
dan sinclaircbe23db2017-10-19 14:29:33 -0400252
253 switch (pData->nType) {
254 case JS_GlobalDataType::NUMBER:
Tom Sepez3a6d0582018-08-17 19:28:52 +0000255 return CJS_Result::Success(pRuntime->NewNumber(pData->dData));
dan sinclaircbe23db2017-10-19 14:29:33 -0400256 case JS_GlobalDataType::BOOLEAN:
Tom Sepez3a6d0582018-08-17 19:28:52 +0000257 return CJS_Result::Success(pRuntime->NewBoolean(pData->bData));
dan sinclaircbe23db2017-10-19 14:29:33 -0400258 case JS_GlobalDataType::STRING:
Tom Sepez3a6d0582018-08-17 19:28:52 +0000259 return CJS_Result::Success(pRuntime->NewString(
Tom Sepezb6b01cb2018-06-20 16:10:13 +0000260 WideString::FromLocal(pData->sData.AsStringView()).AsStringView()));
Dan Sinclair8f524d62017-10-25 13:30:31 -0400261 case JS_GlobalDataType::OBJECT:
Tom Sepez3a6d0582018-08-17 19:28:52 +0000262 return CJS_Result::Success(
Dan Sinclair8f524d62017-10-25 13:30:31 -0400263 v8::Local<v8::Object>::New(pRuntime->GetIsolate(), pData->pData));
dan sinclaircbe23db2017-10-19 14:29:33 -0400264 case JS_GlobalDataType::NULLOBJ:
Tom Sepez3a6d0582018-08-17 19:28:52 +0000265 return CJS_Result::Success(pRuntime->NewNull());
dan sinclaircbe23db2017-10-19 14:29:33 -0400266 default:
267 break;
268 }
Tom Sepez3a6d0582018-08-17 19:28:52 +0000269 return CJS_Result::Failure(JSMessage::kObjectTypeError);
dan sinclaircbe23db2017-10-19 14:29:33 -0400270}
271
Tom Sepez3a6d0582018-08-17 19:28:52 +0000272CJS_Result CJS_Global::SetProperty(CJS_Runtime* pRuntime,
Dan Sinclairf7435522018-02-05 22:27:22 +0000273 const wchar_t* propname,
274 v8::Local<v8::Value> vp) {
Tom Sepez34dab072018-08-08 17:49:02 +0000275 ByteString sPropName = WideString(propname).ToDefANSI();
dan sinclair80435cb2017-10-24 21:40:24 -0400276 if (vp->IsNumber()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400277 return SetGlobalVariables(sPropName, JS_GlobalDataType::NUMBER,
dan sinclair80435cb2017-10-24 21:40:24 -0400278 pRuntime->ToDouble(vp), false, "",
Dan Sinclair3cac3602017-10-24 15:15:27 -0400279 v8::Local<v8::Object>(), false);
280 }
dan sinclair80435cb2017-10-24 21:40:24 -0400281 if (vp->IsBoolean()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400282 return SetGlobalVariables(sPropName, JS_GlobalDataType::BOOLEAN, 0,
dan sinclair80435cb2017-10-24 21:40:24 -0400283 pRuntime->ToBoolean(vp), "",
Dan Sinclair3cac3602017-10-24 15:15:27 -0400284 v8::Local<v8::Object>(), false);
285 }
dan sinclair80435cb2017-10-24 21:40:24 -0400286 if (vp->IsString()) {
Tom Sepez34dab072018-08-08 17:49:02 +0000287 return SetGlobalVariables(sPropName, JS_GlobalDataType::STRING, 0, false,
288 pRuntime->ToWideString(vp).ToDefANSI(),
289 v8::Local<v8::Object>(), false);
Dan Sinclair3cac3602017-10-24 15:15:27 -0400290 }
dan sinclair80435cb2017-10-24 21:40:24 -0400291 if (vp->IsObject()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400292 return SetGlobalVariables(sPropName, JS_GlobalDataType::OBJECT, 0, false,
dan sinclair80435cb2017-10-24 21:40:24 -0400293 "", pRuntime->ToObject(vp), false);
Dan Sinclair3cac3602017-10-24 15:15:27 -0400294 }
dan sinclair80435cb2017-10-24 21:40:24 -0400295 if (vp->IsNull()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400296 return SetGlobalVariables(sPropName, JS_GlobalDataType::NULLOBJ, 0, false,
297 "", v8::Local<v8::Object>(), false);
298 }
dan sinclair80435cb2017-10-24 21:40:24 -0400299 if (vp->IsUndefined()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400300 DelProperty(pRuntime, propname);
Tom Sepez3a6d0582018-08-17 19:28:52 +0000301 return CJS_Result::Success();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700302 }
Tom Sepez3a6d0582018-08-17 19:28:52 +0000303 return CJS_Result::Failure(JSMessage::kObjectTypeError);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700304}
305
Tom Sepez3a6d0582018-08-17 19:28:52 +0000306CJS_Result CJS_Global::setPersistent(
dan sinclair80435cb2017-10-24 21:40:24 -0400307 CJS_Runtime* pRuntime,
Dan Sinclair8f524d62017-10-25 13:30:31 -0400308 const std::vector<v8::Local<v8::Value>>& params) {
309 if (params.size() != 2)
Tom Sepez3a6d0582018-08-17 19:28:52 +0000310 return CJS_Result::Failure(JSMessage::kParamError);
Dan Sinclair8f524d62017-10-25 13:30:31 -0400311
Tom Sepez34dab072018-08-08 17:49:02 +0000312 auto it = m_MapGlobal.find(pRuntime->ToWideString(params[0]).ToDefANSI());
Dan Sinclair8f524d62017-10-25 13:30:31 -0400313 if (it == m_MapGlobal.end() || it->second->bDeleted)
Tom Sepez3a6d0582018-08-17 19:28:52 +0000314 return CJS_Result::Failure(JSMessage::kGlobalNotFoundError);
Dan Sinclair8f524d62017-10-25 13:30:31 -0400315
dan sinclair80435cb2017-10-24 21:40:24 -0400316 it->second->bPersistent = pRuntime->ToBoolean(params[1]);
Tom Sepez3a6d0582018-08-17 19:28:52 +0000317 return CJS_Result::Success();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700318}
319
Dan Sinclairf7435522018-02-05 22:27:22 +0000320void CJS_Global::UpdateGlobalPersistentVariables() {
Tom Sepez6ffd8402018-06-06 20:51:04 +0000321 CJS_Runtime* pRuntime = GetRuntime();
322 if (!pRuntime)
323 return;
tsepezb4694242016-08-15 16:44:55 -0700324
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700325 for (int i = 0, sz = m_pGlobalData->GetSize(); i < sz; i++) {
326 CJS_GlobalData_Element* pData = m_pGlobalData->GetAt(i);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700327 switch (pData->data.nType) {
weili47228ac2016-07-20 10:35:31 -0700328 case JS_GlobalDataType::NUMBER:
329 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::NUMBER,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700330 pData->data.dData, false, "",
331 v8::Local<v8::Object>(), pData->bPersistent == 1);
Dan Sinclairf7435522018-02-05 22:27:22 +0000332 pRuntime->PutObjectProperty(ToV8Object(), pData->data.sKey.UTF8Decode(),
tsepeze6cf0132017-01-18 14:38:18 -0800333 pRuntime->NewNumber(pData->data.dData));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700334 break;
weili47228ac2016-07-20 10:35:31 -0700335 case JS_GlobalDataType::BOOLEAN:
336 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::BOOLEAN, 0,
tsepeze6cf0132017-01-18 14:38:18 -0800337 pData->data.bData == 1, "", v8::Local<v8::Object>(),
338 pData->bPersistent == 1);
339 pRuntime->PutObjectProperty(
Dan Sinclairf7435522018-02-05 22:27:22 +0000340 ToV8Object(), pData->data.sKey.UTF8Decode(),
tsepeze6cf0132017-01-18 14:38:18 -0800341 pRuntime->NewBoolean(pData->data.bData == 1));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700342 break;
weili47228ac2016-07-20 10:35:31 -0700343 case JS_GlobalDataType::STRING:
344 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::STRING, 0,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700345 false, pData->data.sData, v8::Local<v8::Object>(),
346 pData->bPersistent == 1);
tsepeze6cf0132017-01-18 14:38:18 -0800347 pRuntime->PutObjectProperty(
Dan Sinclairf7435522018-02-05 22:27:22 +0000348 ToV8Object(), pData->data.sKey.UTF8Decode(),
Ryan Harrison275e2602017-09-18 14:23:18 -0400349 pRuntime->NewString(pData->data.sData.UTF8Decode().AsStringView()));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700350 break;
weili47228ac2016-07-20 10:35:31 -0700351 case JS_GlobalDataType::OBJECT: {
Tom Sepez9ad9a5f2018-02-07 21:07:24 +0000352 v8::Local<v8::Object> pObj = pRuntime->NewObject();
Tom Sepez63b2fc72017-08-14 16:24:29 -0700353 if (!pObj.IsEmpty()) {
354 PutObjectProperty(pObj, &pData->data);
355 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::OBJECT, 0,
356 false, "", pObj, pData->bPersistent == 1);
Dan Sinclairf7435522018-02-05 22:27:22 +0000357 pRuntime->PutObjectProperty(ToV8Object(),
Tom Sepez63b2fc72017-08-14 16:24:29 -0700358 pData->data.sKey.UTF8Decode(), pObj);
359 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700360 } break;
weili47228ac2016-07-20 10:35:31 -0700361 case JS_GlobalDataType::NULLOBJ:
362 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::NULLOBJ, 0,
363 false, "", v8::Local<v8::Object>(),
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700364 pData->bPersistent == 1);
Dan Sinclairf7435522018-02-05 22:27:22 +0000365 pRuntime->PutObjectProperty(ToV8Object(), pData->data.sKey.UTF8Decode(),
tsepeze6cf0132017-01-18 14:38:18 -0800366 pRuntime->NewNull());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700367 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700368 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700369 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700370}
371
Dan Sinclairf7435522018-02-05 22:27:22 +0000372void CJS_Global::CommitGlobalPersisitentVariables(CJS_Runtime* pRuntime) {
Tom Sepeza7757232017-04-18 11:10:39 -0700373 for (const auto& iter : m_MapGlobal) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400374 ByteString name = iter.first;
Tom Sepeza7757232017-04-18 11:10:39 -0700375 JSGlobalData* pData = iter.second.get();
Tom Sepez09d33bc2015-08-19 09:49:24 -0700376 if (pData->bDeleted) {
377 m_pGlobalData->DeleteGlobalVariable(name);
Tom Sepeza7757232017-04-18 11:10:39 -0700378 continue;
379 }
380 switch (pData->nType) {
381 case JS_GlobalDataType::NUMBER:
382 m_pGlobalData->SetGlobalVariableNumber(name, pData->dData);
383 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
384 break;
385 case JS_GlobalDataType::BOOLEAN:
386 m_pGlobalData->SetGlobalVariableBoolean(name, pData->bData);
387 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
388 break;
389 case JS_GlobalDataType::STRING:
390 m_pGlobalData->SetGlobalVariableString(name, pData->sData);
391 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
392 break;
393 case JS_GlobalDataType::OBJECT: {
394 CJS_GlobalVariableArray array;
Dan Sinclairf7435522018-02-05 22:27:22 +0000395 v8::Local<v8::Object> obj =
396 v8::Local<v8::Object>::New(GetIsolate(), pData->pData);
Lei Zhangb1a4db52018-07-11 13:02:54 +0000397 ObjectToArray(pRuntime, obj, &array);
Tom Sepeza7757232017-04-18 11:10:39 -0700398 m_pGlobalData->SetGlobalVariableObject(name, array);
399 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
400 } break;
401 case JS_GlobalDataType::NULLOBJ:
402 m_pGlobalData->SetGlobalVariableNull(name);
403 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
404 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700405 }
406 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700407}
408
Dan Sinclairf7435522018-02-05 22:27:22 +0000409void CJS_Global::ObjectToArray(CJS_Runtime* pRuntime,
410 v8::Local<v8::Object> pObj,
Lei Zhangb1a4db52018-07-11 13:02:54 +0000411 CJS_GlobalVariableArray* pArray) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400412 std::vector<WideString> pKeyList = pRuntime->GetObjectPropertyNames(pObj);
tsepezd0b6ed12016-08-11 19:50:57 -0700413 for (const auto& ws : pKeyList) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400414 ByteString sKey = ws.UTF8Encode();
tsepezb4694242016-08-15 16:44:55 -0700415 v8::Local<v8::Value> v = pRuntime->GetObjectProperty(pObj, ws);
Dan Sinclair3cac3602017-10-24 15:15:27 -0400416 if (v->IsNumber()) {
417 CJS_KeyValue* pObjElement = new CJS_KeyValue;
418 pObjElement->nType = JS_GlobalDataType::NUMBER;
419 pObjElement->sKey = sKey;
420 pObjElement->dData = pRuntime->ToDouble(v);
Lei Zhangb1a4db52018-07-11 13:02:54 +0000421 pArray->Add(pObjElement);
Dan Sinclair3cac3602017-10-24 15:15:27 -0400422 continue;
423 }
424 if (v->IsBoolean()) {
425 CJS_KeyValue* pObjElement = new CJS_KeyValue;
426 pObjElement->nType = JS_GlobalDataType::BOOLEAN;
427 pObjElement->sKey = sKey;
428 pObjElement->dData = pRuntime->ToBoolean(v);
Lei Zhangb1a4db52018-07-11 13:02:54 +0000429 pArray->Add(pObjElement);
Dan Sinclair3cac3602017-10-24 15:15:27 -0400430 continue;
431 }
432 if (v->IsString()) {
Tom Sepez34dab072018-08-08 17:49:02 +0000433 ByteString sValue = pRuntime->ToWideString(v).ToDefANSI();
Dan Sinclair3cac3602017-10-24 15:15:27 -0400434 CJS_KeyValue* pObjElement = new CJS_KeyValue;
435 pObjElement->nType = JS_GlobalDataType::STRING;
436 pObjElement->sKey = sKey;
437 pObjElement->sData = sValue;
Lei Zhangb1a4db52018-07-11 13:02:54 +0000438 pArray->Add(pObjElement);
Dan Sinclair3cac3602017-10-24 15:15:27 -0400439 continue;
440 }
441 if (v->IsObject()) {
442 CJS_KeyValue* pObjElement = new CJS_KeyValue;
443 pObjElement->nType = JS_GlobalDataType::OBJECT;
444 pObjElement->sKey = sKey;
Lei Zhangb1a4db52018-07-11 13:02:54 +0000445 ObjectToArray(pRuntime, pRuntime->ToObject(v), &pObjElement->objData);
446 pArray->Add(pObjElement);
Dan Sinclair3cac3602017-10-24 15:15:27 -0400447 continue;
448 }
449 if (v->IsNull()) {
450 CJS_KeyValue* pObjElement = new CJS_KeyValue;
451 pObjElement->nType = JS_GlobalDataType::NULLOBJ;
452 pObjElement->sKey = sKey;
Lei Zhangb1a4db52018-07-11 13:02:54 +0000453 pArray->Add(pObjElement);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700454 }
455 }
456}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700457
Dan Sinclairf7435522018-02-05 22:27:22 +0000458void CJS_Global::PutObjectProperty(v8::Local<v8::Object> pObj,
459 CJS_KeyValue* pData) {
Tom Sepez6ffd8402018-06-06 20:51:04 +0000460 CJS_Runtime* pRuntime = GetRuntime();
461 if (pRuntime)
462 return;
tsepezb4694242016-08-15 16:44:55 -0700463
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700464 for (int i = 0, sz = pData->objData.Count(); i < sz; i++) {
465 CJS_KeyValue* pObjData = pData->objData.GetAt(i);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700466 switch (pObjData->nType) {
weili47228ac2016-07-20 10:35:31 -0700467 case JS_GlobalDataType::NUMBER:
tsepeze6cf0132017-01-18 14:38:18 -0800468 pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
469 pRuntime->NewNumber(pObjData->dData));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700470 break;
weili47228ac2016-07-20 10:35:31 -0700471 case JS_GlobalDataType::BOOLEAN:
tsepeze6cf0132017-01-18 14:38:18 -0800472 pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
473 pRuntime->NewBoolean(pObjData->bData == 1));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700474 break;
weili47228ac2016-07-20 10:35:31 -0700475 case JS_GlobalDataType::STRING:
tsepeze6cf0132017-01-18 14:38:18 -0800476 pRuntime->PutObjectProperty(
477 pObj, pObjData->sKey.UTF8Decode(),
Ryan Harrison275e2602017-09-18 14:23:18 -0400478 pRuntime->NewString(pObjData->sData.UTF8Decode().AsStringView()));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700479 break;
weili47228ac2016-07-20 10:35:31 -0700480 case JS_GlobalDataType::OBJECT: {
Tom Sepez9ad9a5f2018-02-07 21:07:24 +0000481 v8::Local<v8::Object> pNewObj = pRuntime->NewObject();
Tom Sepez63b2fc72017-08-14 16:24:29 -0700482 if (!pNewObj.IsEmpty()) {
483 PutObjectProperty(pNewObj, pObjData);
484 pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
485 pNewObj);
486 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700487 } break;
weili47228ac2016-07-20 10:35:31 -0700488 case JS_GlobalDataType::NULLOBJ:
tsepeze6cf0132017-01-18 14:38:18 -0800489 pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
490 pRuntime->NewNull());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700491 break;
492 }
493 }
494}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700495
Dan Sinclairf7435522018-02-05 22:27:22 +0000496void CJS_Global::DestroyGlobalPersisitentVariables() {
Tom Sepeza7757232017-04-18 11:10:39 -0700497 m_MapGlobal.clear();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700498}
499
Tom Sepez3a6d0582018-08-17 19:28:52 +0000500CJS_Result CJS_Global::SetGlobalVariables(const ByteString& propname,
Dan Sinclairf7435522018-02-05 22:27:22 +0000501 JS_GlobalDataType nType,
502 double dData,
503 bool bData,
504 const ByteString& sData,
505 v8::Local<v8::Object> pData,
506 bool bDefaultPersistent) {
tsepezb4c9f3f2016-04-13 15:41:21 -0700507 if (propname.IsEmpty())
Tom Sepez3a6d0582018-08-17 19:28:52 +0000508 return CJS_Result::Failure(JSMessage::kUnknownProperty);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700509
Tom Sepeza7757232017-04-18 11:10:39 -0700510 auto it = m_MapGlobal.find(propname);
511 if (it != m_MapGlobal.end()) {
512 JSGlobalData* pTemp = it->second.get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700513 if (pTemp->bDeleted || pTemp->nType != nType) {
514 pTemp->dData = 0;
515 pTemp->bData = 0;
Lei Zhangfe2cd4d2017-11-22 20:04:12 +0000516 pTemp->sData.clear();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700517 pTemp->nType = nType;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700518 }
tsepez4cf55152016-11-02 14:37:54 -0700519 pTemp->bDeleted = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700520 switch (nType) {
Tom Sepeza7757232017-04-18 11:10:39 -0700521 case JS_GlobalDataType::NUMBER:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700522 pTemp->dData = dData;
Tom Sepeza7757232017-04-18 11:10:39 -0700523 break;
524 case JS_GlobalDataType::BOOLEAN:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700525 pTemp->bData = bData;
Tom Sepeza7757232017-04-18 11:10:39 -0700526 break;
527 case JS_GlobalDataType::STRING:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700528 pTemp->sData = sData;
Tom Sepeza7757232017-04-18 11:10:39 -0700529 break;
530 case JS_GlobalDataType::OBJECT:
Tom Sepez371379d2015-11-06 08:29:39 -0800531 pTemp->pData.Reset(pData->GetIsolate(), pData);
Tom Sepeza7757232017-04-18 11:10:39 -0700532 break;
weili47228ac2016-07-20 10:35:31 -0700533 case JS_GlobalDataType::NULLOBJ:
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700534 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700535 default:
Tom Sepez3a6d0582018-08-17 19:28:52 +0000536 return CJS_Result::Failure(JSMessage::kObjectTypeError);
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700537 }
Tom Sepez3a6d0582018-08-17 19:28:52 +0000538 return CJS_Result::Success();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700539 }
540
Tom Sepeza7757232017-04-18 11:10:39 -0700541 auto pNewData = pdfium::MakeUnique<JSGlobalData>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700542 switch (nType) {
Tom Sepeza7757232017-04-18 11:10:39 -0700543 case JS_GlobalDataType::NUMBER:
weili47228ac2016-07-20 10:35:31 -0700544 pNewData->nType = JS_GlobalDataType::NUMBER;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700545 pNewData->dData = dData;
546 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700547 break;
548 case JS_GlobalDataType::BOOLEAN:
weili47228ac2016-07-20 10:35:31 -0700549 pNewData->nType = JS_GlobalDataType::BOOLEAN;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700550 pNewData->bData = bData;
551 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700552 break;
553 case JS_GlobalDataType::STRING:
weili47228ac2016-07-20 10:35:31 -0700554 pNewData->nType = JS_GlobalDataType::STRING;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700555 pNewData->sData = sData;
556 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700557 break;
558 case JS_GlobalDataType::OBJECT:
weili47228ac2016-07-20 10:35:31 -0700559 pNewData->nType = JS_GlobalDataType::OBJECT;
Tom Sepez371379d2015-11-06 08:29:39 -0800560 pNewData->pData.Reset(pData->GetIsolate(), pData);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700561 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700562 break;
563 case JS_GlobalDataType::NULLOBJ:
weili47228ac2016-07-20 10:35:31 -0700564 pNewData->nType = JS_GlobalDataType::NULLOBJ;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700565 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700566 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700567 default:
Tom Sepez3a6d0582018-08-17 19:28:52 +0000568 return CJS_Result::Failure(JSMessage::kObjectTypeError);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700569 }
Tom Sepeza7757232017-04-18 11:10:39 -0700570 m_MapGlobal[propname] = std::move(pNewData);
Tom Sepez3a6d0582018-08-17 19:28:52 +0000571 return CJS_Result::Success();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700572}