xref: /aosp_15_r20/external/pdfium/fxjs/xfa/cjx_object.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2017 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker 
5*3ac0a46fSAndroid Build Coastguard Worker // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6*3ac0a46fSAndroid Build Coastguard Worker 
7*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cjx_object.h"
8*3ac0a46fSAndroid Build Coastguard Worker 
9*3ac0a46fSAndroid Build Coastguard Worker #include <set>
10*3ac0a46fSAndroid Build Coastguard Worker #include <tuple>
11*3ac0a46fSAndroid Build Coastguard Worker #include <utility>
12*3ac0a46fSAndroid Build Coastguard Worker 
13*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/fx_extension.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/fx_memory.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/xml/cfx_xmlelement.h"
16*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/xml/cfx_xmltext.h"
17*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/cjs_result.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/fxv8.h"
19*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/gc/container_trace.h"
20*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_engine.h"
21*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_mapmodule.h"
22*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cjx_boolean.h"
23*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cjx_draw.h"
24*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cjx_field.h"
25*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cjx_instancemanager.h"
26*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/check.h"
27*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/check_op.h"
28*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/containers/contains.h"
29*3ac0a46fSAndroid Build Coastguard Worker #include "v8/include/v8-forward.h"
30*3ac0a46fSAndroid Build Coastguard Worker #include "v8/include/v8-object.h"
31*3ac0a46fSAndroid Build Coastguard Worker #include "v8/include/v8-primitive.h"
32*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fgas/crt/cfgas_decimal.h"
33*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffnotify.h"
34*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffwidget.h"
35*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_border.h"
36*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_datavalue.h"
37*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_document.h"
38*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_edge.h"
39*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_fill.h"
40*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_font.h"
41*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_measurement.h"
42*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_node.h"
43*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_object.h"
44*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_occur.h"
45*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_proto.h"
46*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_subform.h"
47*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_validate.h"
48*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_value.h"
49*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/xfa_basic_data.h"
50*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/xfa_utils.h"
51*3ac0a46fSAndroid Build Coastguard Worker 
52*3ac0a46fSAndroid Build Coastguard Worker namespace {
53*3ac0a46fSAndroid Build Coastguard Worker 
54*3ac0a46fSAndroid Build Coastguard Worker enum XFA_KEYTYPE {
55*3ac0a46fSAndroid Build Coastguard Worker   XFA_KEYTYPE_Custom,
56*3ac0a46fSAndroid Build Coastguard Worker   XFA_KEYTYPE_Element,
57*3ac0a46fSAndroid Build Coastguard Worker };
58*3ac0a46fSAndroid Build Coastguard Worker 
GetMapKey_Custom(WideStringView wsKey)59*3ac0a46fSAndroid Build Coastguard Worker uint32_t GetMapKey_Custom(WideStringView wsKey) {
60*3ac0a46fSAndroid Build Coastguard Worker   uint32_t dwKey = FX_HashCode_GetW(wsKey);
61*3ac0a46fSAndroid Build Coastguard Worker   return ((dwKey << 1) | XFA_KEYTYPE_Custom);
62*3ac0a46fSAndroid Build Coastguard Worker }
63*3ac0a46fSAndroid Build Coastguard Worker 
GetMapKey_Element(XFA_Element eType,XFA_Attribute eAttribute)64*3ac0a46fSAndroid Build Coastguard Worker uint32_t GetMapKey_Element(XFA_Element eType, XFA_Attribute eAttribute) {
65*3ac0a46fSAndroid Build Coastguard Worker   return ((static_cast<uint32_t>(eType) << 16) |
66*3ac0a46fSAndroid Build Coastguard Worker           (static_cast<uint32_t>(eAttribute) << 8) | XFA_KEYTYPE_Element);
67*3ac0a46fSAndroid Build Coastguard Worker }
68*3ac0a46fSAndroid Build Coastguard Worker 
StrToRGB(const WideString & strRGB)69*3ac0a46fSAndroid Build Coastguard Worker std::tuple<int32_t, int32_t, int32_t> StrToRGB(const WideString& strRGB) {
70*3ac0a46fSAndroid Build Coastguard Worker   int32_t r = 0;
71*3ac0a46fSAndroid Build Coastguard Worker   int32_t g = 0;
72*3ac0a46fSAndroid Build Coastguard Worker   int32_t b = 0;
73*3ac0a46fSAndroid Build Coastguard Worker 
74*3ac0a46fSAndroid Build Coastguard Worker   size_t iIndex = 0;
75*3ac0a46fSAndroid Build Coastguard Worker   for (size_t i = 0; i < strRGB.GetLength(); ++i) {
76*3ac0a46fSAndroid Build Coastguard Worker     wchar_t ch = strRGB[i];
77*3ac0a46fSAndroid Build Coastguard Worker     if (ch == L',')
78*3ac0a46fSAndroid Build Coastguard Worker       ++iIndex;
79*3ac0a46fSAndroid Build Coastguard Worker     if (iIndex > 2)
80*3ac0a46fSAndroid Build Coastguard Worker       break;
81*3ac0a46fSAndroid Build Coastguard Worker 
82*3ac0a46fSAndroid Build Coastguard Worker     int32_t iValue = ch - L'0';
83*3ac0a46fSAndroid Build Coastguard Worker     if (iValue >= 0 && iValue <= 9) {
84*3ac0a46fSAndroid Build Coastguard Worker       switch (iIndex) {
85*3ac0a46fSAndroid Build Coastguard Worker         case 0:
86*3ac0a46fSAndroid Build Coastguard Worker           r = r * 10 + iValue;
87*3ac0a46fSAndroid Build Coastguard Worker           break;
88*3ac0a46fSAndroid Build Coastguard Worker         case 1:
89*3ac0a46fSAndroid Build Coastguard Worker           g = g * 10 + iValue;
90*3ac0a46fSAndroid Build Coastguard Worker           break;
91*3ac0a46fSAndroid Build Coastguard Worker         default:
92*3ac0a46fSAndroid Build Coastguard Worker           b = b * 10 + iValue;
93*3ac0a46fSAndroid Build Coastguard Worker           break;
94*3ac0a46fSAndroid Build Coastguard Worker       }
95*3ac0a46fSAndroid Build Coastguard Worker     }
96*3ac0a46fSAndroid Build Coastguard Worker   }
97*3ac0a46fSAndroid Build Coastguard Worker   return {r, g, b};
98*3ac0a46fSAndroid Build Coastguard Worker }
99*3ac0a46fSAndroid Build Coastguard Worker 
100*3ac0a46fSAndroid Build Coastguard Worker }  // namespace
101*3ac0a46fSAndroid Build Coastguard Worker 
CJX_Object(CXFA_Object * obj)102*3ac0a46fSAndroid Build Coastguard Worker CJX_Object::CJX_Object(CXFA_Object* obj) : object_(obj) {}
103*3ac0a46fSAndroid Build Coastguard Worker 
104*3ac0a46fSAndroid Build Coastguard Worker CJX_Object::~CJX_Object() = default;
105*3ac0a46fSAndroid Build Coastguard Worker 
AsCJXObject()106*3ac0a46fSAndroid Build Coastguard Worker CJX_Object* CJX_Object::AsCJXObject() {
107*3ac0a46fSAndroid Build Coastguard Worker   return this;
108*3ac0a46fSAndroid Build Coastguard Worker }
109*3ac0a46fSAndroid Build Coastguard Worker 
Trace(cppgc::Visitor * visitor) const110*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::Trace(cppgc::Visitor* visitor) const {
111*3ac0a46fSAndroid Build Coastguard Worker   visitor->Trace(object_);
112*3ac0a46fSAndroid Build Coastguard Worker   visitor->Trace(layout_item_);
113*3ac0a46fSAndroid Build Coastguard Worker   visitor->Trace(calc_data_);
114*3ac0a46fSAndroid Build Coastguard Worker }
115*3ac0a46fSAndroid Build Coastguard Worker 
DynamicTypeIs(TypeTag eType) const116*3ac0a46fSAndroid Build Coastguard Worker bool CJX_Object::DynamicTypeIs(TypeTag eType) const {
117*3ac0a46fSAndroid Build Coastguard Worker   return eType == static_type__;
118*3ac0a46fSAndroid Build Coastguard Worker }
119*3ac0a46fSAndroid Build Coastguard Worker 
DefineMethods(pdfium::span<const CJX_MethodSpec> methods)120*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::DefineMethods(pdfium::span<const CJX_MethodSpec> methods) {
121*3ac0a46fSAndroid Build Coastguard Worker   for (const auto& item : methods)
122*3ac0a46fSAndroid Build Coastguard Worker     method_specs_[item.pName] = item.pMethodCall;
123*3ac0a46fSAndroid Build Coastguard Worker }
124*3ac0a46fSAndroid Build Coastguard Worker 
GetDocument() const125*3ac0a46fSAndroid Build Coastguard Worker CXFA_Document* CJX_Object::GetDocument() const {
126*3ac0a46fSAndroid Build Coastguard Worker   return object_->GetDocument();
127*3ac0a46fSAndroid Build Coastguard Worker }
128*3ac0a46fSAndroid Build Coastguard Worker 
GetXFANode() const129*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* CJX_Object::GetXFANode() const {
130*3ac0a46fSAndroid Build Coastguard Worker   return ToNode(GetXFAObject());
131*3ac0a46fSAndroid Build Coastguard Worker }
132*3ac0a46fSAndroid Build Coastguard Worker 
className(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)133*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::className(v8::Isolate* pIsolate,
134*3ac0a46fSAndroid Build Coastguard Worker                            v8::Local<v8::Value>* pValue,
135*3ac0a46fSAndroid Build Coastguard Worker                            bool bSetting,
136*3ac0a46fSAndroid Build Coastguard Worker                            XFA_Attribute eAttribute) {
137*3ac0a46fSAndroid Build Coastguard Worker   if (bSetting) {
138*3ac0a46fSAndroid Build Coastguard Worker     ThrowInvalidPropertyException(pIsolate);
139*3ac0a46fSAndroid Build Coastguard Worker     return;
140*3ac0a46fSAndroid Build Coastguard Worker   }
141*3ac0a46fSAndroid Build Coastguard Worker   *pValue = fxv8::NewStringHelper(pIsolate, GetXFAObject()->GetClassName());
142*3ac0a46fSAndroid Build Coastguard Worker }
143*3ac0a46fSAndroid Build Coastguard Worker 
Subform_and_SubformSet_InstanceIndex()144*3ac0a46fSAndroid Build Coastguard Worker int32_t CJX_Object::Subform_and_SubformSet_InstanceIndex() {
145*3ac0a46fSAndroid Build Coastguard Worker   int32_t index = 0;
146*3ac0a46fSAndroid Build Coastguard Worker   for (CXFA_Node* pNode = GetXFANode()->GetPrevSibling(); pNode;
147*3ac0a46fSAndroid Build Coastguard Worker        pNode = pNode->GetPrevSibling()) {
148*3ac0a46fSAndroid Build Coastguard Worker     if ((pNode->GetElementType() != XFA_Element::Subform) &&
149*3ac0a46fSAndroid Build Coastguard Worker         (pNode->GetElementType() != XFA_Element::SubformSet)) {
150*3ac0a46fSAndroid Build Coastguard Worker       break;
151*3ac0a46fSAndroid Build Coastguard Worker     }
152*3ac0a46fSAndroid Build Coastguard Worker     index++;
153*3ac0a46fSAndroid Build Coastguard Worker   }
154*3ac0a46fSAndroid Build Coastguard Worker   return index;
155*3ac0a46fSAndroid Build Coastguard Worker }
156*3ac0a46fSAndroid Build Coastguard Worker 
HasMethod(const WideString & func) const157*3ac0a46fSAndroid Build Coastguard Worker bool CJX_Object::HasMethod(const WideString& func) const {
158*3ac0a46fSAndroid Build Coastguard Worker   return pdfium::Contains(method_specs_, func.ToUTF8());
159*3ac0a46fSAndroid Build Coastguard Worker }
160*3ac0a46fSAndroid Build Coastguard Worker 
RunMethod(CFXJSE_Engine * pScriptContext,const WideString & func,const std::vector<v8::Local<v8::Value>> & params)161*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_Object::RunMethod(
162*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* pScriptContext,
163*3ac0a46fSAndroid Build Coastguard Worker     const WideString& func,
164*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
165*3ac0a46fSAndroid Build Coastguard Worker   auto it = method_specs_.find(func.ToUTF8());
166*3ac0a46fSAndroid Build Coastguard Worker   if (it == method_specs_.end())
167*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kUnknownMethod);
168*3ac0a46fSAndroid Build Coastguard Worker 
169*3ac0a46fSAndroid Build Coastguard Worker   return it->second(this, pScriptContext, params);
170*3ac0a46fSAndroid Build Coastguard Worker }
171*3ac0a46fSAndroid Build Coastguard Worker 
ThrowTooManyOccurrencesException(v8::Isolate * pIsolate,const WideString & obj) const172*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ThrowTooManyOccurrencesException(v8::Isolate* pIsolate,
173*3ac0a46fSAndroid Build Coastguard Worker                                                   const WideString& obj) const {
174*3ac0a46fSAndroid Build Coastguard Worker   ThrowException(
175*3ac0a46fSAndroid Build Coastguard Worker       pIsolate, WideString::FromASCII("The element [") + obj +
176*3ac0a46fSAndroid Build Coastguard Worker                     WideString::FromASCII(
177*3ac0a46fSAndroid Build Coastguard Worker                         "] has violated its allowable number of occurrences."));
178*3ac0a46fSAndroid Build Coastguard Worker }
179*3ac0a46fSAndroid Build Coastguard Worker 
ThrowInvalidPropertyException(v8::Isolate * pIsolate) const180*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ThrowInvalidPropertyException(v8::Isolate* pIsolate) const {
181*3ac0a46fSAndroid Build Coastguard Worker   ThrowException(pIsolate,
182*3ac0a46fSAndroid Build Coastguard Worker                  WideString::FromASCII("Invalid property set operation."));
183*3ac0a46fSAndroid Build Coastguard Worker }
184*3ac0a46fSAndroid Build Coastguard Worker 
ThrowIndexOutOfBoundsException(v8::Isolate * pIsolate) const185*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ThrowIndexOutOfBoundsException(v8::Isolate* pIsolate) const {
186*3ac0a46fSAndroid Build Coastguard Worker   ThrowException(pIsolate,
187*3ac0a46fSAndroid Build Coastguard Worker                  WideString::FromASCII("Index value is out of bounds."));
188*3ac0a46fSAndroid Build Coastguard Worker }
189*3ac0a46fSAndroid Build Coastguard Worker 
ThrowParamCountMismatchException(v8::Isolate * pIsolate,const WideString & method) const190*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ThrowParamCountMismatchException(
191*3ac0a46fSAndroid Build Coastguard Worker     v8::Isolate* pIsolate,
192*3ac0a46fSAndroid Build Coastguard Worker     const WideString& method) const {
193*3ac0a46fSAndroid Build Coastguard Worker   ThrowException(
194*3ac0a46fSAndroid Build Coastguard Worker       pIsolate,
195*3ac0a46fSAndroid Build Coastguard Worker       WideString::FromASCII("Incorrect number of parameters calling method '") +
196*3ac0a46fSAndroid Build Coastguard Worker           method + WideString::FromASCII("'."));
197*3ac0a46fSAndroid Build Coastguard Worker }
198*3ac0a46fSAndroid Build Coastguard Worker 
ThrowArgumentMismatchException(v8::Isolate * pIsolate) const199*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ThrowArgumentMismatchException(v8::Isolate* pIsolate) const {
200*3ac0a46fSAndroid Build Coastguard Worker   ThrowException(pIsolate,
201*3ac0a46fSAndroid Build Coastguard Worker                  WideString::FromASCII(
202*3ac0a46fSAndroid Build Coastguard Worker                      "Argument mismatch in property or function argument."));
203*3ac0a46fSAndroid Build Coastguard Worker }
204*3ac0a46fSAndroid Build Coastguard Worker 
ThrowException(v8::Isolate * pIsolate,const WideString & str) const205*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ThrowException(v8::Isolate* pIsolate,
206*3ac0a46fSAndroid Build Coastguard Worker                                 const WideString& str) const {
207*3ac0a46fSAndroid Build Coastguard Worker   DCHECK(!str.IsEmpty());
208*3ac0a46fSAndroid Build Coastguard Worker   FXJSE_ThrowMessage(pIsolate, str.ToUTF8().AsStringView());
209*3ac0a46fSAndroid Build Coastguard Worker }
210*3ac0a46fSAndroid Build Coastguard Worker 
HasAttribute(XFA_Attribute eAttr) const211*3ac0a46fSAndroid Build Coastguard Worker bool CJX_Object::HasAttribute(XFA_Attribute eAttr) const {
212*3ac0a46fSAndroid Build Coastguard Worker   uint32_t key = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
213*3ac0a46fSAndroid Build Coastguard Worker   return HasMapModuleKey(key);
214*3ac0a46fSAndroid Build Coastguard Worker }
215*3ac0a46fSAndroid Build Coastguard Worker 
SetAttributeByEnum(XFA_Attribute eAttr,const WideString & wsValue,bool bNotify)216*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::SetAttributeByEnum(XFA_Attribute eAttr,
217*3ac0a46fSAndroid Build Coastguard Worker                                     const WideString& wsValue,
218*3ac0a46fSAndroid Build Coastguard Worker                                     bool bNotify) {
219*3ac0a46fSAndroid Build Coastguard Worker   switch (GetXFANode()->GetAttributeType(eAttr)) {
220*3ac0a46fSAndroid Build Coastguard Worker     case XFA_AttributeType::Enum: {
221*3ac0a46fSAndroid Build Coastguard Worker       absl::optional<XFA_AttributeValue> item =
222*3ac0a46fSAndroid Build Coastguard Worker           XFA_GetAttributeValueByName(wsValue.AsStringView());
223*3ac0a46fSAndroid Build Coastguard Worker       SetEnum(eAttr,
224*3ac0a46fSAndroid Build Coastguard Worker               item.has_value() ? item.value()
225*3ac0a46fSAndroid Build Coastguard Worker                                : GetXFANode()->GetDefaultEnum(eAttr).value(),
226*3ac0a46fSAndroid Build Coastguard Worker               bNotify);
227*3ac0a46fSAndroid Build Coastguard Worker       break;
228*3ac0a46fSAndroid Build Coastguard Worker     }
229*3ac0a46fSAndroid Build Coastguard Worker     case XFA_AttributeType::CData:
230*3ac0a46fSAndroid Build Coastguard Worker       SetCDataImpl(eAttr, WideString(wsValue), bNotify, false);
231*3ac0a46fSAndroid Build Coastguard Worker       break;
232*3ac0a46fSAndroid Build Coastguard Worker     case XFA_AttributeType::Boolean:
233*3ac0a46fSAndroid Build Coastguard Worker       SetBoolean(eAttr, !wsValue.EqualsASCII("0"), bNotify);
234*3ac0a46fSAndroid Build Coastguard Worker       break;
235*3ac0a46fSAndroid Build Coastguard Worker     case XFA_AttributeType::Integer:
236*3ac0a46fSAndroid Build Coastguard Worker       SetInteger(eAttr,
237*3ac0a46fSAndroid Build Coastguard Worker                  FXSYS_roundf(FXSYS_wcstof(wsValue.c_str(), wsValue.GetLength(),
238*3ac0a46fSAndroid Build Coastguard Worker                                            nullptr)),
239*3ac0a46fSAndroid Build Coastguard Worker                  bNotify);
240*3ac0a46fSAndroid Build Coastguard Worker       break;
241*3ac0a46fSAndroid Build Coastguard Worker     case XFA_AttributeType::Measure:
242*3ac0a46fSAndroid Build Coastguard Worker       SetMeasure(eAttr, CXFA_Measurement(wsValue.AsStringView()), bNotify);
243*3ac0a46fSAndroid Build Coastguard Worker       break;
244*3ac0a46fSAndroid Build Coastguard Worker   }
245*3ac0a46fSAndroid Build Coastguard Worker }
246*3ac0a46fSAndroid Build Coastguard Worker 
SetAttributeByString(WideStringView wsAttr,const WideString & wsValue)247*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::SetAttributeByString(WideStringView wsAttr,
248*3ac0a46fSAndroid Build Coastguard Worker                                       const WideString& wsValue) {
249*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<XFA_ATTRIBUTEINFO> attr = XFA_GetAttributeByName(wsAttr);
250*3ac0a46fSAndroid Build Coastguard Worker   if (attr.has_value()) {
251*3ac0a46fSAndroid Build Coastguard Worker     SetAttributeByEnum(attr.value().attribute, wsValue, true);
252*3ac0a46fSAndroid Build Coastguard Worker     return;
253*3ac0a46fSAndroid Build Coastguard Worker   }
254*3ac0a46fSAndroid Build Coastguard Worker   uint32_t key = GetMapKey_Custom(wsAttr);
255*3ac0a46fSAndroid Build Coastguard Worker   SetMapModuleString(key, wsValue);
256*3ac0a46fSAndroid Build Coastguard Worker }
257*3ac0a46fSAndroid Build Coastguard Worker 
GetAttributeByString(WideStringView attr) const258*3ac0a46fSAndroid Build Coastguard Worker WideString CJX_Object::GetAttributeByString(WideStringView attr) const {
259*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<WideString> result;
260*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<XFA_ATTRIBUTEINFO> enum_attr = XFA_GetAttributeByName(attr);
261*3ac0a46fSAndroid Build Coastguard Worker   if (enum_attr.has_value())
262*3ac0a46fSAndroid Build Coastguard Worker     result = TryAttribute(enum_attr.value().attribute, true);
263*3ac0a46fSAndroid Build Coastguard Worker   else
264*3ac0a46fSAndroid Build Coastguard Worker     result = GetMapModuleStringFollowingChain(GetMapKey_Custom(attr));
265*3ac0a46fSAndroid Build Coastguard Worker   return result.value_or(WideString());
266*3ac0a46fSAndroid Build Coastguard Worker }
267*3ac0a46fSAndroid Build Coastguard Worker 
GetAttributeByEnum(XFA_Attribute attr) const268*3ac0a46fSAndroid Build Coastguard Worker WideString CJX_Object::GetAttributeByEnum(XFA_Attribute attr) const {
269*3ac0a46fSAndroid Build Coastguard Worker   return TryAttribute(attr, true).value_or(WideString());
270*3ac0a46fSAndroid Build Coastguard Worker }
271*3ac0a46fSAndroid Build Coastguard Worker 
TryAttribute(XFA_Attribute eAttr,bool bUseDefault) const272*3ac0a46fSAndroid Build Coastguard Worker absl::optional<WideString> CJX_Object::TryAttribute(XFA_Attribute eAttr,
273*3ac0a46fSAndroid Build Coastguard Worker                                                     bool bUseDefault) const {
274*3ac0a46fSAndroid Build Coastguard Worker   switch (GetXFANode()->GetAttributeType(eAttr)) {
275*3ac0a46fSAndroid Build Coastguard Worker     case XFA_AttributeType::Enum: {
276*3ac0a46fSAndroid Build Coastguard Worker       absl::optional<XFA_AttributeValue> value = TryEnum(eAttr, bUseDefault);
277*3ac0a46fSAndroid Build Coastguard Worker       if (!value.has_value())
278*3ac0a46fSAndroid Build Coastguard Worker         return absl::nullopt;
279*3ac0a46fSAndroid Build Coastguard Worker       return WideString::FromASCII(XFA_AttributeValueToName(value.value()));
280*3ac0a46fSAndroid Build Coastguard Worker     }
281*3ac0a46fSAndroid Build Coastguard Worker     case XFA_AttributeType::CData:
282*3ac0a46fSAndroid Build Coastguard Worker       return TryCData(eAttr, bUseDefault);
283*3ac0a46fSAndroid Build Coastguard Worker 
284*3ac0a46fSAndroid Build Coastguard Worker     case XFA_AttributeType::Boolean: {
285*3ac0a46fSAndroid Build Coastguard Worker       absl::optional<bool> value = TryBoolean(eAttr, bUseDefault);
286*3ac0a46fSAndroid Build Coastguard Worker       if (!value.has_value())
287*3ac0a46fSAndroid Build Coastguard Worker         return absl::nullopt;
288*3ac0a46fSAndroid Build Coastguard Worker       return WideString(value.value() ? L"1" : L"0");
289*3ac0a46fSAndroid Build Coastguard Worker     }
290*3ac0a46fSAndroid Build Coastguard Worker     case XFA_AttributeType::Integer: {
291*3ac0a46fSAndroid Build Coastguard Worker       absl::optional<int32_t> iValue = TryInteger(eAttr, bUseDefault);
292*3ac0a46fSAndroid Build Coastguard Worker       if (!iValue.has_value())
293*3ac0a46fSAndroid Build Coastguard Worker         return absl::nullopt;
294*3ac0a46fSAndroid Build Coastguard Worker       return WideString::FormatInteger(iValue.value());
295*3ac0a46fSAndroid Build Coastguard Worker     }
296*3ac0a46fSAndroid Build Coastguard Worker     case XFA_AttributeType::Measure: {
297*3ac0a46fSAndroid Build Coastguard Worker       absl::optional<CXFA_Measurement> value = TryMeasure(eAttr, bUseDefault);
298*3ac0a46fSAndroid Build Coastguard Worker       if (!value.has_value())
299*3ac0a46fSAndroid Build Coastguard Worker         return absl::nullopt;
300*3ac0a46fSAndroid Build Coastguard Worker       return value->ToString();
301*3ac0a46fSAndroid Build Coastguard Worker     }
302*3ac0a46fSAndroid Build Coastguard Worker   }
303*3ac0a46fSAndroid Build Coastguard Worker   return absl::nullopt;
304*3ac0a46fSAndroid Build Coastguard Worker }
305*3ac0a46fSAndroid Build Coastguard Worker 
RemoveAttribute(WideStringView wsAttr)306*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::RemoveAttribute(WideStringView wsAttr) {
307*3ac0a46fSAndroid Build Coastguard Worker   RemoveMapModuleKey(GetMapKey_Custom(wsAttr));
308*3ac0a46fSAndroid Build Coastguard Worker }
309*3ac0a46fSAndroid Build Coastguard Worker 
TryBoolean(XFA_Attribute eAttr,bool bUseDefault) const310*3ac0a46fSAndroid Build Coastguard Worker absl::optional<bool> CJX_Object::TryBoolean(XFA_Attribute eAttr,
311*3ac0a46fSAndroid Build Coastguard Worker                                             bool bUseDefault) const {
312*3ac0a46fSAndroid Build Coastguard Worker   uint32_t key = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
313*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<int32_t> value = GetMapModuleValueFollowingChain(key);
314*3ac0a46fSAndroid Build Coastguard Worker   if (value.has_value())
315*3ac0a46fSAndroid Build Coastguard Worker     return !!value.value();
316*3ac0a46fSAndroid Build Coastguard Worker   if (!bUseDefault)
317*3ac0a46fSAndroid Build Coastguard Worker     return absl::nullopt;
318*3ac0a46fSAndroid Build Coastguard Worker   return GetXFANode()->GetDefaultBoolean(eAttr);
319*3ac0a46fSAndroid Build Coastguard Worker }
320*3ac0a46fSAndroid Build Coastguard Worker 
SetBoolean(XFA_Attribute eAttr,bool bValue,bool bNotify)321*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::SetBoolean(XFA_Attribute eAttr, bool bValue, bool bNotify) {
322*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLElement* elem = SetValue(eAttr, static_cast<int32_t>(bValue), bNotify);
323*3ac0a46fSAndroid Build Coastguard Worker   if (elem) {
324*3ac0a46fSAndroid Build Coastguard Worker     elem->SetAttribute(WideString::FromASCII(XFA_AttributeToName(eAttr)),
325*3ac0a46fSAndroid Build Coastguard Worker                        bValue ? L"1" : L"0");
326*3ac0a46fSAndroid Build Coastguard Worker   }
327*3ac0a46fSAndroid Build Coastguard Worker }
328*3ac0a46fSAndroid Build Coastguard Worker 
GetBoolean(XFA_Attribute eAttr) const329*3ac0a46fSAndroid Build Coastguard Worker bool CJX_Object::GetBoolean(XFA_Attribute eAttr) const {
330*3ac0a46fSAndroid Build Coastguard Worker   return TryBoolean(eAttr, true).value_or(false);
331*3ac0a46fSAndroid Build Coastguard Worker }
332*3ac0a46fSAndroid Build Coastguard Worker 
SetInteger(XFA_Attribute eAttr,int32_t iValue,bool bNotify)333*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::SetInteger(XFA_Attribute eAttr, int32_t iValue, bool bNotify) {
334*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLElement* elem = SetValue(eAttr, iValue, bNotify);
335*3ac0a46fSAndroid Build Coastguard Worker   if (elem) {
336*3ac0a46fSAndroid Build Coastguard Worker     elem->SetAttribute(WideString::FromASCII(XFA_AttributeToName(eAttr)),
337*3ac0a46fSAndroid Build Coastguard Worker                        WideString::FormatInteger(iValue));
338*3ac0a46fSAndroid Build Coastguard Worker   }
339*3ac0a46fSAndroid Build Coastguard Worker }
340*3ac0a46fSAndroid Build Coastguard Worker 
GetInteger(XFA_Attribute eAttr) const341*3ac0a46fSAndroid Build Coastguard Worker int32_t CJX_Object::GetInteger(XFA_Attribute eAttr) const {
342*3ac0a46fSAndroid Build Coastguard Worker   return TryInteger(eAttr, true).value_or(0);
343*3ac0a46fSAndroid Build Coastguard Worker }
344*3ac0a46fSAndroid Build Coastguard Worker 
TryInteger(XFA_Attribute eAttr,bool bUseDefault) const345*3ac0a46fSAndroid Build Coastguard Worker absl::optional<int32_t> CJX_Object::TryInteger(XFA_Attribute eAttr,
346*3ac0a46fSAndroid Build Coastguard Worker                                                bool bUseDefault) const {
347*3ac0a46fSAndroid Build Coastguard Worker   uint32_t key = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
348*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<int32_t> value = GetMapModuleValueFollowingChain(key);
349*3ac0a46fSAndroid Build Coastguard Worker   if (value.has_value())
350*3ac0a46fSAndroid Build Coastguard Worker     return value.value();
351*3ac0a46fSAndroid Build Coastguard Worker   if (!bUseDefault)
352*3ac0a46fSAndroid Build Coastguard Worker     return absl::nullopt;
353*3ac0a46fSAndroid Build Coastguard Worker   return GetXFANode()->GetDefaultInteger(eAttr);
354*3ac0a46fSAndroid Build Coastguard Worker }
355*3ac0a46fSAndroid Build Coastguard Worker 
TryEnum(XFA_Attribute eAttr,bool bUseDefault) const356*3ac0a46fSAndroid Build Coastguard Worker absl::optional<XFA_AttributeValue> CJX_Object::TryEnum(XFA_Attribute eAttr,
357*3ac0a46fSAndroid Build Coastguard Worker                                                        bool bUseDefault) const {
358*3ac0a46fSAndroid Build Coastguard Worker   uint32_t key = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
359*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<int32_t> value = GetMapModuleValueFollowingChain(key);
360*3ac0a46fSAndroid Build Coastguard Worker   if (value.has_value())
361*3ac0a46fSAndroid Build Coastguard Worker     return static_cast<XFA_AttributeValue>(value.value());
362*3ac0a46fSAndroid Build Coastguard Worker   if (!bUseDefault)
363*3ac0a46fSAndroid Build Coastguard Worker     return absl::nullopt;
364*3ac0a46fSAndroid Build Coastguard Worker   return GetXFANode()->GetDefaultEnum(eAttr);
365*3ac0a46fSAndroid Build Coastguard Worker }
366*3ac0a46fSAndroid Build Coastguard Worker 
SetEnum(XFA_Attribute eAttr,XFA_AttributeValue eValue,bool bNotify)367*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::SetEnum(XFA_Attribute eAttr,
368*3ac0a46fSAndroid Build Coastguard Worker                          XFA_AttributeValue eValue,
369*3ac0a46fSAndroid Build Coastguard Worker                          bool bNotify) {
370*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLElement* elem = SetValue(eAttr, static_cast<int32_t>(eValue), bNotify);
371*3ac0a46fSAndroid Build Coastguard Worker   if (elem) {
372*3ac0a46fSAndroid Build Coastguard Worker     elem->SetAttribute(WideString::FromASCII(XFA_AttributeToName(eAttr)),
373*3ac0a46fSAndroid Build Coastguard Worker                        WideString::FromASCII(XFA_AttributeValueToName(eValue)));
374*3ac0a46fSAndroid Build Coastguard Worker   }
375*3ac0a46fSAndroid Build Coastguard Worker }
376*3ac0a46fSAndroid Build Coastguard Worker 
GetEnum(XFA_Attribute eAttr) const377*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue CJX_Object::GetEnum(XFA_Attribute eAttr) const {
378*3ac0a46fSAndroid Build Coastguard Worker   return TryEnum(eAttr, true).value_or(XFA_AttributeValue::Unknown);
379*3ac0a46fSAndroid Build Coastguard Worker }
380*3ac0a46fSAndroid Build Coastguard Worker 
SetMeasure(XFA_Attribute eAttr,const CXFA_Measurement & mValue,bool bNotify)381*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::SetMeasure(XFA_Attribute eAttr,
382*3ac0a46fSAndroid Build Coastguard Worker                             const CXFA_Measurement& mValue,
383*3ac0a46fSAndroid Build Coastguard Worker                             bool bNotify) {
384*3ac0a46fSAndroid Build Coastguard Worker   // Can't short-circuit update here when the value is the same since it
385*3ac0a46fSAndroid Build Coastguard Worker   // might have come from further up the chain from where we are setting it.
386*3ac0a46fSAndroid Build Coastguard Worker   uint32_t key = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
387*3ac0a46fSAndroid Build Coastguard Worker   if (bNotify)
388*3ac0a46fSAndroid Build Coastguard Worker     OnChanging(eAttr);
389*3ac0a46fSAndroid Build Coastguard Worker   SetMapModuleMeasurement(key, mValue);
390*3ac0a46fSAndroid Build Coastguard Worker   if (bNotify)
391*3ac0a46fSAndroid Build Coastguard Worker     OnChanged(eAttr, false);
392*3ac0a46fSAndroid Build Coastguard Worker }
393*3ac0a46fSAndroid Build Coastguard Worker 
TryMeasure(XFA_Attribute eAttr,bool bUseDefault) const394*3ac0a46fSAndroid Build Coastguard Worker absl::optional<CXFA_Measurement> CJX_Object::TryMeasure(
395*3ac0a46fSAndroid Build Coastguard Worker     XFA_Attribute eAttr,
396*3ac0a46fSAndroid Build Coastguard Worker     bool bUseDefault) const {
397*3ac0a46fSAndroid Build Coastguard Worker   uint32_t key = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
398*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<CXFA_Measurement> result =
399*3ac0a46fSAndroid Build Coastguard Worker       GetMapModuleMeasurementFollowingChain(key);
400*3ac0a46fSAndroid Build Coastguard Worker   if (result.has_value())
401*3ac0a46fSAndroid Build Coastguard Worker     return result.value();
402*3ac0a46fSAndroid Build Coastguard Worker   if (!bUseDefault)
403*3ac0a46fSAndroid Build Coastguard Worker     return absl::nullopt;
404*3ac0a46fSAndroid Build Coastguard Worker   return GetXFANode()->GetDefaultMeasurement(eAttr);
405*3ac0a46fSAndroid Build Coastguard Worker }
406*3ac0a46fSAndroid Build Coastguard Worker 
TryMeasureAsFloat(XFA_Attribute attr) const407*3ac0a46fSAndroid Build Coastguard Worker absl::optional<float> CJX_Object::TryMeasureAsFloat(XFA_Attribute attr) const {
408*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<CXFA_Measurement> measure = TryMeasure(attr, false);
409*3ac0a46fSAndroid Build Coastguard Worker   if (!measure.has_value())
410*3ac0a46fSAndroid Build Coastguard Worker     return absl::nullopt;
411*3ac0a46fSAndroid Build Coastguard Worker   return measure->ToUnit(XFA_Unit::Pt);
412*3ac0a46fSAndroid Build Coastguard Worker }
413*3ac0a46fSAndroid Build Coastguard Worker 
GetMeasure(XFA_Attribute eAttr) const414*3ac0a46fSAndroid Build Coastguard Worker CXFA_Measurement CJX_Object::GetMeasure(XFA_Attribute eAttr) const {
415*3ac0a46fSAndroid Build Coastguard Worker   return TryMeasure(eAttr, true).value_or(CXFA_Measurement());
416*3ac0a46fSAndroid Build Coastguard Worker }
417*3ac0a46fSAndroid Build Coastguard Worker 
GetMeasureInUnit(XFA_Attribute eAttr,XFA_Unit unit) const418*3ac0a46fSAndroid Build Coastguard Worker float CJX_Object::GetMeasureInUnit(XFA_Attribute eAttr, XFA_Unit unit) const {
419*3ac0a46fSAndroid Build Coastguard Worker   return GetMeasure(eAttr).ToUnit(unit);
420*3ac0a46fSAndroid Build Coastguard Worker }
421*3ac0a46fSAndroid Build Coastguard Worker 
GetCData(XFA_Attribute eAttr) const422*3ac0a46fSAndroid Build Coastguard Worker WideString CJX_Object::GetCData(XFA_Attribute eAttr) const {
423*3ac0a46fSAndroid Build Coastguard Worker   return TryCData(eAttr, true).value_or(WideString());
424*3ac0a46fSAndroid Build Coastguard Worker }
425*3ac0a46fSAndroid Build Coastguard Worker 
SetCData(XFA_Attribute eAttr,const WideString & wsValue)426*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::SetCData(XFA_Attribute eAttr, const WideString& wsValue) {
427*3ac0a46fSAndroid Build Coastguard Worker   return SetCDataImpl(eAttr, wsValue, false, false);
428*3ac0a46fSAndroid Build Coastguard Worker }
429*3ac0a46fSAndroid Build Coastguard Worker 
SetCDataImpl(XFA_Attribute eAttr,const WideString & wsValue,bool bNotify,bool bScriptModify)430*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::SetCDataImpl(XFA_Attribute eAttr,
431*3ac0a46fSAndroid Build Coastguard Worker                               const WideString& wsValue,
432*3ac0a46fSAndroid Build Coastguard Worker                               bool bNotify,
433*3ac0a46fSAndroid Build Coastguard Worker                               bool bScriptModify) {
434*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* xfaObj = GetXFANode();
435*3ac0a46fSAndroid Build Coastguard Worker   uint32_t key = GetMapKey_Element(xfaObj->GetElementType(), eAttr);
436*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<WideString> old_value = GetMapModuleString(key);
437*3ac0a46fSAndroid Build Coastguard Worker   if (!old_value.has_value() || old_value.value() != wsValue) {
438*3ac0a46fSAndroid Build Coastguard Worker     if (bNotify)
439*3ac0a46fSAndroid Build Coastguard Worker       OnChanging(eAttr);
440*3ac0a46fSAndroid Build Coastguard Worker     SetMapModuleString(key, wsValue);
441*3ac0a46fSAndroid Build Coastguard Worker     if (eAttr == XFA_Attribute::Name)
442*3ac0a46fSAndroid Build Coastguard Worker       xfaObj->UpdateNameHash();
443*3ac0a46fSAndroid Build Coastguard Worker     if (bNotify)
444*3ac0a46fSAndroid Build Coastguard Worker       OnChanged(eAttr, bScriptModify);
445*3ac0a46fSAndroid Build Coastguard Worker   }
446*3ac0a46fSAndroid Build Coastguard Worker 
447*3ac0a46fSAndroid Build Coastguard Worker   if (!xfaObj->IsNeedSavingXMLNode() || eAttr == XFA_Attribute::QualifiedName ||
448*3ac0a46fSAndroid Build Coastguard Worker       eAttr == XFA_Attribute::BindingNode) {
449*3ac0a46fSAndroid Build Coastguard Worker     return;
450*3ac0a46fSAndroid Build Coastguard Worker   }
451*3ac0a46fSAndroid Build Coastguard Worker 
452*3ac0a46fSAndroid Build Coastguard Worker   if (eAttr == XFA_Attribute::Name &&
453*3ac0a46fSAndroid Build Coastguard Worker       (xfaObj->GetElementType() == XFA_Element::DataValue ||
454*3ac0a46fSAndroid Build Coastguard Worker        xfaObj->GetElementType() == XFA_Element::DataGroup)) {
455*3ac0a46fSAndroid Build Coastguard Worker     return;
456*3ac0a46fSAndroid Build Coastguard Worker   }
457*3ac0a46fSAndroid Build Coastguard Worker 
458*3ac0a46fSAndroid Build Coastguard Worker   if (eAttr == XFA_Attribute::Value) {
459*3ac0a46fSAndroid Build Coastguard Worker     xfaObj->SetToXML(wsValue);
460*3ac0a46fSAndroid Build Coastguard Worker     return;
461*3ac0a46fSAndroid Build Coastguard Worker   }
462*3ac0a46fSAndroid Build Coastguard Worker 
463*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLElement* elem = ToXMLElement(xfaObj->GetXMLMappingNode());
464*3ac0a46fSAndroid Build Coastguard Worker   if (!elem) {
465*3ac0a46fSAndroid Build Coastguard Worker     return;
466*3ac0a46fSAndroid Build Coastguard Worker   }
467*3ac0a46fSAndroid Build Coastguard Worker 
468*3ac0a46fSAndroid Build Coastguard Worker   WideString wsAttrName = WideString::FromASCII(XFA_AttributeToName(eAttr));
469*3ac0a46fSAndroid Build Coastguard Worker   if (eAttr == XFA_Attribute::ContentType)
470*3ac0a46fSAndroid Build Coastguard Worker     wsAttrName = L"xfa:" + wsAttrName;
471*3ac0a46fSAndroid Build Coastguard Worker   elem->SetAttribute(wsAttrName, wsValue);
472*3ac0a46fSAndroid Build Coastguard Worker }
473*3ac0a46fSAndroid Build Coastguard Worker 
SetAttributeValue(const WideString & wsValue,const WideString & wsXMLValue)474*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::SetAttributeValue(const WideString& wsValue,
475*3ac0a46fSAndroid Build Coastguard Worker                                    const WideString& wsXMLValue) {
476*3ac0a46fSAndroid Build Coastguard Worker   SetAttributeValueImpl(wsValue, wsXMLValue, false, false);
477*3ac0a46fSAndroid Build Coastguard Worker }
478*3ac0a46fSAndroid Build Coastguard Worker 
SetAttributeValueImpl(const WideString & wsValue,const WideString & wsXMLValue,bool bNotify,bool bScriptModify)479*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::SetAttributeValueImpl(const WideString& wsValue,
480*3ac0a46fSAndroid Build Coastguard Worker                                        const WideString& wsXMLValue,
481*3ac0a46fSAndroid Build Coastguard Worker                                        bool bNotify,
482*3ac0a46fSAndroid Build Coastguard Worker                                        bool bScriptModify) {
483*3ac0a46fSAndroid Build Coastguard Worker   auto* xfaObj = GetXFANode();
484*3ac0a46fSAndroid Build Coastguard Worker   uint32_t key =
485*3ac0a46fSAndroid Build Coastguard Worker       GetMapKey_Element(xfaObj->GetElementType(), XFA_Attribute::Value);
486*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<WideString> old_value = GetMapModuleString(key);
487*3ac0a46fSAndroid Build Coastguard Worker   if (!old_value.has_value() || old_value.value() != wsValue) {
488*3ac0a46fSAndroid Build Coastguard Worker     if (bNotify)
489*3ac0a46fSAndroid Build Coastguard Worker       OnChanging(XFA_Attribute::Value);
490*3ac0a46fSAndroid Build Coastguard Worker     SetMapModuleString(key, wsValue);
491*3ac0a46fSAndroid Build Coastguard Worker     if (bNotify)
492*3ac0a46fSAndroid Build Coastguard Worker       OnChanged(XFA_Attribute::Value, bScriptModify);
493*3ac0a46fSAndroid Build Coastguard Worker     if (xfaObj->IsNeedSavingXMLNode())
494*3ac0a46fSAndroid Build Coastguard Worker       xfaObj->SetToXML(wsXMLValue);
495*3ac0a46fSAndroid Build Coastguard Worker   }
496*3ac0a46fSAndroid Build Coastguard Worker }
497*3ac0a46fSAndroid Build Coastguard Worker 
TryCData(XFA_Attribute eAttr,bool bUseDefault) const498*3ac0a46fSAndroid Build Coastguard Worker absl::optional<WideString> CJX_Object::TryCData(XFA_Attribute eAttr,
499*3ac0a46fSAndroid Build Coastguard Worker                                                 bool bUseDefault) const {
500*3ac0a46fSAndroid Build Coastguard Worker   uint32_t key = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
501*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<WideString> value = GetMapModuleStringFollowingChain(key);
502*3ac0a46fSAndroid Build Coastguard Worker   if (value.has_value())
503*3ac0a46fSAndroid Build Coastguard Worker     return value;
504*3ac0a46fSAndroid Build Coastguard Worker 
505*3ac0a46fSAndroid Build Coastguard Worker   if (!bUseDefault)
506*3ac0a46fSAndroid Build Coastguard Worker     return absl::nullopt;
507*3ac0a46fSAndroid Build Coastguard Worker 
508*3ac0a46fSAndroid Build Coastguard Worker   return GetXFANode()->GetDefaultCData(eAttr);
509*3ac0a46fSAndroid Build Coastguard Worker }
510*3ac0a46fSAndroid Build Coastguard Worker 
SetValue(XFA_Attribute eAttr,int32_t value,bool bNotify)511*3ac0a46fSAndroid Build Coastguard Worker CFX_XMLElement* CJX_Object::SetValue(XFA_Attribute eAttr,
512*3ac0a46fSAndroid Build Coastguard Worker                                      int32_t value,
513*3ac0a46fSAndroid Build Coastguard Worker                                      bool bNotify) {
514*3ac0a46fSAndroid Build Coastguard Worker   uint32_t key = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
515*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<int32_t> old_value = GetMapModuleValue(key);
516*3ac0a46fSAndroid Build Coastguard Worker   if (!old_value.has_value() || old_value.value() != value) {
517*3ac0a46fSAndroid Build Coastguard Worker     if (bNotify)
518*3ac0a46fSAndroid Build Coastguard Worker       OnChanging(eAttr);
519*3ac0a46fSAndroid Build Coastguard Worker     SetMapModuleValue(key, value);
520*3ac0a46fSAndroid Build Coastguard Worker     if (bNotify)
521*3ac0a46fSAndroid Build Coastguard Worker       OnChanged(eAttr, false);
522*3ac0a46fSAndroid Build Coastguard Worker   }
523*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pNode = GetXFANode();
524*3ac0a46fSAndroid Build Coastguard Worker   return pNode->IsNeedSavingXMLNode() ? ToXMLElement(pNode->GetXMLMappingNode())
525*3ac0a46fSAndroid Build Coastguard Worker                                       : nullptr;
526*3ac0a46fSAndroid Build Coastguard Worker }
527*3ac0a46fSAndroid Build Coastguard Worker 
SetContent(const WideString & wsContent,const WideString & wsXMLValue,bool bNotify,bool bScriptModify,bool bSyncData)528*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::SetContent(const WideString& wsContent,
529*3ac0a46fSAndroid Build Coastguard Worker                             const WideString& wsXMLValue,
530*3ac0a46fSAndroid Build Coastguard Worker                             bool bNotify,
531*3ac0a46fSAndroid Build Coastguard Worker                             bool bScriptModify,
532*3ac0a46fSAndroid Build Coastguard Worker                             bool bSyncData) {
533*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pNode = nullptr;
534*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pBindNode = nullptr;
535*3ac0a46fSAndroid Build Coastguard Worker   switch (GetXFANode()->GetObjectType()) {
536*3ac0a46fSAndroid Build Coastguard Worker     case XFA_ObjectType::ContainerNode: {
537*3ac0a46fSAndroid Build Coastguard Worker       if (XFA_FieldIsMultiListBox(GetXFANode())) {
538*3ac0a46fSAndroid Build Coastguard Worker         CXFA_Value* pValue =
539*3ac0a46fSAndroid Build Coastguard Worker             GetOrCreateProperty<CXFA_Value>(0, XFA_Element::Value);
540*3ac0a46fSAndroid Build Coastguard Worker         if (!pValue)
541*3ac0a46fSAndroid Build Coastguard Worker           break;
542*3ac0a46fSAndroid Build Coastguard Worker 
543*3ac0a46fSAndroid Build Coastguard Worker         CXFA_Node* pChildValue = pValue->GetFirstChild();
544*3ac0a46fSAndroid Build Coastguard Worker         pChildValue->JSObject()->SetCData(XFA_Attribute::ContentType,
545*3ac0a46fSAndroid Build Coastguard Worker                                           L"text/xml");
546*3ac0a46fSAndroid Build Coastguard Worker         pChildValue->JSObject()->SetContent(wsContent, wsContent, bNotify,
547*3ac0a46fSAndroid Build Coastguard Worker                                             bScriptModify, false);
548*3ac0a46fSAndroid Build Coastguard Worker 
549*3ac0a46fSAndroid Build Coastguard Worker         CXFA_Node* pBind = GetXFANode()->GetBindData();
550*3ac0a46fSAndroid Build Coastguard Worker         if (bSyncData && pBind) {
551*3ac0a46fSAndroid Build Coastguard Worker           std::vector<WideString> wsSaveTextArray =
552*3ac0a46fSAndroid Build Coastguard Worker               fxcrt::Split(wsContent, L'\n');
553*3ac0a46fSAndroid Build Coastguard Worker           std::vector<CXFA_Node*> valueNodes =
554*3ac0a46fSAndroid Build Coastguard Worker               pBind->GetNodeListForType(XFA_Element::DataValue);
555*3ac0a46fSAndroid Build Coastguard Worker 
556*3ac0a46fSAndroid Build Coastguard Worker           // Adusting node count might have side effects, do not trust that
557*3ac0a46fSAndroid Build Coastguard Worker           // we'll ever actually get there.
558*3ac0a46fSAndroid Build Coastguard Worker           size_t tries = 0;
559*3ac0a46fSAndroid Build Coastguard Worker           while (valueNodes.size() != wsSaveTextArray.size()) {
560*3ac0a46fSAndroid Build Coastguard Worker             if (++tries > 4)
561*3ac0a46fSAndroid Build Coastguard Worker               return;
562*3ac0a46fSAndroid Build Coastguard Worker             if (valueNodes.size() < wsSaveTextArray.size()) {
563*3ac0a46fSAndroid Build Coastguard Worker               size_t iAddNodes = wsSaveTextArray.size() - valueNodes.size();
564*3ac0a46fSAndroid Build Coastguard Worker               while (iAddNodes-- > 0) {
565*3ac0a46fSAndroid Build Coastguard Worker                 CXFA_Node* pValueNodes =
566*3ac0a46fSAndroid Build Coastguard Worker                     pBind->CreateSamePacketNode(XFA_Element::DataValue);
567*3ac0a46fSAndroid Build Coastguard Worker                 pValueNodes->JSObject()->SetCData(XFA_Attribute::Name,
568*3ac0a46fSAndroid Build Coastguard Worker                                                   L"value");
569*3ac0a46fSAndroid Build Coastguard Worker                 pValueNodes->CreateXMLMappingNode();
570*3ac0a46fSAndroid Build Coastguard Worker                 pBind->InsertChildAndNotify(pValueNodes, nullptr);
571*3ac0a46fSAndroid Build Coastguard Worker               }
572*3ac0a46fSAndroid Build Coastguard Worker             } else {
573*3ac0a46fSAndroid Build Coastguard Worker               size_t iDelNodes = valueNodes.size() - wsSaveTextArray.size();
574*3ac0a46fSAndroid Build Coastguard Worker               for (size_t i = 0; i < iDelNodes; ++i)
575*3ac0a46fSAndroid Build Coastguard Worker                 pBind->RemoveChildAndNotify(valueNodes[i], true);
576*3ac0a46fSAndroid Build Coastguard Worker             }
577*3ac0a46fSAndroid Build Coastguard Worker             valueNodes = pBind->GetNodeListForType(XFA_Element::DataValue);
578*3ac0a46fSAndroid Build Coastguard Worker           }
579*3ac0a46fSAndroid Build Coastguard Worker           DCHECK_EQ(valueNodes.size(), wsSaveTextArray.size());
580*3ac0a46fSAndroid Build Coastguard Worker           size_t i = 0;
581*3ac0a46fSAndroid Build Coastguard Worker           for (CXFA_Node* pValueNode : valueNodes) {
582*3ac0a46fSAndroid Build Coastguard Worker             pValueNode->JSObject()->SetAttributeValue(wsSaveTextArray[i],
583*3ac0a46fSAndroid Build Coastguard Worker                                                       wsSaveTextArray[i]);
584*3ac0a46fSAndroid Build Coastguard Worker             i++;
585*3ac0a46fSAndroid Build Coastguard Worker           }
586*3ac0a46fSAndroid Build Coastguard Worker           for (auto* pArrayNode : pBind->GetBindItemsCopy()) {
587*3ac0a46fSAndroid Build Coastguard Worker             if (pArrayNode != GetXFANode()) {
588*3ac0a46fSAndroid Build Coastguard Worker               pArrayNode->JSObject()->SetContent(wsContent, wsContent, bNotify,
589*3ac0a46fSAndroid Build Coastguard Worker                                                  bScriptModify, false);
590*3ac0a46fSAndroid Build Coastguard Worker             }
591*3ac0a46fSAndroid Build Coastguard Worker           }
592*3ac0a46fSAndroid Build Coastguard Worker         }
593*3ac0a46fSAndroid Build Coastguard Worker         break;
594*3ac0a46fSAndroid Build Coastguard Worker       }
595*3ac0a46fSAndroid Build Coastguard Worker       if (GetXFANode()->GetElementType() == XFA_Element::ExclGroup) {
596*3ac0a46fSAndroid Build Coastguard Worker         pNode = GetXFANode();
597*3ac0a46fSAndroid Build Coastguard Worker       } else {
598*3ac0a46fSAndroid Build Coastguard Worker         CXFA_Value* pValue =
599*3ac0a46fSAndroid Build Coastguard Worker             GetOrCreateProperty<CXFA_Value>(0, XFA_Element::Value);
600*3ac0a46fSAndroid Build Coastguard Worker         if (!pValue)
601*3ac0a46fSAndroid Build Coastguard Worker           break;
602*3ac0a46fSAndroid Build Coastguard Worker 
603*3ac0a46fSAndroid Build Coastguard Worker         CXFA_Node* pChildValue = pValue->GetFirstChild();
604*3ac0a46fSAndroid Build Coastguard Worker         if (pChildValue) {
605*3ac0a46fSAndroid Build Coastguard Worker           pChildValue->JSObject()->SetContent(wsContent, wsContent, bNotify,
606*3ac0a46fSAndroid Build Coastguard Worker                                               bScriptModify, false);
607*3ac0a46fSAndroid Build Coastguard Worker         }
608*3ac0a46fSAndroid Build Coastguard Worker       }
609*3ac0a46fSAndroid Build Coastguard Worker       pBindNode = GetXFANode()->GetBindData();
610*3ac0a46fSAndroid Build Coastguard Worker       if (pBindNode && bSyncData) {
611*3ac0a46fSAndroid Build Coastguard Worker         pBindNode->JSObject()->SetContent(wsContent, wsXMLValue, bNotify,
612*3ac0a46fSAndroid Build Coastguard Worker                                           bScriptModify, false);
613*3ac0a46fSAndroid Build Coastguard Worker         for (auto* pArrayNode : pBindNode->GetBindItemsCopy()) {
614*3ac0a46fSAndroid Build Coastguard Worker           if (pArrayNode != GetXFANode()) {
615*3ac0a46fSAndroid Build Coastguard Worker             pArrayNode->JSObject()->SetContent(wsContent, wsContent, bNotify,
616*3ac0a46fSAndroid Build Coastguard Worker                                                true, false);
617*3ac0a46fSAndroid Build Coastguard Worker           }
618*3ac0a46fSAndroid Build Coastguard Worker         }
619*3ac0a46fSAndroid Build Coastguard Worker       }
620*3ac0a46fSAndroid Build Coastguard Worker       pBindNode = nullptr;
621*3ac0a46fSAndroid Build Coastguard Worker       break;
622*3ac0a46fSAndroid Build Coastguard Worker     }
623*3ac0a46fSAndroid Build Coastguard Worker     case XFA_ObjectType::ContentNode: {
624*3ac0a46fSAndroid Build Coastguard Worker       WideString wsContentType;
625*3ac0a46fSAndroid Build Coastguard Worker       if (GetXFANode()->GetElementType() == XFA_Element::ExData) {
626*3ac0a46fSAndroid Build Coastguard Worker         absl::optional<WideString> ret =
627*3ac0a46fSAndroid Build Coastguard Worker             TryAttribute(XFA_Attribute::ContentType, false);
628*3ac0a46fSAndroid Build Coastguard Worker         if (ret.has_value())
629*3ac0a46fSAndroid Build Coastguard Worker           wsContentType = ret.value();
630*3ac0a46fSAndroid Build Coastguard Worker         if (wsContentType.EqualsASCII("text/html")) {
631*3ac0a46fSAndroid Build Coastguard Worker           wsContentType.clear();
632*3ac0a46fSAndroid Build Coastguard Worker           SetAttributeByEnum(XFA_Attribute::ContentType, wsContentType, false);
633*3ac0a46fSAndroid Build Coastguard Worker         }
634*3ac0a46fSAndroid Build Coastguard Worker       }
635*3ac0a46fSAndroid Build Coastguard Worker 
636*3ac0a46fSAndroid Build Coastguard Worker       CXFA_Node* pContentRawDataNode = GetXFANode()->GetFirstChild();
637*3ac0a46fSAndroid Build Coastguard Worker       if (!pContentRawDataNode) {
638*3ac0a46fSAndroid Build Coastguard Worker         pContentRawDataNode = GetXFANode()->CreateSamePacketNode(
639*3ac0a46fSAndroid Build Coastguard Worker             wsContentType.EqualsASCII("text/xml") ? XFA_Element::Sharpxml
640*3ac0a46fSAndroid Build Coastguard Worker                                                   : XFA_Element::Sharptext);
641*3ac0a46fSAndroid Build Coastguard Worker         GetXFANode()->InsertChildAndNotify(pContentRawDataNode, nullptr);
642*3ac0a46fSAndroid Build Coastguard Worker       }
643*3ac0a46fSAndroid Build Coastguard Worker       pContentRawDataNode->JSObject()->SetContent(
644*3ac0a46fSAndroid Build Coastguard Worker           wsContent, wsXMLValue, bNotify, bScriptModify, bSyncData);
645*3ac0a46fSAndroid Build Coastguard Worker       return;
646*3ac0a46fSAndroid Build Coastguard Worker     }
647*3ac0a46fSAndroid Build Coastguard Worker     case XFA_ObjectType::NodeC:
648*3ac0a46fSAndroid Build Coastguard Worker     case XFA_ObjectType::TextNode:
649*3ac0a46fSAndroid Build Coastguard Worker       pNode = GetXFANode();
650*3ac0a46fSAndroid Build Coastguard Worker       break;
651*3ac0a46fSAndroid Build Coastguard Worker     case XFA_ObjectType::NodeV:
652*3ac0a46fSAndroid Build Coastguard Worker       pNode = GetXFANode();
653*3ac0a46fSAndroid Build Coastguard Worker       if (bSyncData && GetXFANode()->GetPacketType() == XFA_PacketType::Form) {
654*3ac0a46fSAndroid Build Coastguard Worker         CXFA_Node* pParent = GetXFANode()->GetParent();
655*3ac0a46fSAndroid Build Coastguard Worker         if (pParent) {
656*3ac0a46fSAndroid Build Coastguard Worker           pParent = pParent->GetParent();
657*3ac0a46fSAndroid Build Coastguard Worker         }
658*3ac0a46fSAndroid Build Coastguard Worker         if (pParent && pParent->GetElementType() == XFA_Element::Value) {
659*3ac0a46fSAndroid Build Coastguard Worker           pParent = pParent->GetParent();
660*3ac0a46fSAndroid Build Coastguard Worker           if (pParent && pParent->IsContainerNode()) {
661*3ac0a46fSAndroid Build Coastguard Worker             pBindNode = pParent->GetBindData();
662*3ac0a46fSAndroid Build Coastguard Worker             if (pBindNode) {
663*3ac0a46fSAndroid Build Coastguard Worker               pBindNode->JSObject()->SetContent(wsContent, wsXMLValue, bNotify,
664*3ac0a46fSAndroid Build Coastguard Worker                                                 bScriptModify, false);
665*3ac0a46fSAndroid Build Coastguard Worker             }
666*3ac0a46fSAndroid Build Coastguard Worker           }
667*3ac0a46fSAndroid Build Coastguard Worker         }
668*3ac0a46fSAndroid Build Coastguard Worker       }
669*3ac0a46fSAndroid Build Coastguard Worker       break;
670*3ac0a46fSAndroid Build Coastguard Worker     default:
671*3ac0a46fSAndroid Build Coastguard Worker       if (GetXFANode()->GetElementType() == XFA_Element::DataValue) {
672*3ac0a46fSAndroid Build Coastguard Worker         pNode = GetXFANode();
673*3ac0a46fSAndroid Build Coastguard Worker         pBindNode = GetXFANode();
674*3ac0a46fSAndroid Build Coastguard Worker       }
675*3ac0a46fSAndroid Build Coastguard Worker       break;
676*3ac0a46fSAndroid Build Coastguard Worker   }
677*3ac0a46fSAndroid Build Coastguard Worker   if (!pNode)
678*3ac0a46fSAndroid Build Coastguard Worker     return;
679*3ac0a46fSAndroid Build Coastguard Worker 
680*3ac0a46fSAndroid Build Coastguard Worker   SetAttributeValueImpl(wsContent, wsXMLValue, bNotify, bScriptModify);
681*3ac0a46fSAndroid Build Coastguard Worker   if (pBindNode && bSyncData) {
682*3ac0a46fSAndroid Build Coastguard Worker     for (auto* pArrayNode : pBindNode->GetBindItemsCopy()) {
683*3ac0a46fSAndroid Build Coastguard Worker       pArrayNode->JSObject()->SetContent(wsContent, wsContent, bNotify,
684*3ac0a46fSAndroid Build Coastguard Worker                                          bScriptModify, false);
685*3ac0a46fSAndroid Build Coastguard Worker     }
686*3ac0a46fSAndroid Build Coastguard Worker   }
687*3ac0a46fSAndroid Build Coastguard Worker }
688*3ac0a46fSAndroid Build Coastguard Worker 
GetContent(bool bScriptModify) const689*3ac0a46fSAndroid Build Coastguard Worker WideString CJX_Object::GetContent(bool bScriptModify) const {
690*3ac0a46fSAndroid Build Coastguard Worker   return TryContent(bScriptModify, true).value_or(WideString());
691*3ac0a46fSAndroid Build Coastguard Worker }
692*3ac0a46fSAndroid Build Coastguard Worker 
TryContent(bool bScriptModify,bool bProto) const693*3ac0a46fSAndroid Build Coastguard Worker absl::optional<WideString> CJX_Object::TryContent(bool bScriptModify,
694*3ac0a46fSAndroid Build Coastguard Worker                                                   bool bProto) const {
695*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pNode = nullptr;
696*3ac0a46fSAndroid Build Coastguard Worker   switch (GetXFANode()->GetObjectType()) {
697*3ac0a46fSAndroid Build Coastguard Worker     case XFA_ObjectType::ContainerNode:
698*3ac0a46fSAndroid Build Coastguard Worker       if (GetXFANode()->GetElementType() == XFA_Element::ExclGroup) {
699*3ac0a46fSAndroid Build Coastguard Worker         pNode = GetXFANode();
700*3ac0a46fSAndroid Build Coastguard Worker       } else {
701*3ac0a46fSAndroid Build Coastguard Worker         CXFA_Value* pValue =
702*3ac0a46fSAndroid Build Coastguard Worker             GetXFANode()->GetChild<CXFA_Value>(0, XFA_Element::Value, false);
703*3ac0a46fSAndroid Build Coastguard Worker         if (!pValue)
704*3ac0a46fSAndroid Build Coastguard Worker           return absl::nullopt;
705*3ac0a46fSAndroid Build Coastguard Worker 
706*3ac0a46fSAndroid Build Coastguard Worker         CXFA_Node* pChildValue = pValue->GetFirstChild();
707*3ac0a46fSAndroid Build Coastguard Worker         if (pChildValue && XFA_FieldIsMultiListBox(GetXFANode())) {
708*3ac0a46fSAndroid Build Coastguard Worker           pChildValue->JSObject()->SetAttributeByEnum(
709*3ac0a46fSAndroid Build Coastguard Worker               XFA_Attribute::ContentType, L"text/xml", false);
710*3ac0a46fSAndroid Build Coastguard Worker         }
711*3ac0a46fSAndroid Build Coastguard Worker         if (!pChildValue)
712*3ac0a46fSAndroid Build Coastguard Worker           return absl::nullopt;
713*3ac0a46fSAndroid Build Coastguard Worker         return pChildValue->JSObject()->TryContent(bScriptModify, bProto);
714*3ac0a46fSAndroid Build Coastguard Worker       }
715*3ac0a46fSAndroid Build Coastguard Worker       break;
716*3ac0a46fSAndroid Build Coastguard Worker     case XFA_ObjectType::ContentNode: {
717*3ac0a46fSAndroid Build Coastguard Worker       CXFA_Node* pContentRawDataNode = GetXFANode()->GetFirstChild();
718*3ac0a46fSAndroid Build Coastguard Worker       if (!pContentRawDataNode) {
719*3ac0a46fSAndroid Build Coastguard Worker         XFA_Element element = XFA_Element::Sharptext;
720*3ac0a46fSAndroid Build Coastguard Worker         if (GetXFANode()->GetElementType() == XFA_Element::ExData) {
721*3ac0a46fSAndroid Build Coastguard Worker           absl::optional<WideString> contentType =
722*3ac0a46fSAndroid Build Coastguard Worker               TryAttribute(XFA_Attribute::ContentType, false);
723*3ac0a46fSAndroid Build Coastguard Worker           if (contentType.has_value()) {
724*3ac0a46fSAndroid Build Coastguard Worker             if (contentType.value().EqualsASCII("text/html"))
725*3ac0a46fSAndroid Build Coastguard Worker               element = XFA_Element::SharpxHTML;
726*3ac0a46fSAndroid Build Coastguard Worker             else if (contentType.value().EqualsASCII("text/xml"))
727*3ac0a46fSAndroid Build Coastguard Worker               element = XFA_Element::Sharpxml;
728*3ac0a46fSAndroid Build Coastguard Worker           }
729*3ac0a46fSAndroid Build Coastguard Worker         }
730*3ac0a46fSAndroid Build Coastguard Worker         pContentRawDataNode = GetXFANode()->CreateSamePacketNode(element);
731*3ac0a46fSAndroid Build Coastguard Worker         GetXFANode()->InsertChildAndNotify(pContentRawDataNode, nullptr);
732*3ac0a46fSAndroid Build Coastguard Worker       }
733*3ac0a46fSAndroid Build Coastguard Worker       return pContentRawDataNode->JSObject()->TryContent(bScriptModify, true);
734*3ac0a46fSAndroid Build Coastguard Worker     }
735*3ac0a46fSAndroid Build Coastguard Worker     case XFA_ObjectType::NodeC:
736*3ac0a46fSAndroid Build Coastguard Worker     case XFA_ObjectType::NodeV:
737*3ac0a46fSAndroid Build Coastguard Worker     case XFA_ObjectType::TextNode:
738*3ac0a46fSAndroid Build Coastguard Worker       pNode = GetXFANode();
739*3ac0a46fSAndroid Build Coastguard Worker       [[fallthrough]];
740*3ac0a46fSAndroid Build Coastguard Worker     default:
741*3ac0a46fSAndroid Build Coastguard Worker       if (GetXFANode()->GetElementType() == XFA_Element::DataValue)
742*3ac0a46fSAndroid Build Coastguard Worker         pNode = GetXFANode();
743*3ac0a46fSAndroid Build Coastguard Worker       break;
744*3ac0a46fSAndroid Build Coastguard Worker   }
745*3ac0a46fSAndroid Build Coastguard Worker   if (pNode) {
746*3ac0a46fSAndroid Build Coastguard Worker     if (bScriptModify) {
747*3ac0a46fSAndroid Build Coastguard Worker       CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
748*3ac0a46fSAndroid Build Coastguard Worker       pScriptContext->AddNodesOfRunScript(GetXFANode());
749*3ac0a46fSAndroid Build Coastguard Worker     }
750*3ac0a46fSAndroid Build Coastguard Worker     return TryCData(XFA_Attribute::Value, false);
751*3ac0a46fSAndroid Build Coastguard Worker   }
752*3ac0a46fSAndroid Build Coastguard Worker   return absl::nullopt;
753*3ac0a46fSAndroid Build Coastguard Worker }
754*3ac0a46fSAndroid Build Coastguard Worker 
TryNamespace() const755*3ac0a46fSAndroid Build Coastguard Worker absl::optional<WideString> CJX_Object::TryNamespace() const {
756*3ac0a46fSAndroid Build Coastguard Worker   if (GetXFANode()->IsModelNode() ||
757*3ac0a46fSAndroid Build Coastguard Worker       GetXFANode()->GetElementType() == XFA_Element::Packet) {
758*3ac0a46fSAndroid Build Coastguard Worker     CFX_XMLNode* pXMLNode = GetXFANode()->GetXMLMappingNode();
759*3ac0a46fSAndroid Build Coastguard Worker     CFX_XMLElement* element = ToXMLElement(pXMLNode);
760*3ac0a46fSAndroid Build Coastguard Worker     if (!element)
761*3ac0a46fSAndroid Build Coastguard Worker       return absl::nullopt;
762*3ac0a46fSAndroid Build Coastguard Worker 
763*3ac0a46fSAndroid Build Coastguard Worker     return element->GetNamespaceURI();
764*3ac0a46fSAndroid Build Coastguard Worker   }
765*3ac0a46fSAndroid Build Coastguard Worker 
766*3ac0a46fSAndroid Build Coastguard Worker   if (GetXFANode()->GetPacketType() != XFA_PacketType::Datasets)
767*3ac0a46fSAndroid Build Coastguard Worker     return GetXFANode()->GetModelNode()->JSObject()->TryNamespace();
768*3ac0a46fSAndroid Build Coastguard Worker 
769*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLNode* pXMLNode = GetXFANode()->GetXMLMappingNode();
770*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLElement* element = ToXMLElement(pXMLNode);
771*3ac0a46fSAndroid Build Coastguard Worker   if (!element)
772*3ac0a46fSAndroid Build Coastguard Worker     return absl::nullopt;
773*3ac0a46fSAndroid Build Coastguard Worker 
774*3ac0a46fSAndroid Build Coastguard Worker   if (GetXFANode()->GetElementType() == XFA_Element::DataValue &&
775*3ac0a46fSAndroid Build Coastguard Worker       GetEnum(XFA_Attribute::Contains) == XFA_AttributeValue::MetaData) {
776*3ac0a46fSAndroid Build Coastguard Worker     WideString wsNamespace;
777*3ac0a46fSAndroid Build Coastguard Worker     if (!XFA_FDEExtension_ResolveNamespaceQualifier(
778*3ac0a46fSAndroid Build Coastguard Worker             element, GetCData(XFA_Attribute::QualifiedName), &wsNamespace)) {
779*3ac0a46fSAndroid Build Coastguard Worker       return absl::nullopt;
780*3ac0a46fSAndroid Build Coastguard Worker     }
781*3ac0a46fSAndroid Build Coastguard Worker     return wsNamespace;
782*3ac0a46fSAndroid Build Coastguard Worker   }
783*3ac0a46fSAndroid Build Coastguard Worker   return element->GetNamespaceURI();
784*3ac0a46fSAndroid Build Coastguard Worker }
785*3ac0a46fSAndroid Build Coastguard Worker 
GetPropertyInternal(int32_t index,XFA_Element eProperty) const786*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* CJX_Object::GetPropertyInternal(int32_t index,
787*3ac0a46fSAndroid Build Coastguard Worker                                            XFA_Element eProperty) const {
788*3ac0a46fSAndroid Build Coastguard Worker   return GetXFANode()->GetProperty(index, eProperty).first;
789*3ac0a46fSAndroid Build Coastguard Worker }
790*3ac0a46fSAndroid Build Coastguard Worker 
GetOrCreatePropertyInternal(int32_t index,XFA_Element eProperty)791*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* CJX_Object::GetOrCreatePropertyInternal(int32_t index,
792*3ac0a46fSAndroid Build Coastguard Worker                                                    XFA_Element eProperty) {
793*3ac0a46fSAndroid Build Coastguard Worker   return GetXFANode()->GetOrCreateProperty(index, eProperty);
794*3ac0a46fSAndroid Build Coastguard Worker }
795*3ac0a46fSAndroid Build Coastguard Worker 
CreateMapModule()796*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_MapModule* CJX_Object::CreateMapModule() {
797*3ac0a46fSAndroid Build Coastguard Worker   if (!map_module_)
798*3ac0a46fSAndroid Build Coastguard Worker     map_module_ = std::make_unique<CFXJSE_MapModule>();
799*3ac0a46fSAndroid Build Coastguard Worker   return map_module_.get();
800*3ac0a46fSAndroid Build Coastguard Worker }
801*3ac0a46fSAndroid Build Coastguard Worker 
GetMapModule() const802*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_MapModule* CJX_Object::GetMapModule() const {
803*3ac0a46fSAndroid Build Coastguard Worker   return map_module_.get();
804*3ac0a46fSAndroid Build Coastguard Worker }
805*3ac0a46fSAndroid Build Coastguard Worker 
SetMapModuleValue(uint32_t key,int32_t value)806*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::SetMapModuleValue(uint32_t key, int32_t value) {
807*3ac0a46fSAndroid Build Coastguard Worker   CreateMapModule()->SetValue(key, value);
808*3ac0a46fSAndroid Build Coastguard Worker }
809*3ac0a46fSAndroid Build Coastguard Worker 
SetMapModuleString(uint32_t key,const WideString & wsValue)810*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::SetMapModuleString(uint32_t key, const WideString& wsValue) {
811*3ac0a46fSAndroid Build Coastguard Worker   CreateMapModule()->SetString(key, wsValue);
812*3ac0a46fSAndroid Build Coastguard Worker }
813*3ac0a46fSAndroid Build Coastguard Worker 
SetMapModuleMeasurement(uint32_t key,const CXFA_Measurement & value)814*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::SetMapModuleMeasurement(uint32_t key,
815*3ac0a46fSAndroid Build Coastguard Worker                                          const CXFA_Measurement& value) {
816*3ac0a46fSAndroid Build Coastguard Worker   CreateMapModule()->SetMeasurement(key, value);
817*3ac0a46fSAndroid Build Coastguard Worker }
818*3ac0a46fSAndroid Build Coastguard Worker 
GetMapModuleValue(uint32_t key) const819*3ac0a46fSAndroid Build Coastguard Worker absl::optional<int32_t> CJX_Object::GetMapModuleValue(uint32_t key) const {
820*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_MapModule* pModule = GetMapModule();
821*3ac0a46fSAndroid Build Coastguard Worker   if (!pModule)
822*3ac0a46fSAndroid Build Coastguard Worker     return absl::nullopt;
823*3ac0a46fSAndroid Build Coastguard Worker   return pModule->GetValue(key);
824*3ac0a46fSAndroid Build Coastguard Worker }
825*3ac0a46fSAndroid Build Coastguard Worker 
GetMapModuleString(uint32_t key) const826*3ac0a46fSAndroid Build Coastguard Worker absl::optional<WideString> CJX_Object::GetMapModuleString(uint32_t key) const {
827*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_MapModule* pModule = GetMapModule();
828*3ac0a46fSAndroid Build Coastguard Worker   if (!pModule)
829*3ac0a46fSAndroid Build Coastguard Worker     return absl::nullopt;
830*3ac0a46fSAndroid Build Coastguard Worker   return pModule->GetString(key);
831*3ac0a46fSAndroid Build Coastguard Worker }
832*3ac0a46fSAndroid Build Coastguard Worker 
GetMapModuleMeasurement(uint32_t key) const833*3ac0a46fSAndroid Build Coastguard Worker absl::optional<CXFA_Measurement> CJX_Object::GetMapModuleMeasurement(
834*3ac0a46fSAndroid Build Coastguard Worker     uint32_t key) const {
835*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_MapModule* pModule = GetMapModule();
836*3ac0a46fSAndroid Build Coastguard Worker   if (!pModule)
837*3ac0a46fSAndroid Build Coastguard Worker     return absl::nullopt;
838*3ac0a46fSAndroid Build Coastguard Worker   return pModule->GetMeasurement(key);
839*3ac0a46fSAndroid Build Coastguard Worker }
840*3ac0a46fSAndroid Build Coastguard Worker 
GetMapModuleValueFollowingChain(uint32_t key) const841*3ac0a46fSAndroid Build Coastguard Worker absl::optional<int32_t> CJX_Object::GetMapModuleValueFollowingChain(
842*3ac0a46fSAndroid Build Coastguard Worker     uint32_t key) const {
843*3ac0a46fSAndroid Build Coastguard Worker   std::set<const CXFA_Node*> visited;
844*3ac0a46fSAndroid Build Coastguard Worker   for (const CXFA_Node* pNode = GetXFANode(); pNode;
845*3ac0a46fSAndroid Build Coastguard Worker        pNode = pNode->GetTemplateNodeIfExists()) {
846*3ac0a46fSAndroid Build Coastguard Worker     if (!visited.insert(pNode).second)
847*3ac0a46fSAndroid Build Coastguard Worker       break;
848*3ac0a46fSAndroid Build Coastguard Worker 
849*3ac0a46fSAndroid Build Coastguard Worker     absl::optional<int32_t> result = pNode->JSObject()->GetMapModuleValue(key);
850*3ac0a46fSAndroid Build Coastguard Worker     if (result.has_value())
851*3ac0a46fSAndroid Build Coastguard Worker       return result;
852*3ac0a46fSAndroid Build Coastguard Worker 
853*3ac0a46fSAndroid Build Coastguard Worker     if (pNode->GetPacketType() == XFA_PacketType::Datasets)
854*3ac0a46fSAndroid Build Coastguard Worker       break;
855*3ac0a46fSAndroid Build Coastguard Worker   }
856*3ac0a46fSAndroid Build Coastguard Worker   return absl::nullopt;
857*3ac0a46fSAndroid Build Coastguard Worker }
858*3ac0a46fSAndroid Build Coastguard Worker 
GetMapModuleStringFollowingChain(uint32_t key) const859*3ac0a46fSAndroid Build Coastguard Worker absl::optional<WideString> CJX_Object::GetMapModuleStringFollowingChain(
860*3ac0a46fSAndroid Build Coastguard Worker     uint32_t key) const {
861*3ac0a46fSAndroid Build Coastguard Worker   std::set<const CXFA_Node*> visited;
862*3ac0a46fSAndroid Build Coastguard Worker   for (const CXFA_Node* pNode = GetXFANode(); pNode;
863*3ac0a46fSAndroid Build Coastguard Worker        pNode = pNode->GetTemplateNodeIfExists()) {
864*3ac0a46fSAndroid Build Coastguard Worker     if (!visited.insert(pNode).second)
865*3ac0a46fSAndroid Build Coastguard Worker       break;
866*3ac0a46fSAndroid Build Coastguard Worker 
867*3ac0a46fSAndroid Build Coastguard Worker     absl::optional<WideString> result =
868*3ac0a46fSAndroid Build Coastguard Worker         pNode->JSObject()->GetMapModuleString(key);
869*3ac0a46fSAndroid Build Coastguard Worker     if (result.has_value())
870*3ac0a46fSAndroid Build Coastguard Worker       return result;
871*3ac0a46fSAndroid Build Coastguard Worker 
872*3ac0a46fSAndroid Build Coastguard Worker     if (pNode->GetPacketType() == XFA_PacketType::Datasets)
873*3ac0a46fSAndroid Build Coastguard Worker       break;
874*3ac0a46fSAndroid Build Coastguard Worker   }
875*3ac0a46fSAndroid Build Coastguard Worker   return absl::nullopt;
876*3ac0a46fSAndroid Build Coastguard Worker }
877*3ac0a46fSAndroid Build Coastguard Worker 
878*3ac0a46fSAndroid Build Coastguard Worker absl::optional<CXFA_Measurement>
GetMapModuleMeasurementFollowingChain(uint32_t key) const879*3ac0a46fSAndroid Build Coastguard Worker CJX_Object::GetMapModuleMeasurementFollowingChain(uint32_t key) const {
880*3ac0a46fSAndroid Build Coastguard Worker   std::set<const CXFA_Node*> visited;
881*3ac0a46fSAndroid Build Coastguard Worker   for (const CXFA_Node* pNode = GetXFANode(); pNode;
882*3ac0a46fSAndroid Build Coastguard Worker        pNode = pNode->GetTemplateNodeIfExists()) {
883*3ac0a46fSAndroid Build Coastguard Worker     if (!visited.insert(pNode).second)
884*3ac0a46fSAndroid Build Coastguard Worker       break;
885*3ac0a46fSAndroid Build Coastguard Worker 
886*3ac0a46fSAndroid Build Coastguard Worker     absl::optional<CXFA_Measurement> result =
887*3ac0a46fSAndroid Build Coastguard Worker         pNode->JSObject()->GetMapModuleMeasurement(key);
888*3ac0a46fSAndroid Build Coastguard Worker     if (result.has_value())
889*3ac0a46fSAndroid Build Coastguard Worker       return result;
890*3ac0a46fSAndroid Build Coastguard Worker 
891*3ac0a46fSAndroid Build Coastguard Worker     if (pNode->GetPacketType() == XFA_PacketType::Datasets)
892*3ac0a46fSAndroid Build Coastguard Worker       break;
893*3ac0a46fSAndroid Build Coastguard Worker   }
894*3ac0a46fSAndroid Build Coastguard Worker   return absl::nullopt;
895*3ac0a46fSAndroid Build Coastguard Worker }
896*3ac0a46fSAndroid Build Coastguard Worker 
HasMapModuleKey(uint32_t key) const897*3ac0a46fSAndroid Build Coastguard Worker bool CJX_Object::HasMapModuleKey(uint32_t key) const {
898*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_MapModule* pModule = GetMapModule();
899*3ac0a46fSAndroid Build Coastguard Worker   return pModule && pModule->HasKey(key);
900*3ac0a46fSAndroid Build Coastguard Worker }
901*3ac0a46fSAndroid Build Coastguard Worker 
RemoveMapModuleKey(uint32_t key)902*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::RemoveMapModuleKey(uint32_t key) {
903*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_MapModule* pModule = GetMapModule();
904*3ac0a46fSAndroid Build Coastguard Worker   if (pModule)
905*3ac0a46fSAndroid Build Coastguard Worker     pModule->RemoveKey(key);
906*3ac0a46fSAndroid Build Coastguard Worker }
907*3ac0a46fSAndroid Build Coastguard Worker 
MergeAllData(CXFA_Object * pDstObj)908*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::MergeAllData(CXFA_Object* pDstObj) {
909*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_MapModule* pDstModule = ToNode(pDstObj)->JSObject()->CreateMapModule();
910*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_MapModule* pSrcModule = GetMapModule();
911*3ac0a46fSAndroid Build Coastguard Worker   if (!pSrcModule)
912*3ac0a46fSAndroid Build Coastguard Worker     return;
913*3ac0a46fSAndroid Build Coastguard Worker 
914*3ac0a46fSAndroid Build Coastguard Worker   pDstModule->MergeDataFrom(pSrcModule);
915*3ac0a46fSAndroid Build Coastguard Worker }
916*3ac0a46fSAndroid Build Coastguard Worker 
MoveBufferMapData(CXFA_Object * pDstObj)917*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::MoveBufferMapData(CXFA_Object* pDstObj) {
918*3ac0a46fSAndroid Build Coastguard Worker   if (!pDstObj)
919*3ac0a46fSAndroid Build Coastguard Worker     return;
920*3ac0a46fSAndroid Build Coastguard Worker 
921*3ac0a46fSAndroid Build Coastguard Worker   if (pDstObj->GetElementType() == GetXFAObject()->GetElementType())
922*3ac0a46fSAndroid Build Coastguard Worker     ToNode(pDstObj)->JSObject()->TakeCalcDataFrom(this);
923*3ac0a46fSAndroid Build Coastguard Worker 
924*3ac0a46fSAndroid Build Coastguard Worker   if (!pDstObj->IsNodeV())
925*3ac0a46fSAndroid Build Coastguard Worker     return;
926*3ac0a46fSAndroid Build Coastguard Worker 
927*3ac0a46fSAndroid Build Coastguard Worker   WideString wsValue = ToNode(pDstObj)->JSObject()->GetContent(false);
928*3ac0a46fSAndroid Build Coastguard Worker   WideString wsFormatValue(wsValue);
929*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pNode = ToNode(pDstObj)->GetContainerNode();
930*3ac0a46fSAndroid Build Coastguard Worker   if (pNode)
931*3ac0a46fSAndroid Build Coastguard Worker     wsFormatValue = pNode->GetFormatDataValue(wsValue);
932*3ac0a46fSAndroid Build Coastguard Worker 
933*3ac0a46fSAndroid Build Coastguard Worker   ToNode(pDstObj)->JSObject()->SetContent(wsValue, wsFormatValue, true, true,
934*3ac0a46fSAndroid Build Coastguard Worker                                           true);
935*3ac0a46fSAndroid Build Coastguard Worker }
936*3ac0a46fSAndroid Build Coastguard Worker 
MoveBufferMapData(CXFA_Object * pSrcObj,CXFA_Object * pDstObj)937*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::MoveBufferMapData(CXFA_Object* pSrcObj, CXFA_Object* pDstObj) {
938*3ac0a46fSAndroid Build Coastguard Worker   if (!pSrcObj || !pDstObj)
939*3ac0a46fSAndroid Build Coastguard Worker     return;
940*3ac0a46fSAndroid Build Coastguard Worker 
941*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pSrcChild = ToNode(pSrcObj)->GetFirstChild();
942*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pDstChild = ToNode(pDstObj)->GetFirstChild();
943*3ac0a46fSAndroid Build Coastguard Worker   while (pSrcChild && pDstChild) {
944*3ac0a46fSAndroid Build Coastguard Worker     MoveBufferMapData(pSrcChild, pDstChild);
945*3ac0a46fSAndroid Build Coastguard Worker     pSrcChild = pSrcChild->GetNextSibling();
946*3ac0a46fSAndroid Build Coastguard Worker     pDstChild = pDstChild->GetNextSibling();
947*3ac0a46fSAndroid Build Coastguard Worker   }
948*3ac0a46fSAndroid Build Coastguard Worker   ToNode(pSrcObj)->JSObject()->MoveBufferMapData(pDstObj);
949*3ac0a46fSAndroid Build Coastguard Worker }
950*3ac0a46fSAndroid Build Coastguard Worker 
OnChanging(XFA_Attribute eAttr)951*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::OnChanging(XFA_Attribute eAttr) {
952*3ac0a46fSAndroid Build Coastguard Worker   if (!GetXFANode()->IsInitialized())
953*3ac0a46fSAndroid Build Coastguard Worker     return;
954*3ac0a46fSAndroid Build Coastguard Worker 
955*3ac0a46fSAndroid Build Coastguard Worker   CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
956*3ac0a46fSAndroid Build Coastguard Worker   if (!pNotify)
957*3ac0a46fSAndroid Build Coastguard Worker     return;
958*3ac0a46fSAndroid Build Coastguard Worker 
959*3ac0a46fSAndroid Build Coastguard Worker   pNotify->OnValueChanging(GetXFANode(), eAttr);
960*3ac0a46fSAndroid Build Coastguard Worker }
961*3ac0a46fSAndroid Build Coastguard Worker 
OnChanged(XFA_Attribute eAttr,bool bScriptModify)962*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::OnChanged(XFA_Attribute eAttr, bool bScriptModify) {
963*3ac0a46fSAndroid Build Coastguard Worker   if (!GetXFANode()->IsInitialized())
964*3ac0a46fSAndroid Build Coastguard Worker     return;
965*3ac0a46fSAndroid Build Coastguard Worker 
966*3ac0a46fSAndroid Build Coastguard Worker   GetXFANode()->SendAttributeChangeMessage(eAttr, bScriptModify);
967*3ac0a46fSAndroid Build Coastguard Worker }
968*3ac0a46fSAndroid Build Coastguard Worker 
GetOrCreateCalcData(cppgc::Heap * heap)969*3ac0a46fSAndroid Build Coastguard Worker CJX_Object::CalcData* CJX_Object::GetOrCreateCalcData(cppgc::Heap* heap) {
970*3ac0a46fSAndroid Build Coastguard Worker   if (!calc_data_) {
971*3ac0a46fSAndroid Build Coastguard Worker     calc_data_ =
972*3ac0a46fSAndroid Build Coastguard Worker         cppgc::MakeGarbageCollected<CalcData>(heap->GetAllocationHandle());
973*3ac0a46fSAndroid Build Coastguard Worker   }
974*3ac0a46fSAndroid Build Coastguard Worker   return calc_data_;
975*3ac0a46fSAndroid Build Coastguard Worker }
976*3ac0a46fSAndroid Build Coastguard Worker 
TakeCalcDataFrom(CJX_Object * that)977*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::TakeCalcDataFrom(CJX_Object* that) {
978*3ac0a46fSAndroid Build Coastguard Worker   calc_data_ = that->calc_data_;
979*3ac0a46fSAndroid Build Coastguard Worker   that->calc_data_ = nullptr;
980*3ac0a46fSAndroid Build Coastguard Worker }
981*3ac0a46fSAndroid Build Coastguard Worker 
ScriptAttributeString(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)982*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ScriptAttributeString(v8::Isolate* pIsolate,
983*3ac0a46fSAndroid Build Coastguard Worker                                        v8::Local<v8::Value>* pValue,
984*3ac0a46fSAndroid Build Coastguard Worker                                        bool bSetting,
985*3ac0a46fSAndroid Build Coastguard Worker                                        XFA_Attribute eAttribute) {
986*3ac0a46fSAndroid Build Coastguard Worker   if (!bSetting) {
987*3ac0a46fSAndroid Build Coastguard Worker     *pValue = fxv8::NewStringHelper(
988*3ac0a46fSAndroid Build Coastguard Worker         pIsolate, GetAttributeByEnum(eAttribute).ToUTF8().AsStringView());
989*3ac0a46fSAndroid Build Coastguard Worker     return;
990*3ac0a46fSAndroid Build Coastguard Worker   }
991*3ac0a46fSAndroid Build Coastguard Worker 
992*3ac0a46fSAndroid Build Coastguard Worker   WideString wsValue = fxv8::ReentrantToWideStringHelper(pIsolate, *pValue);
993*3ac0a46fSAndroid Build Coastguard Worker   SetAttributeByEnum(eAttribute, wsValue, true);
994*3ac0a46fSAndroid Build Coastguard Worker   if (eAttribute != XFA_Attribute::Use ||
995*3ac0a46fSAndroid Build Coastguard Worker       GetXFAObject()->GetElementType() != XFA_Element::Desc) {
996*3ac0a46fSAndroid Build Coastguard Worker     return;
997*3ac0a46fSAndroid Build Coastguard Worker   }
998*3ac0a46fSAndroid Build Coastguard Worker 
999*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pTemplateNode =
1000*3ac0a46fSAndroid Build Coastguard Worker       ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Template));
1001*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Subform* pSubForm =
1002*3ac0a46fSAndroid Build Coastguard Worker       pTemplateNode->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform);
1003*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Proto* pProtoRoot =
1004*3ac0a46fSAndroid Build Coastguard Worker       pSubForm ? pSubForm->GetFirstChildByClass<CXFA_Proto>(XFA_Element::Proto)
1005*3ac0a46fSAndroid Build Coastguard Worker                : nullptr;
1006*3ac0a46fSAndroid Build Coastguard Worker 
1007*3ac0a46fSAndroid Build Coastguard Worker   WideString wsID;
1008*3ac0a46fSAndroid Build Coastguard Worker   WideString wsSOM;
1009*3ac0a46fSAndroid Build Coastguard Worker   if (!wsValue.IsEmpty()) {
1010*3ac0a46fSAndroid Build Coastguard Worker     if (wsValue[0] == '#')
1011*3ac0a46fSAndroid Build Coastguard Worker       wsID = wsValue.Substr(1);
1012*3ac0a46fSAndroid Build Coastguard Worker     else
1013*3ac0a46fSAndroid Build Coastguard Worker       wsSOM = std::move(wsValue);
1014*3ac0a46fSAndroid Build Coastguard Worker   }
1015*3ac0a46fSAndroid Build Coastguard Worker 
1016*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pProtoNode = nullptr;
1017*3ac0a46fSAndroid Build Coastguard Worker   if (!wsSOM.IsEmpty()) {
1018*3ac0a46fSAndroid Build Coastguard Worker     absl::optional<CFXJSE_Engine::ResolveResult> maybeResult =
1019*3ac0a46fSAndroid Build Coastguard Worker         GetDocument()->GetScriptContext()->ResolveObjects(
1020*3ac0a46fSAndroid Build Coastguard Worker             pProtoRoot, wsSOM.AsStringView(),
1021*3ac0a46fSAndroid Build Coastguard Worker             Mask<XFA_ResolveFlag>{
1022*3ac0a46fSAndroid Build Coastguard Worker                 XFA_ResolveFlag::kChildren, XFA_ResolveFlag::kAttributes,
1023*3ac0a46fSAndroid Build Coastguard Worker                 XFA_ResolveFlag::kProperties, XFA_ResolveFlag::kParent,
1024*3ac0a46fSAndroid Build Coastguard Worker                 XFA_ResolveFlag::kSiblings});
1025*3ac0a46fSAndroid Build Coastguard Worker     if (maybeResult.has_value() &&
1026*3ac0a46fSAndroid Build Coastguard Worker         maybeResult.value().objects.front()->IsNode()) {
1027*3ac0a46fSAndroid Build Coastguard Worker       pProtoNode = maybeResult.value().objects.front()->AsNode();
1028*3ac0a46fSAndroid Build Coastguard Worker     }
1029*3ac0a46fSAndroid Build Coastguard Worker   } else if (!wsID.IsEmpty()) {
1030*3ac0a46fSAndroid Build Coastguard Worker     pProtoNode = GetDocument()->GetNodeByID(pProtoRoot, wsID.AsStringView());
1031*3ac0a46fSAndroid Build Coastguard Worker   }
1032*3ac0a46fSAndroid Build Coastguard Worker   if (!pProtoNode || pProtoNode->GetPacketType() != XFA_PacketType::Template)
1033*3ac0a46fSAndroid Build Coastguard Worker     return;
1034*3ac0a46fSAndroid Build Coastguard Worker 
1035*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pHeadChild = GetXFANode()->GetFirstChild();
1036*3ac0a46fSAndroid Build Coastguard Worker   while (pHeadChild) {
1037*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Node* pSibling = pHeadChild->GetNextSibling();
1038*3ac0a46fSAndroid Build Coastguard Worker     GetXFANode()->RemoveChildAndNotify(pHeadChild, true);
1039*3ac0a46fSAndroid Build Coastguard Worker     pHeadChild = pSibling;
1040*3ac0a46fSAndroid Build Coastguard Worker   }
1041*3ac0a46fSAndroid Build Coastguard Worker 
1042*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pProtoForm = pProtoNode->CloneTemplateToForm(true);
1043*3ac0a46fSAndroid Build Coastguard Worker   pHeadChild = pProtoForm->GetFirstChild();
1044*3ac0a46fSAndroid Build Coastguard Worker   while (pHeadChild) {
1045*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Node* pSibling = pHeadChild->GetNextSibling();
1046*3ac0a46fSAndroid Build Coastguard Worker     pProtoForm->RemoveChildAndNotify(pHeadChild, true);
1047*3ac0a46fSAndroid Build Coastguard Worker     GetXFANode()->InsertChildAndNotify(pHeadChild, nullptr);
1048*3ac0a46fSAndroid Build Coastguard Worker     pHeadChild = pSibling;
1049*3ac0a46fSAndroid Build Coastguard Worker   }
1050*3ac0a46fSAndroid Build Coastguard Worker }
1051*3ac0a46fSAndroid Build Coastguard Worker 
ScriptAttributeBool(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)1052*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ScriptAttributeBool(v8::Isolate* pIsolate,
1053*3ac0a46fSAndroid Build Coastguard Worker                                      v8::Local<v8::Value>* pValue,
1054*3ac0a46fSAndroid Build Coastguard Worker                                      bool bSetting,
1055*3ac0a46fSAndroid Build Coastguard Worker                                      XFA_Attribute eAttribute) {
1056*3ac0a46fSAndroid Build Coastguard Worker   if (bSetting) {
1057*3ac0a46fSAndroid Build Coastguard Worker     SetBoolean(eAttribute, fxv8::ReentrantToBooleanHelper(pIsolate, *pValue),
1058*3ac0a46fSAndroid Build Coastguard Worker                true);
1059*3ac0a46fSAndroid Build Coastguard Worker     return;
1060*3ac0a46fSAndroid Build Coastguard Worker   }
1061*3ac0a46fSAndroid Build Coastguard Worker   *pValue = fxv8::NewStringHelper(pIsolate, GetBoolean(eAttribute) ? "1" : "0");
1062*3ac0a46fSAndroid Build Coastguard Worker }
1063*3ac0a46fSAndroid Build Coastguard Worker 
ScriptAttributeInteger(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)1064*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ScriptAttributeInteger(v8::Isolate* pIsolate,
1065*3ac0a46fSAndroid Build Coastguard Worker                                         v8::Local<v8::Value>* pValue,
1066*3ac0a46fSAndroid Build Coastguard Worker                                         bool bSetting,
1067*3ac0a46fSAndroid Build Coastguard Worker                                         XFA_Attribute eAttribute) {
1068*3ac0a46fSAndroid Build Coastguard Worker   if (bSetting) {
1069*3ac0a46fSAndroid Build Coastguard Worker     SetInteger(eAttribute, fxv8::ReentrantToInt32Helper(pIsolate, *pValue),
1070*3ac0a46fSAndroid Build Coastguard Worker                true);
1071*3ac0a46fSAndroid Build Coastguard Worker     return;
1072*3ac0a46fSAndroid Build Coastguard Worker   }
1073*3ac0a46fSAndroid Build Coastguard Worker   *pValue = fxv8::NewNumberHelper(pIsolate, GetInteger(eAttribute));
1074*3ac0a46fSAndroid Build Coastguard Worker }
1075*3ac0a46fSAndroid Build Coastguard Worker 
ScriptSomFontColor(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)1076*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ScriptSomFontColor(v8::Isolate* pIsolate,
1077*3ac0a46fSAndroid Build Coastguard Worker                                     v8::Local<v8::Value>* pValue,
1078*3ac0a46fSAndroid Build Coastguard Worker                                     bool bSetting,
1079*3ac0a46fSAndroid Build Coastguard Worker                                     XFA_Attribute eAttribute) {
1080*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Font* font = ToNode(object_.Get())->GetOrCreateFontIfPossible();
1081*3ac0a46fSAndroid Build Coastguard Worker   if (!font)
1082*3ac0a46fSAndroid Build Coastguard Worker     return;
1083*3ac0a46fSAndroid Build Coastguard Worker 
1084*3ac0a46fSAndroid Build Coastguard Worker   if (bSetting) {
1085*3ac0a46fSAndroid Build Coastguard Worker     int32_t r;
1086*3ac0a46fSAndroid Build Coastguard Worker     int32_t g;
1087*3ac0a46fSAndroid Build Coastguard Worker     int32_t b;
1088*3ac0a46fSAndroid Build Coastguard Worker     std::tie(r, g, b) =
1089*3ac0a46fSAndroid Build Coastguard Worker         StrToRGB(fxv8::ReentrantToWideStringHelper(pIsolate, *pValue));
1090*3ac0a46fSAndroid Build Coastguard Worker     FX_ARGB color = ArgbEncode(0xff, r, g, b);
1091*3ac0a46fSAndroid Build Coastguard Worker     font->SetColor(color);
1092*3ac0a46fSAndroid Build Coastguard Worker     return;
1093*3ac0a46fSAndroid Build Coastguard Worker   }
1094*3ac0a46fSAndroid Build Coastguard Worker 
1095*3ac0a46fSAndroid Build Coastguard Worker   int32_t a;
1096*3ac0a46fSAndroid Build Coastguard Worker   int32_t r;
1097*3ac0a46fSAndroid Build Coastguard Worker   int32_t g;
1098*3ac0a46fSAndroid Build Coastguard Worker   int32_t b;
1099*3ac0a46fSAndroid Build Coastguard Worker   std::tie(a, r, g, b) = ArgbDecode(font->GetColor());
1100*3ac0a46fSAndroid Build Coastguard Worker   *pValue = fxv8::NewStringHelper(
1101*3ac0a46fSAndroid Build Coastguard Worker       pIsolate, ByteString::Format("%d,%d,%d", r, g, b).AsStringView());
1102*3ac0a46fSAndroid Build Coastguard Worker }
1103*3ac0a46fSAndroid Build Coastguard Worker 
ScriptSomFillColor(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)1104*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ScriptSomFillColor(v8::Isolate* pIsolate,
1105*3ac0a46fSAndroid Build Coastguard Worker                                     v8::Local<v8::Value>* pValue,
1106*3ac0a46fSAndroid Build Coastguard Worker                                     bool bSetting,
1107*3ac0a46fSAndroid Build Coastguard Worker                                     XFA_Attribute eAttribute) {
1108*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Border* border = ToNode(object_.Get())->GetOrCreateBorderIfPossible();
1109*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Fill* borderfill = border->GetOrCreateFillIfPossible();
1110*3ac0a46fSAndroid Build Coastguard Worker   if (!borderfill)
1111*3ac0a46fSAndroid Build Coastguard Worker     return;
1112*3ac0a46fSAndroid Build Coastguard Worker 
1113*3ac0a46fSAndroid Build Coastguard Worker   if (bSetting) {
1114*3ac0a46fSAndroid Build Coastguard Worker     int32_t r;
1115*3ac0a46fSAndroid Build Coastguard Worker     int32_t g;
1116*3ac0a46fSAndroid Build Coastguard Worker     int32_t b;
1117*3ac0a46fSAndroid Build Coastguard Worker     std::tie(r, g, b) =
1118*3ac0a46fSAndroid Build Coastguard Worker         StrToRGB(fxv8::ReentrantToWideStringHelper(pIsolate, *pValue));
1119*3ac0a46fSAndroid Build Coastguard Worker     FX_ARGB color = ArgbEncode(0xff, r, g, b);
1120*3ac0a46fSAndroid Build Coastguard Worker     borderfill->SetColor(color);
1121*3ac0a46fSAndroid Build Coastguard Worker     return;
1122*3ac0a46fSAndroid Build Coastguard Worker   }
1123*3ac0a46fSAndroid Build Coastguard Worker 
1124*3ac0a46fSAndroid Build Coastguard Worker   FX_ARGB color = borderfill->GetFillColor();
1125*3ac0a46fSAndroid Build Coastguard Worker   int32_t a;
1126*3ac0a46fSAndroid Build Coastguard Worker   int32_t r;
1127*3ac0a46fSAndroid Build Coastguard Worker   int32_t g;
1128*3ac0a46fSAndroid Build Coastguard Worker   int32_t b;
1129*3ac0a46fSAndroid Build Coastguard Worker   std::tie(a, r, g, b) = ArgbDecode(color);
1130*3ac0a46fSAndroid Build Coastguard Worker   *pValue = fxv8::NewStringHelper(
1131*3ac0a46fSAndroid Build Coastguard Worker       pIsolate, ByteString::Format("%d,%d,%d", r, g, b).AsStringView());
1132*3ac0a46fSAndroid Build Coastguard Worker }
1133*3ac0a46fSAndroid Build Coastguard Worker 
ScriptSomBorderColor(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)1134*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ScriptSomBorderColor(v8::Isolate* pIsolate,
1135*3ac0a46fSAndroid Build Coastguard Worker                                       v8::Local<v8::Value>* pValue,
1136*3ac0a46fSAndroid Build Coastguard Worker                                       bool bSetting,
1137*3ac0a46fSAndroid Build Coastguard Worker                                       XFA_Attribute eAttribute) {
1138*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Border* border = ToNode(object_.Get())->GetOrCreateBorderIfPossible();
1139*3ac0a46fSAndroid Build Coastguard Worker   int32_t iSize = border->CountEdges();
1140*3ac0a46fSAndroid Build Coastguard Worker   if (bSetting) {
1141*3ac0a46fSAndroid Build Coastguard Worker     int32_t r = 0;
1142*3ac0a46fSAndroid Build Coastguard Worker     int32_t g = 0;
1143*3ac0a46fSAndroid Build Coastguard Worker     int32_t b = 0;
1144*3ac0a46fSAndroid Build Coastguard Worker     std::tie(r, g, b) =
1145*3ac0a46fSAndroid Build Coastguard Worker         StrToRGB(fxv8::ReentrantToWideStringHelper(pIsolate, *pValue));
1146*3ac0a46fSAndroid Build Coastguard Worker     FX_ARGB rgb = ArgbEncode(100, r, g, b);
1147*3ac0a46fSAndroid Build Coastguard Worker     for (int32_t i = 0; i < iSize; ++i) {
1148*3ac0a46fSAndroid Build Coastguard Worker       CXFA_Edge* edge = border->GetEdgeIfExists(i);
1149*3ac0a46fSAndroid Build Coastguard Worker       if (edge)
1150*3ac0a46fSAndroid Build Coastguard Worker         edge->SetColor(rgb);
1151*3ac0a46fSAndroid Build Coastguard Worker     }
1152*3ac0a46fSAndroid Build Coastguard Worker 
1153*3ac0a46fSAndroid Build Coastguard Worker     return;
1154*3ac0a46fSAndroid Build Coastguard Worker   }
1155*3ac0a46fSAndroid Build Coastguard Worker 
1156*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Edge* edge = border->GetEdgeIfExists(0);
1157*3ac0a46fSAndroid Build Coastguard Worker   FX_ARGB color = edge ? edge->GetColor() : CXFA_Edge::kDefaultColor;
1158*3ac0a46fSAndroid Build Coastguard Worker   int32_t a;
1159*3ac0a46fSAndroid Build Coastguard Worker   int32_t r;
1160*3ac0a46fSAndroid Build Coastguard Worker   int32_t g;
1161*3ac0a46fSAndroid Build Coastguard Worker   int32_t b;
1162*3ac0a46fSAndroid Build Coastguard Worker   std::tie(a, r, g, b) = ArgbDecode(color);
1163*3ac0a46fSAndroid Build Coastguard Worker   *pValue = fxv8::NewStringHelper(
1164*3ac0a46fSAndroid Build Coastguard Worker       pIsolate, ByteString::Format("%d,%d,%d", r, g, b).AsStringView());
1165*3ac0a46fSAndroid Build Coastguard Worker }
1166*3ac0a46fSAndroid Build Coastguard Worker 
ScriptSomBorderWidth(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)1167*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ScriptSomBorderWidth(v8::Isolate* pIsolate,
1168*3ac0a46fSAndroid Build Coastguard Worker                                       v8::Local<v8::Value>* pValue,
1169*3ac0a46fSAndroid Build Coastguard Worker                                       bool bSetting,
1170*3ac0a46fSAndroid Build Coastguard Worker                                       XFA_Attribute eAttribute) {
1171*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Border* border = ToNode(object_.Get())->GetOrCreateBorderIfPossible();
1172*3ac0a46fSAndroid Build Coastguard Worker   if (bSetting) {
1173*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Edge* edge = border->GetEdgeIfExists(0);
1174*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Measurement thickness =
1175*3ac0a46fSAndroid Build Coastguard Worker         edge ? edge->GetMSThickness() : CXFA_Measurement(0.5, XFA_Unit::Pt);
1176*3ac0a46fSAndroid Build Coastguard Worker     *pValue = fxv8::NewStringHelper(
1177*3ac0a46fSAndroid Build Coastguard Worker         pIsolate, thickness.ToString().ToUTF8().AsStringView());
1178*3ac0a46fSAndroid Build Coastguard Worker     return;
1179*3ac0a46fSAndroid Build Coastguard Worker   }
1180*3ac0a46fSAndroid Build Coastguard Worker 
1181*3ac0a46fSAndroid Build Coastguard Worker   if (pValue->IsEmpty())
1182*3ac0a46fSAndroid Build Coastguard Worker     return;
1183*3ac0a46fSAndroid Build Coastguard Worker 
1184*3ac0a46fSAndroid Build Coastguard Worker   WideString wsThickness = fxv8::ReentrantToWideStringHelper(pIsolate, *pValue);
1185*3ac0a46fSAndroid Build Coastguard Worker   for (size_t i = 0; i < border->CountEdges(); ++i) {
1186*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Edge* edge = border->GetEdgeIfExists(i);
1187*3ac0a46fSAndroid Build Coastguard Worker     if (edge)
1188*3ac0a46fSAndroid Build Coastguard Worker       edge->SetMSThickness(CXFA_Measurement(wsThickness.AsStringView()));
1189*3ac0a46fSAndroid Build Coastguard Worker   }
1190*3ac0a46fSAndroid Build Coastguard Worker }
1191*3ac0a46fSAndroid Build Coastguard Worker 
ScriptSomMessage(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,SOMMessageType iMessageType)1192*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ScriptSomMessage(v8::Isolate* pIsolate,
1193*3ac0a46fSAndroid Build Coastguard Worker                                   v8::Local<v8::Value>* pValue,
1194*3ac0a46fSAndroid Build Coastguard Worker                                   bool bSetting,
1195*3ac0a46fSAndroid Build Coastguard Worker                                   SOMMessageType iMessageType) {
1196*3ac0a46fSAndroid Build Coastguard Worker   bool bNew = false;
1197*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Validate* validate = ToNode(object_.Get())->GetValidateIfExists();
1198*3ac0a46fSAndroid Build Coastguard Worker   if (!validate) {
1199*3ac0a46fSAndroid Build Coastguard Worker     validate = ToNode(object_.Get())->GetOrCreateValidateIfPossible();
1200*3ac0a46fSAndroid Build Coastguard Worker     bNew = true;
1201*3ac0a46fSAndroid Build Coastguard Worker   }
1202*3ac0a46fSAndroid Build Coastguard Worker 
1203*3ac0a46fSAndroid Build Coastguard Worker   if (bSetting) {
1204*3ac0a46fSAndroid Build Coastguard Worker     if (validate) {
1205*3ac0a46fSAndroid Build Coastguard Worker       switch (iMessageType) {
1206*3ac0a46fSAndroid Build Coastguard Worker         case SOMMessageType::kValidationMessage:
1207*3ac0a46fSAndroid Build Coastguard Worker           validate->SetScriptMessageText(
1208*3ac0a46fSAndroid Build Coastguard Worker               fxv8::ReentrantToWideStringHelper(pIsolate, *pValue));
1209*3ac0a46fSAndroid Build Coastguard Worker           break;
1210*3ac0a46fSAndroid Build Coastguard Worker         case SOMMessageType::kFormatMessage:
1211*3ac0a46fSAndroid Build Coastguard Worker           validate->SetFormatMessageText(
1212*3ac0a46fSAndroid Build Coastguard Worker               fxv8::ReentrantToWideStringHelper(pIsolate, *pValue));
1213*3ac0a46fSAndroid Build Coastguard Worker           break;
1214*3ac0a46fSAndroid Build Coastguard Worker         case SOMMessageType::kMandatoryMessage:
1215*3ac0a46fSAndroid Build Coastguard Worker           validate->SetNullMessageText(
1216*3ac0a46fSAndroid Build Coastguard Worker               fxv8::ReentrantToWideStringHelper(pIsolate, *pValue));
1217*3ac0a46fSAndroid Build Coastguard Worker           break;
1218*3ac0a46fSAndroid Build Coastguard Worker       }
1219*3ac0a46fSAndroid Build Coastguard Worker     }
1220*3ac0a46fSAndroid Build Coastguard Worker 
1221*3ac0a46fSAndroid Build Coastguard Worker     if (!bNew) {
1222*3ac0a46fSAndroid Build Coastguard Worker       CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
1223*3ac0a46fSAndroid Build Coastguard Worker       if (!pNotify)
1224*3ac0a46fSAndroid Build Coastguard Worker         return;
1225*3ac0a46fSAndroid Build Coastguard Worker 
1226*3ac0a46fSAndroid Build Coastguard Worker       pNotify->AddCalcValidate(GetXFANode());
1227*3ac0a46fSAndroid Build Coastguard Worker     }
1228*3ac0a46fSAndroid Build Coastguard Worker     return;
1229*3ac0a46fSAndroid Build Coastguard Worker   }
1230*3ac0a46fSAndroid Build Coastguard Worker 
1231*3ac0a46fSAndroid Build Coastguard Worker   if (!validate) {
1232*3ac0a46fSAndroid Build Coastguard Worker     // TODO(dsinclair): Better error message?
1233*3ac0a46fSAndroid Build Coastguard Worker     ThrowInvalidPropertyException(pIsolate);
1234*3ac0a46fSAndroid Build Coastguard Worker     return;
1235*3ac0a46fSAndroid Build Coastguard Worker   }
1236*3ac0a46fSAndroid Build Coastguard Worker 
1237*3ac0a46fSAndroid Build Coastguard Worker   WideString wsMessage;
1238*3ac0a46fSAndroid Build Coastguard Worker   switch (iMessageType) {
1239*3ac0a46fSAndroid Build Coastguard Worker     case SOMMessageType::kValidationMessage:
1240*3ac0a46fSAndroid Build Coastguard Worker       wsMessage = validate->GetScriptMessageText();
1241*3ac0a46fSAndroid Build Coastguard Worker       break;
1242*3ac0a46fSAndroid Build Coastguard Worker     case SOMMessageType::kFormatMessage:
1243*3ac0a46fSAndroid Build Coastguard Worker       wsMessage = validate->GetFormatMessageText();
1244*3ac0a46fSAndroid Build Coastguard Worker       break;
1245*3ac0a46fSAndroid Build Coastguard Worker     case SOMMessageType::kMandatoryMessage:
1246*3ac0a46fSAndroid Build Coastguard Worker       wsMessage = validate->GetNullMessageText();
1247*3ac0a46fSAndroid Build Coastguard Worker       break;
1248*3ac0a46fSAndroid Build Coastguard Worker   }
1249*3ac0a46fSAndroid Build Coastguard Worker   *pValue = fxv8::NewStringHelper(pIsolate, wsMessage.ToUTF8().AsStringView());
1250*3ac0a46fSAndroid Build Coastguard Worker }
1251*3ac0a46fSAndroid Build Coastguard Worker 
ScriptSomValidationMessage(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)1252*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ScriptSomValidationMessage(v8::Isolate* pIsolate,
1253*3ac0a46fSAndroid Build Coastguard Worker                                             v8::Local<v8::Value>* pValue,
1254*3ac0a46fSAndroid Build Coastguard Worker                                             bool bSetting,
1255*3ac0a46fSAndroid Build Coastguard Worker                                             XFA_Attribute eAttribute) {
1256*3ac0a46fSAndroid Build Coastguard Worker   ScriptSomMessage(pIsolate, pValue, bSetting,
1257*3ac0a46fSAndroid Build Coastguard Worker                    SOMMessageType::kValidationMessage);
1258*3ac0a46fSAndroid Build Coastguard Worker }
1259*3ac0a46fSAndroid Build Coastguard Worker 
ScriptSomMandatoryMessage(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)1260*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ScriptSomMandatoryMessage(v8::Isolate* pIsolate,
1261*3ac0a46fSAndroid Build Coastguard Worker                                            v8::Local<v8::Value>* pValue,
1262*3ac0a46fSAndroid Build Coastguard Worker                                            bool bSetting,
1263*3ac0a46fSAndroid Build Coastguard Worker                                            XFA_Attribute eAttribute) {
1264*3ac0a46fSAndroid Build Coastguard Worker   ScriptSomMessage(pIsolate, pValue, bSetting,
1265*3ac0a46fSAndroid Build Coastguard Worker                    SOMMessageType::kMandatoryMessage);
1266*3ac0a46fSAndroid Build Coastguard Worker }
1267*3ac0a46fSAndroid Build Coastguard Worker 
ScriptSomDefaultValue(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute)1268*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ScriptSomDefaultValue(v8::Isolate* pIsolate,
1269*3ac0a46fSAndroid Build Coastguard Worker                                        v8::Local<v8::Value>* pValue,
1270*3ac0a46fSAndroid Build Coastguard Worker                                        bool bSetting,
1271*3ac0a46fSAndroid Build Coastguard Worker                                        XFA_Attribute /* unused */) {
1272*3ac0a46fSAndroid Build Coastguard Worker   XFA_Element eType = GetXFANode()->GetElementType();
1273*3ac0a46fSAndroid Build Coastguard Worker 
1274*3ac0a46fSAndroid Build Coastguard Worker   // TODO(dsinclair): This should look through the properties on the node to see
1275*3ac0a46fSAndroid Build Coastguard Worker   // if defaultValue is defined and, if so, call that one. Just have to make
1276*3ac0a46fSAndroid Build Coastguard Worker   // sure that those defaultValue calls don't call back to this one ....
1277*3ac0a46fSAndroid Build Coastguard Worker   if (eType == XFA_Element::Field) {
1278*3ac0a46fSAndroid Build Coastguard Worker     static_cast<CJX_Field*>(this)->defaultValue(pIsolate, pValue, bSetting,
1279*3ac0a46fSAndroid Build Coastguard Worker                                                 XFA_Attribute::Unknown);
1280*3ac0a46fSAndroid Build Coastguard Worker     return;
1281*3ac0a46fSAndroid Build Coastguard Worker   }
1282*3ac0a46fSAndroid Build Coastguard Worker   if (eType == XFA_Element::Draw) {
1283*3ac0a46fSAndroid Build Coastguard Worker     static_cast<CJX_Draw*>(this)->defaultValue(pIsolate, pValue, bSetting,
1284*3ac0a46fSAndroid Build Coastguard Worker                                                XFA_Attribute::Unknown);
1285*3ac0a46fSAndroid Build Coastguard Worker     return;
1286*3ac0a46fSAndroid Build Coastguard Worker   }
1287*3ac0a46fSAndroid Build Coastguard Worker   if (eType == XFA_Element::Boolean) {
1288*3ac0a46fSAndroid Build Coastguard Worker     static_cast<CJX_Boolean*>(this)->defaultValue(pIsolate, pValue, bSetting,
1289*3ac0a46fSAndroid Build Coastguard Worker                                                   XFA_Attribute::Unknown);
1290*3ac0a46fSAndroid Build Coastguard Worker     return;
1291*3ac0a46fSAndroid Build Coastguard Worker   }
1292*3ac0a46fSAndroid Build Coastguard Worker 
1293*3ac0a46fSAndroid Build Coastguard Worker   if (bSetting) {
1294*3ac0a46fSAndroid Build Coastguard Worker     WideString wsNewValue;
1295*3ac0a46fSAndroid Build Coastguard Worker     if (pValue && !(pValue->IsEmpty() || fxv8::IsNull(*pValue) ||
1296*3ac0a46fSAndroid Build Coastguard Worker                     fxv8::IsUndefined(*pValue))) {
1297*3ac0a46fSAndroid Build Coastguard Worker       wsNewValue = fxv8::ReentrantToWideStringHelper(pIsolate, *pValue);
1298*3ac0a46fSAndroid Build Coastguard Worker     }
1299*3ac0a46fSAndroid Build Coastguard Worker 
1300*3ac0a46fSAndroid Build Coastguard Worker     WideString wsFormatValue = wsNewValue;
1301*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Node* pContainerNode = nullptr;
1302*3ac0a46fSAndroid Build Coastguard Worker     if (GetXFANode()->GetPacketType() == XFA_PacketType::Datasets) {
1303*3ac0a46fSAndroid Build Coastguard Worker       WideString wsPicture;
1304*3ac0a46fSAndroid Build Coastguard Worker       for (auto* pFormNode : GetXFANode()->GetBindItemsCopy()) {
1305*3ac0a46fSAndroid Build Coastguard Worker         if (!pFormNode || pFormNode->HasRemovedChildren())
1306*3ac0a46fSAndroid Build Coastguard Worker           continue;
1307*3ac0a46fSAndroid Build Coastguard Worker 
1308*3ac0a46fSAndroid Build Coastguard Worker         pContainerNode = pFormNode->GetContainerNode();
1309*3ac0a46fSAndroid Build Coastguard Worker         if (pContainerNode) {
1310*3ac0a46fSAndroid Build Coastguard Worker           wsPicture =
1311*3ac0a46fSAndroid Build Coastguard Worker               pContainerNode->GetPictureContent(XFA_ValuePicture::kDataBind);
1312*3ac0a46fSAndroid Build Coastguard Worker         }
1313*3ac0a46fSAndroid Build Coastguard Worker         if (!wsPicture.IsEmpty())
1314*3ac0a46fSAndroid Build Coastguard Worker           break;
1315*3ac0a46fSAndroid Build Coastguard Worker 
1316*3ac0a46fSAndroid Build Coastguard Worker         pContainerNode = nullptr;
1317*3ac0a46fSAndroid Build Coastguard Worker       }
1318*3ac0a46fSAndroid Build Coastguard Worker     } else if (GetXFANode()->GetPacketType() == XFA_PacketType::Form) {
1319*3ac0a46fSAndroid Build Coastguard Worker       pContainerNode = GetXFANode()->GetContainerNode();
1320*3ac0a46fSAndroid Build Coastguard Worker     }
1321*3ac0a46fSAndroid Build Coastguard Worker 
1322*3ac0a46fSAndroid Build Coastguard Worker     if (pContainerNode)
1323*3ac0a46fSAndroid Build Coastguard Worker       wsFormatValue = pContainerNode->GetFormatDataValue(wsNewValue);
1324*3ac0a46fSAndroid Build Coastguard Worker 
1325*3ac0a46fSAndroid Build Coastguard Worker     SetContent(wsNewValue, wsFormatValue, true, true, true);
1326*3ac0a46fSAndroid Build Coastguard Worker     return;
1327*3ac0a46fSAndroid Build Coastguard Worker   }
1328*3ac0a46fSAndroid Build Coastguard Worker 
1329*3ac0a46fSAndroid Build Coastguard Worker   WideString content = GetContent(true);
1330*3ac0a46fSAndroid Build Coastguard Worker   if (content.IsEmpty() && eType != XFA_Element::Text &&
1331*3ac0a46fSAndroid Build Coastguard Worker       eType != XFA_Element::SubmitUrl) {
1332*3ac0a46fSAndroid Build Coastguard Worker     *pValue = fxv8::NewNullHelper(pIsolate);
1333*3ac0a46fSAndroid Build Coastguard Worker   } else if (eType == XFA_Element::Integer) {
1334*3ac0a46fSAndroid Build Coastguard Worker     *pValue = fxv8::NewNumberHelper(pIsolate, FXSYS_wtoi(content.c_str()));
1335*3ac0a46fSAndroid Build Coastguard Worker   } else if (eType == XFA_Element::Float || eType == XFA_Element::Decimal) {
1336*3ac0a46fSAndroid Build Coastguard Worker     CFGAS_Decimal decimal(content.AsStringView());
1337*3ac0a46fSAndroid Build Coastguard Worker     *pValue = fxv8::NewNumberHelper(pIsolate, decimal.ToFloat());
1338*3ac0a46fSAndroid Build Coastguard Worker   } else {
1339*3ac0a46fSAndroid Build Coastguard Worker     *pValue = fxv8::NewStringHelper(pIsolate, content.ToUTF8().AsStringView());
1340*3ac0a46fSAndroid Build Coastguard Worker   }
1341*3ac0a46fSAndroid Build Coastguard Worker }
1342*3ac0a46fSAndroid Build Coastguard Worker 
ScriptSomDefaultValue_Read(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)1343*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ScriptSomDefaultValue_Read(v8::Isolate* pIsolate,
1344*3ac0a46fSAndroid Build Coastguard Worker                                             v8::Local<v8::Value>* pValue,
1345*3ac0a46fSAndroid Build Coastguard Worker                                             bool bSetting,
1346*3ac0a46fSAndroid Build Coastguard Worker                                             XFA_Attribute eAttribute) {
1347*3ac0a46fSAndroid Build Coastguard Worker   if (bSetting) {
1348*3ac0a46fSAndroid Build Coastguard Worker     ThrowInvalidPropertyException(pIsolate);
1349*3ac0a46fSAndroid Build Coastguard Worker     return;
1350*3ac0a46fSAndroid Build Coastguard Worker   }
1351*3ac0a46fSAndroid Build Coastguard Worker 
1352*3ac0a46fSAndroid Build Coastguard Worker   WideString content = GetContent(true);
1353*3ac0a46fSAndroid Build Coastguard Worker   if (content.IsEmpty()) {
1354*3ac0a46fSAndroid Build Coastguard Worker     *pValue = fxv8::NewNullHelper(pIsolate);
1355*3ac0a46fSAndroid Build Coastguard Worker     return;
1356*3ac0a46fSAndroid Build Coastguard Worker   }
1357*3ac0a46fSAndroid Build Coastguard Worker   *pValue = fxv8::NewStringHelper(pIsolate, content.ToUTF8().AsStringView());
1358*3ac0a46fSAndroid Build Coastguard Worker }
1359*3ac0a46fSAndroid Build Coastguard Worker 
ScriptSomDataNode(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)1360*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ScriptSomDataNode(v8::Isolate* pIsolate,
1361*3ac0a46fSAndroid Build Coastguard Worker                                    v8::Local<v8::Value>* pValue,
1362*3ac0a46fSAndroid Build Coastguard Worker                                    bool bSetting,
1363*3ac0a46fSAndroid Build Coastguard Worker                                    XFA_Attribute eAttribute) {
1364*3ac0a46fSAndroid Build Coastguard Worker   if (bSetting) {
1365*3ac0a46fSAndroid Build Coastguard Worker     ThrowInvalidPropertyException(pIsolate);
1366*3ac0a46fSAndroid Build Coastguard Worker     return;
1367*3ac0a46fSAndroid Build Coastguard Worker   }
1368*3ac0a46fSAndroid Build Coastguard Worker 
1369*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pDataNode = GetXFANode()->GetBindData();
1370*3ac0a46fSAndroid Build Coastguard Worker   if (!pDataNode) {
1371*3ac0a46fSAndroid Build Coastguard Worker     *pValue = fxv8::NewNullHelper(pIsolate);
1372*3ac0a46fSAndroid Build Coastguard Worker     return;
1373*3ac0a46fSAndroid Build Coastguard Worker   }
1374*3ac0a46fSAndroid Build Coastguard Worker 
1375*3ac0a46fSAndroid Build Coastguard Worker   *pValue =
1376*3ac0a46fSAndroid Build Coastguard Worker       GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(pDataNode);
1377*3ac0a46fSAndroid Build Coastguard Worker }
1378*3ac0a46fSAndroid Build Coastguard Worker 
ScriptSomMandatory(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)1379*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ScriptSomMandatory(v8::Isolate* pIsolate,
1380*3ac0a46fSAndroid Build Coastguard Worker                                     v8::Local<v8::Value>* pValue,
1381*3ac0a46fSAndroid Build Coastguard Worker                                     bool bSetting,
1382*3ac0a46fSAndroid Build Coastguard Worker                                     XFA_Attribute eAttribute) {
1383*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Validate* validate =
1384*3ac0a46fSAndroid Build Coastguard Worker       ToNode(object_.Get())->GetOrCreateValidateIfPossible();
1385*3ac0a46fSAndroid Build Coastguard Worker   if (!validate)
1386*3ac0a46fSAndroid Build Coastguard Worker     return;
1387*3ac0a46fSAndroid Build Coastguard Worker 
1388*3ac0a46fSAndroid Build Coastguard Worker   if (bSetting) {
1389*3ac0a46fSAndroid Build Coastguard Worker     validate->SetNullTest(fxv8::ReentrantToWideStringHelper(pIsolate, *pValue));
1390*3ac0a46fSAndroid Build Coastguard Worker     return;
1391*3ac0a46fSAndroid Build Coastguard Worker   }
1392*3ac0a46fSAndroid Build Coastguard Worker 
1393*3ac0a46fSAndroid Build Coastguard Worker   *pValue = fxv8::NewStringHelper(
1394*3ac0a46fSAndroid Build Coastguard Worker       pIsolate, XFA_AttributeValueToName(validate->GetNullTest()));
1395*3ac0a46fSAndroid Build Coastguard Worker }
1396*3ac0a46fSAndroid Build Coastguard Worker 
ScriptSomInstanceIndex(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)1397*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ScriptSomInstanceIndex(v8::Isolate* pIsolate,
1398*3ac0a46fSAndroid Build Coastguard Worker                                         v8::Local<v8::Value>* pValue,
1399*3ac0a46fSAndroid Build Coastguard Worker                                         bool bSetting,
1400*3ac0a46fSAndroid Build Coastguard Worker                                         XFA_Attribute eAttribute) {
1401*3ac0a46fSAndroid Build Coastguard Worker   if (!bSetting) {
1402*3ac0a46fSAndroid Build Coastguard Worker     *pValue =
1403*3ac0a46fSAndroid Build Coastguard Worker         fxv8::NewNumberHelper(pIsolate, Subform_and_SubformSet_InstanceIndex());
1404*3ac0a46fSAndroid Build Coastguard Worker     return;
1405*3ac0a46fSAndroid Build Coastguard Worker   }
1406*3ac0a46fSAndroid Build Coastguard Worker 
1407*3ac0a46fSAndroid Build Coastguard Worker   int32_t iTo = fxv8::ReentrantToInt32Helper(pIsolate, *pValue);
1408*3ac0a46fSAndroid Build Coastguard Worker   int32_t iFrom = Subform_and_SubformSet_InstanceIndex();
1409*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pManagerNode = nullptr;
1410*3ac0a46fSAndroid Build Coastguard Worker   for (CXFA_Node* pNode = GetXFANode()->GetPrevSibling(); pNode;
1411*3ac0a46fSAndroid Build Coastguard Worker        pNode = pNode->GetPrevSibling()) {
1412*3ac0a46fSAndroid Build Coastguard Worker     if (pNode->GetElementType() == XFA_Element::InstanceManager) {
1413*3ac0a46fSAndroid Build Coastguard Worker       pManagerNode = pNode;
1414*3ac0a46fSAndroid Build Coastguard Worker       break;
1415*3ac0a46fSAndroid Build Coastguard Worker     }
1416*3ac0a46fSAndroid Build Coastguard Worker   }
1417*3ac0a46fSAndroid Build Coastguard Worker   if (!pManagerNode)
1418*3ac0a46fSAndroid Build Coastguard Worker     return;
1419*3ac0a46fSAndroid Build Coastguard Worker 
1420*3ac0a46fSAndroid Build Coastguard Worker   auto* mgr = static_cast<CJX_InstanceManager*>(pManagerNode->JSObject());
1421*3ac0a46fSAndroid Build Coastguard Worker   mgr->MoveInstance(pIsolate, iTo, iFrom);
1422*3ac0a46fSAndroid Build Coastguard Worker   CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
1423*3ac0a46fSAndroid Build Coastguard Worker   if (!pNotify)
1424*3ac0a46fSAndroid Build Coastguard Worker     return;
1425*3ac0a46fSAndroid Build Coastguard Worker 
1426*3ac0a46fSAndroid Build Coastguard Worker   auto* pToInstance =
1427*3ac0a46fSAndroid Build Coastguard Worker       CXFA_Subform::FromNode(pManagerNode->GetItemIfExists(iTo));
1428*3ac0a46fSAndroid Build Coastguard Worker   if (pToInstance)
1429*3ac0a46fSAndroid Build Coastguard Worker     pNotify->RunSubformIndexChange(pToInstance);
1430*3ac0a46fSAndroid Build Coastguard Worker 
1431*3ac0a46fSAndroid Build Coastguard Worker   auto* pFromInstance =
1432*3ac0a46fSAndroid Build Coastguard Worker       CXFA_Subform::FromNode(pManagerNode->GetItemIfExists(iFrom));
1433*3ac0a46fSAndroid Build Coastguard Worker   if (pFromInstance)
1434*3ac0a46fSAndroid Build Coastguard Worker     pNotify->RunSubformIndexChange(pFromInstance);
1435*3ac0a46fSAndroid Build Coastguard Worker }
1436*3ac0a46fSAndroid Build Coastguard Worker 
ScriptSubmitFormatMode(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)1437*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::ScriptSubmitFormatMode(v8::Isolate* pIsolate,
1438*3ac0a46fSAndroid Build Coastguard Worker                                         v8::Local<v8::Value>* pValue,
1439*3ac0a46fSAndroid Build Coastguard Worker                                         bool bSetting,
1440*3ac0a46fSAndroid Build Coastguard Worker                                         XFA_Attribute eAttribute) {}
1441*3ac0a46fSAndroid Build Coastguard Worker 
1442*3ac0a46fSAndroid Build Coastguard Worker CJX_Object::CalcData::CalcData() = default;
1443*3ac0a46fSAndroid Build Coastguard Worker 
1444*3ac0a46fSAndroid Build Coastguard Worker CJX_Object::CalcData::~CalcData() = default;
1445*3ac0a46fSAndroid Build Coastguard Worker 
Trace(cppgc::Visitor * visitor) const1446*3ac0a46fSAndroid Build Coastguard Worker void CJX_Object::CalcData::Trace(cppgc::Visitor* visitor) const {
1447*3ac0a46fSAndroid Build Coastguard Worker   ContainerTrace(visitor, m_Globals);
1448*3ac0a46fSAndroid Build Coastguard Worker }
1449