• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4 
5 #include "libcef/renderer/dom_node_impl.h"
6 
7 #include "libcef/common/tracker.h"
8 #include "libcef/renderer/blink_glue.h"
9 #include "libcef/renderer/browser_impl.h"
10 #include "libcef/renderer/dom_document_impl.h"
11 #include "libcef/renderer/thread_util.h"
12 
13 #include "base/logging.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "third_party/blink/public/platform/web_string.h"
17 #include "third_party/blink/public/web/web_document.h"
18 #include "third_party/blink/public/web/web_dom_event.h"
19 #include "third_party/blink/public/web/web_element.h"
20 #include "third_party/blink/public/web/web_form_control_element.h"
21 #include "third_party/blink/public/web/web_input_element.h"
22 #include "third_party/blink/public/web/web_node.h"
23 #include "third_party/blink/public/web/web_select_element.h"
24 
25 using blink::WebDocument;
26 using blink::WebDOMEvent;
27 using blink::WebElement;
28 using blink::WebFormControlElement;
29 using blink::WebInputElement;
30 using blink::WebNode;
31 using blink::WebSelectElement;
32 using blink::WebString;
33 
CefDOMNodeImpl(CefRefPtr<CefDOMDocumentImpl> document,const blink::WebNode & node)34 CefDOMNodeImpl::CefDOMNodeImpl(CefRefPtr<CefDOMDocumentImpl> document,
35                                const blink::WebNode& node)
36     : document_(document), node_(node) {}
37 
~CefDOMNodeImpl()38 CefDOMNodeImpl::~CefDOMNodeImpl() {
39   CEF_REQUIRE_RT();
40 
41   if (document_.get() && !node_.IsNull()) {
42     // Remove the node from the document.
43     document_->RemoveNode(node_);
44   }
45 }
46 
GetType()47 CefDOMNodeImpl::Type CefDOMNodeImpl::GetType() {
48   if (!VerifyContext())
49     return DOM_NODE_TYPE_UNSUPPORTED;
50 
51   return blink_glue::GetNodeType(node_);
52 }
53 
IsText()54 bool CefDOMNodeImpl::IsText() {
55   if (!VerifyContext())
56     return false;
57 
58   return node_.IsTextNode();
59 }
60 
IsElement()61 bool CefDOMNodeImpl::IsElement() {
62   if (!VerifyContext())
63     return false;
64 
65   return node_.IsElementNode();
66 }
67 
68 // Logic copied from RenderViewImpl::IsEditableNode.
IsEditable()69 bool CefDOMNodeImpl::IsEditable() {
70   if (!VerifyContext())
71     return false;
72 
73   if (node_.IsContentEditable())
74     return true;
75 
76   if (node_.IsElementNode()) {
77     const WebElement& element = node_.ToConst<WebElement>();
78     if (blink_glue::IsTextControlElement(element))
79       return true;
80 
81     // Also return true if it has an ARIA role of 'textbox'.
82     for (unsigned i = 0; i < element.AttributeCount(); ++i) {
83       if (base::LowerCaseEqualsASCII(element.AttributeLocalName(i).Utf8(),
84                                      "role")) {
85         if (base::LowerCaseEqualsASCII(element.AttributeValue(i).Utf8(),
86                                        "textbox")) {
87           return true;
88         }
89         break;
90       }
91     }
92   }
93 
94   return false;
95 }
96 
IsFormControlElement()97 bool CefDOMNodeImpl::IsFormControlElement() {
98   if (!VerifyContext())
99     return false;
100 
101   if (node_.IsElementNode()) {
102     const WebElement& element = node_.ToConst<WebElement>();
103     return element.IsFormControlElement();
104   }
105 
106   return false;
107 }
108 
GetFormControlElementType()109 CefString CefDOMNodeImpl::GetFormControlElementType() {
110   CefString str;
111   if (!VerifyContext())
112     return str;
113 
114   if (node_.IsElementNode()) {
115     const WebElement& element = node_.ToConst<WebElement>();
116     if (element.IsFormControlElement()) {
117       // Retrieve the type from the form control element.
118       const WebFormControlElement& formElement =
119           node_.ToConst<WebFormControlElement>();
120 
121       const std::u16string& form_control_type =
122           formElement.FormControlType().Utf16();
123       str = form_control_type;
124     }
125   }
126 
127   return str;
128 }
129 
IsSame(CefRefPtr<CefDOMNode> that)130 bool CefDOMNodeImpl::IsSame(CefRefPtr<CefDOMNode> that) {
131   if (!VerifyContext())
132     return false;
133 
134   CefDOMNodeImpl* impl = static_cast<CefDOMNodeImpl*>(that.get());
135   if (!impl || !impl->VerifyContext())
136     return false;
137 
138   return node_.Equals(impl->node_);
139 }
140 
GetName()141 CefString CefDOMNodeImpl::GetName() {
142   CefString str;
143   if (!VerifyContext())
144     return str;
145 
146   const WebString& name = blink_glue::GetNodeName(node_);
147   if (!name.IsNull())
148     str = name.Utf16();
149 
150   return str;
151 }
152 
GetValue()153 CefString CefDOMNodeImpl::GetValue() {
154   CefString str;
155   if (!VerifyContext())
156     return str;
157 
158   if (node_.IsElementNode()) {
159     const WebElement& element = node_.ToConst<WebElement>();
160     if (element.IsFormControlElement()) {
161       // Retrieve the value from the form control element.
162       const WebFormControlElement& formElement =
163           node_.ToConst<WebFormControlElement>();
164 
165       std::u16string value;
166       const std::u16string& form_control_type =
167           formElement.FormControlType().Utf16();
168       if (form_control_type == u"text") {
169         const WebInputElement& input_element =
170             formElement.ToConst<WebInputElement>();
171         value = input_element.Value().Utf16();
172       } else if (form_control_type == u"select-one") {
173         const WebSelectElement& select_element =
174             formElement.ToConst<WebSelectElement>();
175         value = select_element.Value().Utf16();
176       }
177 
178       base::TrimWhitespace(value, base::TRIM_LEADING, &value);
179       str = value;
180     }
181   }
182 
183   if (str.empty()) {
184     const WebString& value = node_.NodeValue();
185     if (!value.IsNull())
186       str = value.Utf16();
187   }
188 
189   return str;
190 }
191 
SetValue(const CefString & value)192 bool CefDOMNodeImpl::SetValue(const CefString& value) {
193   if (!VerifyContext())
194     return false;
195 
196   if (node_.IsElementNode())
197     return false;
198 
199   return blink_glue::SetNodeValue(node_,
200                                   WebString::FromUTF16(value.ToString16()));
201 }
202 
GetAsMarkup()203 CefString CefDOMNodeImpl::GetAsMarkup() {
204   CefString str;
205   if (!VerifyContext())
206     return str;
207 
208   const WebString& markup = blink_glue::CreateNodeMarkup(node_);
209   if (!markup.IsNull())
210     str = markup.Utf16();
211 
212   return str;
213 }
214 
GetDocument()215 CefRefPtr<CefDOMDocument> CefDOMNodeImpl::GetDocument() {
216   if (!VerifyContext())
217     return nullptr;
218 
219   return document_.get();
220 }
221 
GetParent()222 CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetParent() {
223   if (!VerifyContext())
224     return nullptr;
225 
226   return document_->GetOrCreateNode(node_.ParentNode());
227 }
228 
GetPreviousSibling()229 CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetPreviousSibling() {
230   if (!VerifyContext())
231     return nullptr;
232 
233   return document_->GetOrCreateNode(node_.PreviousSibling());
234 }
235 
GetNextSibling()236 CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetNextSibling() {
237   if (!VerifyContext())
238     return nullptr;
239 
240   return document_->GetOrCreateNode(node_.NextSibling());
241 }
242 
HasChildren()243 bool CefDOMNodeImpl::HasChildren() {
244   if (!VerifyContext())
245     return false;
246 
247   return !node_.FirstChild().IsNull();
248 }
249 
GetFirstChild()250 CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetFirstChild() {
251   if (!VerifyContext())
252     return nullptr;
253 
254   return document_->GetOrCreateNode(node_.FirstChild());
255 }
256 
GetLastChild()257 CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetLastChild() {
258   if (!VerifyContext())
259     return nullptr;
260 
261   return document_->GetOrCreateNode(node_.LastChild());
262 }
263 
GetElementTagName()264 CefString CefDOMNodeImpl::GetElementTagName() {
265   CefString str;
266   if (!VerifyContext())
267     return str;
268 
269   if (!node_.IsElementNode()) {
270     NOTREACHED();
271     return str;
272   }
273 
274   const WebElement& element = node_.ToConst<blink::WebElement>();
275   const WebString& tagname = element.TagName();
276   if (!tagname.IsNull())
277     str = tagname.Utf16();
278 
279   return str;
280 }
281 
HasElementAttributes()282 bool CefDOMNodeImpl::HasElementAttributes() {
283   if (!VerifyContext())
284     return false;
285 
286   if (!node_.IsElementNode()) {
287     NOTREACHED();
288     return false;
289   }
290 
291   const WebElement& element = node_.ToConst<blink::WebElement>();
292   return (element.AttributeCount() > 0);
293 }
294 
HasElementAttribute(const CefString & attrName)295 bool CefDOMNodeImpl::HasElementAttribute(const CefString& attrName) {
296   if (!VerifyContext())
297     return false;
298 
299   if (!node_.IsElementNode()) {
300     NOTREACHED();
301     return false;
302   }
303 
304   const WebElement& element = node_.ToConst<blink::WebElement>();
305   return element.HasAttribute(WebString::FromUTF16(attrName.ToString16()));
306 }
307 
GetElementAttribute(const CefString & attrName)308 CefString CefDOMNodeImpl::GetElementAttribute(const CefString& attrName) {
309   CefString str;
310   if (!VerifyContext())
311     return str;
312 
313   if (!node_.IsElementNode()) {
314     NOTREACHED();
315     return str;
316   }
317 
318   const WebElement& element = node_.ToConst<blink::WebElement>();
319   const WebString& attr =
320       element.GetAttribute(WebString::FromUTF16(attrName.ToString16()));
321   if (!attr.IsNull())
322     str = attr.Utf16();
323 
324   return str;
325 }
326 
GetElementAttributes(AttributeMap & attrMap)327 void CefDOMNodeImpl::GetElementAttributes(AttributeMap& attrMap) {
328   if (!VerifyContext())
329     return;
330 
331   if (!node_.IsElementNode()) {
332     NOTREACHED();
333     return;
334   }
335 
336   const WebElement& element = node_.ToConst<blink::WebElement>();
337   unsigned int len = element.AttributeCount();
338   if (len == 0)
339     return;
340 
341   for (unsigned int i = 0; i < len; ++i) {
342     std::u16string name = element.AttributeLocalName(i).Utf16();
343     std::u16string value = element.AttributeValue(i).Utf16();
344     attrMap.insert(std::make_pair(name, value));
345   }
346 }
347 
SetElementAttribute(const CefString & attrName,const CefString & value)348 bool CefDOMNodeImpl::SetElementAttribute(const CefString& attrName,
349                                          const CefString& value) {
350   if (!VerifyContext())
351     return false;
352 
353   if (!node_.IsElementNode()) {
354     NOTREACHED();
355     return false;
356   }
357 
358   WebElement element = node_.To<blink::WebElement>();
359   element.SetAttribute(WebString::FromUTF16(attrName.ToString16()),
360                        WebString::FromUTF16(value.ToString16()));
361   return true;
362 }
363 
GetElementInnerText()364 CefString CefDOMNodeImpl::GetElementInnerText() {
365   CefString str;
366   if (!VerifyContext())
367     return str;
368 
369   if (!node_.IsElementNode()) {
370     NOTREACHED();
371     return str;
372   }
373 
374   WebElement element = node_.To<blink::WebElement>();
375   const WebString& text = element.TextContent();
376   if (!text.IsNull())
377     str = text.Utf16();
378 
379   return str;
380 }
381 
GetElementBounds()382 CefRect CefDOMNodeImpl::GetElementBounds() {
383   CefRect rect;
384   if (!VerifyContext())
385     return rect;
386 
387   if (!node_.IsElementNode()) {
388     NOTREACHED();
389     return rect;
390   }
391 
392   WebElement element = node_.To<blink::WebElement>();
393   const auto& rc = element.BoundsInViewport();
394   rect.Set(rc.x(), rc.y(), rc.width(), rc.height());
395 
396   return rect;
397 }
398 
Detach()399 void CefDOMNodeImpl::Detach() {
400   document_ = nullptr;
401   node_.Assign(WebNode());
402 }
403 
VerifyContext()404 bool CefDOMNodeImpl::VerifyContext() {
405   if (!document_.get()) {
406     NOTREACHED();
407     return false;
408   }
409   if (!document_->VerifyContext())
410     return false;
411   if (node_.IsNull()) {
412     NOTREACHED();
413     return false;
414   }
415   return true;
416 }
417