• 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_document_impl.h"
6 #include "libcef/renderer/dom_node_impl.h"
7 #include "libcef/renderer/thread_util.h"
8 
9 #include "base/logging.h"
10 #include "third_party/blink/public/platform/web_string.h"
11 #include "third_party/blink/public/platform/web_url.h"
12 #include "third_party/blink/public/web/web_document.h"
13 #include "third_party/blink/public/web/web_element.h"
14 #include "third_party/blink/public/web/web_local_frame.h"
15 #include "third_party/blink/public/web/web_node.h"
16 #include "third_party/blink/public/web/web_range.h"
17 
18 using blink::WebDocument;
19 using blink::WebElement;
20 using blink::WebLocalFrame;
21 using blink::WebNode;
22 using blink::WebRange;
23 using blink::WebString;
24 using blink::WebURL;
25 
CefDOMDocumentImpl(CefBrowserImpl * browser,WebLocalFrame * frame)26 CefDOMDocumentImpl::CefDOMDocumentImpl(CefBrowserImpl* browser,
27                                        WebLocalFrame* frame)
28     : browser_(browser), frame_(frame) {
29   const WebDocument& document = frame_->GetDocument();
30   DCHECK(!document.IsNull());
31 }
32 
~CefDOMDocumentImpl()33 CefDOMDocumentImpl::~CefDOMDocumentImpl() {
34   CEF_REQUIRE_RT();
35 
36   // Verify that the Detach() method has been called.
37   DCHECK(frame_ == nullptr);
38 }
39 
GetType()40 CefDOMDocumentImpl::Type CefDOMDocumentImpl::GetType() {
41   if (!VerifyContext())
42     return DOM_DOCUMENT_TYPE_UNKNOWN;
43 
44   const WebDocument& document = frame_->GetDocument();
45   if (document.IsHTMLDocument())
46     return DOM_DOCUMENT_TYPE_HTML;
47   if (document.IsXHTMLDocument())
48     return DOM_DOCUMENT_TYPE_XHTML;
49   if (document.IsPluginDocument())
50     return DOM_DOCUMENT_TYPE_PLUGIN;
51   return DOM_DOCUMENT_TYPE_UNKNOWN;
52 }
53 
GetDocument()54 CefRefPtr<CefDOMNode> CefDOMDocumentImpl::GetDocument() {
55   const WebDocument& document = frame_->GetDocument();
56   return GetOrCreateNode(document.GetDocument());
57 }
58 
GetBody()59 CefRefPtr<CefDOMNode> CefDOMDocumentImpl::GetBody() {
60   const WebDocument& document = frame_->GetDocument();
61   return GetOrCreateNode(document.Body());
62 }
63 
GetHead()64 CefRefPtr<CefDOMNode> CefDOMDocumentImpl::GetHead() {
65   WebDocument document = frame_->GetDocument();
66   return GetOrCreateNode(document.Head());
67 }
68 
GetTitle()69 CefString CefDOMDocumentImpl::GetTitle() {
70   CefString str;
71   if (!VerifyContext())
72     return str;
73 
74   const WebDocument& document = frame_->GetDocument();
75   const WebString& title = document.Title();
76   if (!title.IsNull())
77     str = title.Utf16();
78 
79   return str;
80 }
81 
GetElementById(const CefString & id)82 CefRefPtr<CefDOMNode> CefDOMDocumentImpl::GetElementById(const CefString& id) {
83   const WebDocument& document = frame_->GetDocument();
84   return GetOrCreateNode(
85       document.GetElementById(WebString::FromUTF16(id.ToString16())));
86 }
87 
GetFocusedNode()88 CefRefPtr<CefDOMNode> CefDOMDocumentImpl::GetFocusedNode() {
89   const WebDocument& document = frame_->GetDocument();
90   return GetOrCreateNode(document.FocusedElement());
91 }
92 
HasSelection()93 bool CefDOMDocumentImpl::HasSelection() {
94   if (!VerifyContext())
95     return false;
96 
97   return frame_->HasSelection();
98 }
99 
GetSelectionStartOffset()100 int CefDOMDocumentImpl::GetSelectionStartOffset() {
101   if (!VerifyContext())
102     return 0;
103 
104   if (!frame_->HasSelection())
105     return 0;
106 
107   const WebRange& range = frame_->SelectionRange();
108   if (range.IsNull())
109     return 0;
110 
111   return range.StartOffset();
112 }
113 
GetSelectionEndOffset()114 int CefDOMDocumentImpl::GetSelectionEndOffset() {
115   if (!VerifyContext())
116     return 0;
117 
118   if (!frame_->HasSelection())
119     return 0;
120 
121   const WebRange& range = frame_->SelectionRange();
122   if (range.IsNull())
123     return 0;
124 
125   return range.EndOffset();
126 }
127 
GetSelectionAsMarkup()128 CefString CefDOMDocumentImpl::GetSelectionAsMarkup() {
129   CefString str;
130   if (!VerifyContext())
131     return str;
132 
133   if (!frame_->HasSelection())
134     return str;
135 
136   const WebString& markup = frame_->SelectionAsMarkup();
137   if (!markup.IsNull())
138     str = markup.Utf16();
139 
140   return str;
141 }
142 
GetSelectionAsText()143 CefString CefDOMDocumentImpl::GetSelectionAsText() {
144   CefString str;
145   if (!VerifyContext())
146     return str;
147 
148   if (!frame_->HasSelection())
149     return str;
150 
151   const WebString& text = frame_->SelectionAsText();
152   if (!text.IsNull())
153     str = text.Utf16();
154 
155   return str;
156 }
157 
GetBaseURL()158 CefString CefDOMDocumentImpl::GetBaseURL() {
159   CefString str;
160   if (!VerifyContext())
161     return str;
162 
163   const WebDocument& document = frame_->GetDocument();
164   const WebURL& url = document.BaseURL();
165   if (!url.IsNull()) {
166     GURL gurl = url;
167     str = gurl.spec();
168   }
169 
170   return str;
171 }
172 
GetCompleteURL(const CefString & partialURL)173 CefString CefDOMDocumentImpl::GetCompleteURL(const CefString& partialURL) {
174   CefString str;
175   if (!VerifyContext())
176     return str;
177 
178   const WebDocument& document = frame_->GetDocument();
179   const WebURL& url =
180       document.CompleteURL(WebString::FromUTF16(partialURL.ToString16()));
181   if (!url.IsNull()) {
182     GURL gurl = url;
183     str = gurl.spec();
184   }
185 
186   return str;
187 }
188 
GetOrCreateNode(const blink::WebNode & node)189 CefRefPtr<CefDOMNode> CefDOMDocumentImpl::GetOrCreateNode(
190     const blink::WebNode& node) {
191   if (!VerifyContext())
192     return nullptr;
193 
194   // Nodes may potentially be null.
195   if (node.IsNull())
196     return nullptr;
197 
198   if (!node_map_.empty()) {
199     // Locate the existing node, if any.
200     NodeMap::const_iterator it = node_map_.find(node);
201     if (it != node_map_.end())
202       return it->second;
203   }
204 
205   // Create the new node object.
206   CefRefPtr<CefDOMNode> nodeImpl(new CefDOMNodeImpl(this, node));
207   node_map_.insert(std::make_pair(node, nodeImpl.get()));
208   return nodeImpl;
209 }
210 
RemoveNode(const blink::WebNode & node)211 void CefDOMDocumentImpl::RemoveNode(const blink::WebNode& node) {
212   if (!VerifyContext())
213     return;
214 
215   if (!node_map_.empty()) {
216     NodeMap::iterator it = node_map_.find(node);
217     if (it != node_map_.end())
218       node_map_.erase(it);
219   }
220 }
221 
Detach()222 void CefDOMDocumentImpl::Detach() {
223   if (!VerifyContext())
224     return;
225 
226   // If you hit this assert it means that you are keeping references to node
227   // objects beyond the valid scope.
228   DCHECK(node_map_.empty());
229 
230   // If you hit this assert it means that you are keeping references to this
231   // document object beyond the valid scope.
232   DCHECK(HasOneRef());
233 
234   if (!node_map_.empty()) {
235     NodeMap::const_iterator it = node_map_.begin();
236     for (; it != node_map_.end(); ++it)
237       static_cast<CefDOMNodeImpl*>(it->second)->Detach();
238     node_map_.clear();
239   }
240 
241   frame_ = nullptr;
242 }
243 
VerifyContext()244 bool CefDOMDocumentImpl::VerifyContext() {
245   if (!CEF_CURRENTLY_ON_RT() || frame_ == nullptr) {
246     NOTREACHED();
247     return false;
248   }
249   return true;
250 }
251