1 /*
2 * Copyright (C) 2007 Kevin Ollivier All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "CString.h"
28 #include "Document.h"
29 #include "Editor.h"
30 #include "Element.h"
31 #include "EventHandler.h"
32 #include "Frame.h"
33 #include "FrameLoader.h"
34 #include "FrameView.h"
35 #include "HitTestResult.h"
36 #include "HTMLFrameOwnerElement.h"
37 #include "markup.h"
38 #include "Page.h"
39 #include "PlatformString.h"
40 #include "RenderTreeAsText.h"
41 #include "RenderObject.h"
42 #include "RenderView.h"
43 #include "ScriptController.h"
44 #include "ScriptValue.h"
45 #include "TextEncoding.h"
46
47 #include "JSDOMBinding.h"
48 #include <runtime/JSValue.h>
49 #include <runtime/UString.h>
50
51 #include "EditorClientWx.h"
52 #include "FrameLoaderClientWx.h"
53
54 #include "wx/wxprec.h"
55 #ifndef WX_PRECOMP
56 #include "wx/wx.h"
57 #endif
58
59 #include "WebFrame.h"
60 #include "WebView.h"
61 #include "WebFramePrivate.h"
62 #include "WebViewPrivate.h"
63
64 #include <wx/defs.h>
65 #include <wx/dcbuffer.h>
66
67 // Match Safari's min/max zoom sizes by default
68 #define MinimumTextSizeMultiplier 0.5f
69 #define MaximumTextSizeMultiplier 3.0f
70 #define TextSizeMultiplierRatio 1.2f
71
wxWebFrame(wxWebView * container,wxWebFrame * parent,WebViewFrameData * data)72 wxWebFrame::wxWebFrame(wxWebView* container, wxWebFrame* parent, WebViewFrameData* data) :
73 m_textMagnifier(1.0),
74 m_isEditable(false),
75 m_isInitialized(false),
76 m_beingDestroyed(false),
77 m_title(wxEmptyString)
78 {
79
80 m_impl = new WebFramePrivate();
81
82 WebCore::HTMLFrameOwnerElement* parentFrame = 0;
83
84 if (data) {
85 parentFrame = data->ownerElement;
86 }
87
88 WebCore::FrameLoaderClientWx* loaderClient = new WebCore::FrameLoaderClientWx();
89
90 m_impl->frame = WebCore::Frame::create(container->m_impl->page, parentFrame, loaderClient);
91 m_impl->frame->deref();
92
93 loaderClient->setFrame(m_impl->frame.get());
94 loaderClient->setWebView(container);
95
96 m_impl->frame->init();
97
98 m_isInitialized = true;
99 }
100
~wxWebFrame()101 wxWebFrame::~wxWebFrame()
102 {
103 m_impl->frame->loader()->detachFromParent();
104 }
105
GetFrame()106 WebCore::Frame* wxWebFrame::GetFrame()
107 {
108 if (m_impl)
109 return m_impl->frame.get();
110
111 return 0;
112 }
113
Stop()114 void wxWebFrame::Stop()
115 {
116 if (m_impl->frame && m_impl->frame->loader())
117 m_impl->frame->loader()->stop();
118 }
119
Reload()120 void wxWebFrame::Reload()
121 {
122 if (m_impl->frame && m_impl->frame->loader())
123 m_impl->frame->loader()->reload();
124 }
125
GetPageSource()126 wxString wxWebFrame::GetPageSource()
127 {
128 if (m_impl->frame) {
129 if (m_impl->frame->view() && m_impl->frame->view()->layoutPending())
130 m_impl->frame->view()->layout();
131
132 WebCore::Document* doc = m_impl->frame->document();
133
134 if (doc) {
135 wxString source = createMarkup(doc);
136 return source;
137 }
138 }
139 return wxEmptyString;
140 }
141
SetPageSource(const wxString & source,const wxString & baseUrl)142 void wxWebFrame::SetPageSource(const wxString& source, const wxString& baseUrl)
143 {
144 if (m_impl->frame && m_impl->frame->loader()) {
145 WebCore::FrameLoader* loader = m_impl->frame->loader();
146 loader->begin(WebCore::KURL(WebCore::KURL(), static_cast<const char*>(baseUrl.mb_str(wxConvUTF8)), WebCore::UTF8Encoding()));
147 loader->write(static_cast<const WebCore::String>(source));
148 loader->end();
149 }
150 }
151
GetInnerText()152 wxString wxWebFrame::GetInnerText()
153 {
154 if (m_impl->frame->view() && m_impl->frame->view()->layoutPending())
155 m_impl->frame->view()->layout();
156
157 WebCore::Element *documentElement = m_impl->frame->document()->documentElement();
158 return documentElement->innerText();
159 }
160
GetAsMarkup()161 wxString wxWebFrame::GetAsMarkup()
162 {
163 if (!m_impl->frame || !m_impl->frame->document())
164 return wxEmptyString;
165
166 return createMarkup(m_impl->frame->document());
167 }
168
GetExternalRepresentation()169 wxString wxWebFrame::GetExternalRepresentation()
170 {
171 if (m_impl->frame->view() && m_impl->frame->view()->layoutPending())
172 m_impl->frame->view()->layout();
173
174 return externalRepresentation(m_impl->frame->contentRenderer());
175 }
176
RunScript(const wxString & javascript)177 wxString wxWebFrame::RunScript(const wxString& javascript)
178 {
179 wxString returnValue = wxEmptyString;
180 if (m_impl->frame) {
181 JSC::JSValue result = m_impl->frame->loader()->executeScript(javascript, true).jsValue();
182 if (result)
183 returnValue = wxString(result.toString(m_impl->frame->script()->globalObject()->globalExec()).UTF8String().c_str(), wxConvUTF8);
184 }
185 return returnValue;
186 }
187
FindString(const wxString & string,bool forward,bool caseSensitive,bool wrapSelection,bool startInSelection)188 bool wxWebFrame::FindString(const wxString& string, bool forward, bool caseSensitive, bool wrapSelection, bool startInSelection)
189 {
190 if (m_impl->frame)
191 return m_impl->frame->findString(string, forward, caseSensitive, wrapSelection, startInSelection);
192
193 return false;
194 }
195
LoadURL(const wxString & url)196 void wxWebFrame::LoadURL(const wxString& url)
197 {
198 if (m_impl->frame && m_impl->frame->loader()) {
199 WebCore::KURL kurl = WebCore::KURL(WebCore::KURL(), static_cast<const char*>(url.mb_str(wxConvUTF8)), WebCore::UTF8Encoding());
200 // NB: This is an ugly fix, but CURL won't load sub-resources if the
201 // protocol is omitted; sadly, it will not emit an error, either, so
202 // there's no way for us to catch this problem the correct way yet.
203 if (kurl.protocol().isEmpty()) {
204 // is it a file on disk?
205 if (wxFileExists(url)) {
206 kurl.setProtocol("file");
207 kurl.setPath("//" + kurl.path());
208 }
209 else {
210 kurl.setProtocol("http");
211 kurl.setPath("//" + kurl.path());
212 }
213 }
214 m_impl->frame->loader()->load(kurl, false);
215 }
216 }
217
GoBack()218 bool wxWebFrame::GoBack()
219 {
220 if (m_impl->frame && m_impl->frame->page())
221 return m_impl->frame->page()->goBack();
222
223 return false;
224 }
225
GoForward()226 bool wxWebFrame::GoForward()
227 {
228 if (m_impl->frame && m_impl->frame->page())
229 return m_impl->frame->page()->goForward();
230
231 return false;
232 }
233
CanGoBack()234 bool wxWebFrame::CanGoBack()
235 {
236 if (m_impl->frame && m_impl->frame->page() && m_impl->frame->page()->backForwardList())
237 return m_impl->frame->page()->backForwardList()->backItem() != NULL;
238
239 return false;
240 }
241
CanGoForward()242 bool wxWebFrame::CanGoForward()
243 {
244 if (m_impl->frame && m_impl->frame->page() && m_impl->frame->page()->backForwardList())
245 return m_impl->frame->page()->backForwardList()->forwardItem() != NULL;
246
247 return false;
248 }
249
Undo()250 void wxWebFrame::Undo()
251 {
252 if (m_impl->frame && m_impl->frame->editor() && CanUndo())
253 return m_impl->frame->editor()->undo();
254 }
255
Redo()256 void wxWebFrame::Redo()
257 {
258 if (m_impl->frame && m_impl->frame->editor() && CanRedo())
259 return m_impl->frame->editor()->redo();
260 }
261
CanUndo()262 bool wxWebFrame::CanUndo()
263 {
264 if (m_impl->frame && m_impl->frame->editor())
265 return m_impl->frame->editor()->canUndo();
266
267 return false;
268 }
269
CanRedo()270 bool wxWebFrame::CanRedo()
271 {
272 if (m_impl->frame && m_impl->frame->editor())
273 return m_impl->frame->editor()->canRedo();
274
275 return false;
276 }
277
CanIncreaseTextSize() const278 bool wxWebFrame::CanIncreaseTextSize() const
279 {
280 if (m_impl->frame) {
281 if (m_textMagnifier*TextSizeMultiplierRatio <= MaximumTextSizeMultiplier)
282 return true;
283 }
284 return false;
285 }
286
IncreaseTextSize()287 void wxWebFrame::IncreaseTextSize()
288 {
289 if (CanIncreaseTextSize()) {
290 m_textMagnifier = m_textMagnifier*TextSizeMultiplierRatio;
291 m_impl->frame->setZoomFactor(m_textMagnifier, true);
292 }
293 }
294
CanDecreaseTextSize() const295 bool wxWebFrame::CanDecreaseTextSize() const
296 {
297 if (m_impl->frame) {
298 if (m_textMagnifier/TextSizeMultiplierRatio >= MinimumTextSizeMultiplier)
299 return true;
300 }
301 return false;
302 }
303
DecreaseTextSize()304 void wxWebFrame::DecreaseTextSize()
305 {
306 if (CanDecreaseTextSize()) {
307 m_textMagnifier = m_textMagnifier/TextSizeMultiplierRatio;
308 m_impl->frame->setZoomFactor(m_textMagnifier, true);
309 }
310 }
311
ResetTextSize()312 void wxWebFrame::ResetTextSize()
313 {
314 m_textMagnifier = 1.0;
315 if (m_impl->frame)
316 m_impl->frame->setZoomFactor(m_textMagnifier, true);
317 }
318
MakeEditable(bool enable)319 void wxWebFrame::MakeEditable(bool enable)
320 {
321 m_isEditable = enable;
322 }
323
324
325
CanCopy()326 bool wxWebFrame::CanCopy()
327 {
328 if (m_impl->frame && m_impl->frame->view())
329 return (m_impl->frame->editor()->canCopy() || m_impl->frame->editor()->canDHTMLCopy());
330
331 return false;
332 }
333
Copy()334 void wxWebFrame::Copy()
335 {
336 if (CanCopy())
337 m_impl->frame->editor()->copy();
338 }
339
CanCut()340 bool wxWebFrame::CanCut()
341 {
342 if (m_impl->frame && m_impl->frame->view())
343 return (m_impl->frame->editor()->canCut() || m_impl->frame->editor()->canDHTMLCut());
344
345 return false;
346 }
347
Cut()348 void wxWebFrame::Cut()
349 {
350 if (CanCut())
351 m_impl->frame->editor()->cut();
352 }
353
CanPaste()354 bool wxWebFrame::CanPaste()
355 {
356 if (m_impl->frame && m_impl->frame->view())
357 return (m_impl->frame->editor()->canPaste() || m_impl->frame->editor()->canDHTMLPaste());
358
359 return false;
360 }
361
Paste()362 void wxWebFrame::Paste()
363 {
364 if (CanPaste())
365 m_impl->frame->editor()->paste();
366
367 }
368
HitTest(const wxPoint & pos) const369 wxWebViewDOMElementInfo wxWebFrame::HitTest(const wxPoint& pos) const
370 {
371 wxWebViewDOMElementInfo domInfo;
372
373 if (m_impl->frame->view()) {
374 WebCore::HitTestResult result = m_impl->frame->eventHandler()->hitTestResultAtPoint(m_impl->frame->view()->windowToContents(pos), false);
375 if (result.innerNode()) {
376 domInfo.SetLink(result.absoluteLinkURL().string());
377 domInfo.SetText(result.textContent());
378 domInfo.SetImageSrc(result.absoluteImageURL().string());
379 domInfo.SetSelected(result.isSelected());
380 }
381 }
382
383 return domInfo;
384 }
385
386