Reviewed by Kevin Ollivier.
[WebKit.git] / WebKit / wx / WebFrame.cpp
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 "RenderTreeAsText.h"
40 #include "RenderObject.h"
41 #include "RenderView.h"
42
43 #include "EditorClientWx.h"
44 #include "FrameLoaderClientWx.h"
45
46 #include "ScriptController.h"
47 #include "ScriptValue.h"
48 #include "JSDOMBinding.h"
49 #include <runtime/JSValue.h>
50 #include <runtime/UString.h>
51
52 #include "wx/wxprec.h"
53 #ifndef WX_PRECOMP
54     #include "wx/wx.h"
55 #endif
56
57 #include "WebFrame.h"
58 #include "WebView.h"
59 #include "WebFramePrivate.h"
60 #include "WebViewPrivate.h"
61
62 #include <wx/defs.h>
63 #include <wx/dcbuffer.h>
64
65 // Match Safari's min/max zoom sizes by default
66 #define MinimumTextSizeMultiplier       0.5f
67 #define MaximumTextSizeMultiplier       3.0f
68 #define TextSizeMultiplierRatio         1.2f
69
70 wxWebFrame::wxWebFrame(wxWebView* container, wxWebFrame* parent, WebViewFrameData* data) :
71     m_textMagnifier(1.0),
72     m_isEditable(false),
73     m_isInitialized(false),
74     m_beingDestroyed(false),
75     m_title(wxEmptyString)
76 {
77
78     m_impl = new WebFramePrivate();
79  
80     WebCore::HTMLFrameOwnerElement* parentFrame = 0;
81     
82     if (data) {
83         parentFrame = data->ownerElement;
84     }
85     
86     WebCore::FrameLoaderClientWx* loaderClient = new WebCore::FrameLoaderClientWx();
87     
88     m_impl->frame = WebCore::Frame::create(container->m_impl->page, parentFrame, loaderClient);
89     m_impl->frame->deref();
90
91     loaderClient->setFrame(m_impl->frame.get());
92     loaderClient->setWebView(container);
93     
94     m_impl->frame->init();
95         
96     m_isInitialized = true;
97 }
98
99 wxWebFrame::~wxWebFrame()
100 {
101     m_impl->frame->loader()->detachFromParent();
102 }
103
104 WebCore::Frame* wxWebFrame::GetFrame()
105 {
106     if (m_impl)
107         return m_impl->frame.get();
108         
109     return 0;
110 }
111
112 void wxWebFrame::Stop()
113 {
114     if (m_impl->frame && m_impl->frame->loader())
115         m_impl->frame->loader()->stop();
116 }
117
118 void wxWebFrame::Reload()
119 {
120     if (m_impl->frame && m_impl->frame->loader())
121         m_impl->frame->loader()->reload();
122 }
123
124 wxString wxWebFrame::GetPageSource()
125 {
126     if (m_impl->frame) {
127         if (m_impl->frame->view() && m_impl->frame->view()->layoutPending())
128             m_impl->frame->view()->layout();
129     
130         WebCore::Document* doc = m_impl->frame->document();
131         
132         if (doc) {
133             wxString source = createMarkup(doc);
134             return source;
135         }
136     }
137     return wxEmptyString;
138 }
139
140 void wxWebFrame::SetPageSource(const wxString& source, const wxString& baseUrl)
141 {
142     if (m_impl->frame && m_impl->frame->loader()) {
143         WebCore::FrameLoader* loader = m_impl->frame->loader();
144         loader->begin(WebCore::KURL(static_cast<const char*>(baseUrl.mb_str(wxConvUTF8))));
145         loader->write(source);
146         loader->end();
147     }
148 }
149
150 wxString wxWebFrame::GetInnerText()
151 {
152     if (m_impl->frame->view() && m_impl->frame->view()->layoutPending())
153         m_impl->frame->view()->layout();
154         
155     WebCore::Element *documentElement = m_impl->frame->document()->documentElement();
156     return documentElement->innerText();
157 }
158
159 wxString wxWebFrame::GetAsMarkup()
160 {
161     if (!m_impl->frame || !m_impl->frame->document())
162         return wxEmptyString;
163
164     return createMarkup(m_impl->frame->document());
165 }
166
167 wxString wxWebFrame::GetExternalRepresentation()
168 {
169     if (m_impl->frame->view() && m_impl->frame->view()->layoutPending())
170         m_impl->frame->view()->layout();
171
172     return externalRepresentation(m_impl->frame->contentRenderer());
173 }
174
175 wxString wxWebFrame::RunScript(const wxString& javascript)
176 {
177     wxString returnValue = wxEmptyString;
178     if (m_impl->frame) {
179         JSC::JSValue* result = m_impl->frame->loader()->executeScript(javascript, true).jsValue();
180         if (result)
181             returnValue = wxString(result->toString(m_impl->frame->script()->globalObject()->globalExec()).UTF8String().c_str(), wxConvUTF8);        
182     }
183     return returnValue;
184 }
185
186 void wxWebFrame::LoadURL(const wxString& url)
187 {
188     if (m_impl->frame && m_impl->frame->loader()) {
189         WebCore::KURL kurl = WebCore::KURL(static_cast<const char*>(url.mb_str(wxConvUTF8)));
190         // NB: This is an ugly fix, but CURL won't load sub-resources if the
191         // protocol is omitted; sadly, it will not emit an error, either, so
192         // there's no way for us to catch this problem the correct way yet.
193         if (kurl.protocol().isEmpty()) {
194             // is it a file on disk?
195             if (wxFileExists(url)) {
196                 kurl.setProtocol("file");
197                 kurl.setPath("//" + kurl.path());
198             }
199             else {
200                 kurl.setProtocol("http");
201                 kurl.setPath("//" + kurl.path());
202             }
203         }
204         m_impl->frame->loader()->load(kurl);
205     }
206 }
207
208 bool wxWebFrame::GoBack()
209 {
210     if (m_impl->frame && m_impl->frame->page())
211         return m_impl->frame->page()->goBack();
212
213     return false;
214 }
215
216 bool wxWebFrame::GoForward()
217 {
218     if (m_impl->frame && m_impl->frame->page())
219         return m_impl->frame->page()->goForward();
220
221     return false;
222 }
223
224 bool wxWebFrame::CanGoBack()
225 {
226     if (m_impl->frame && m_impl->frame->page() && m_impl->frame->page()->backForwardList())
227         return m_impl->frame->page()->backForwardList()->backItem() != NULL;
228
229     return false;
230 }
231
232 bool wxWebFrame::CanGoForward()
233 {
234     if (m_impl->frame && m_impl->frame->page() && m_impl->frame->page()->backForwardList())
235         return m_impl->frame->page()->backForwardList()->forwardItem() != NULL;
236
237     return false;
238 }
239
240 void wxWebFrame::Undo()
241 {
242     if (m_impl->frame && m_impl->frame->editor() && CanUndo())
243         return m_impl->frame->editor()->undo();
244 }
245
246 void wxWebFrame::Redo()
247 {
248     if (m_impl->frame && m_impl->frame->editor() && CanRedo())
249         return m_impl->frame->editor()->redo();
250 }
251
252 bool wxWebFrame::CanUndo()
253 {
254     if (m_impl->frame && m_impl->frame->editor())
255         return m_impl->frame->editor()->canUndo();
256
257     return false;
258 }
259
260 bool wxWebFrame::CanRedo()
261 {
262     if (m_impl->frame && m_impl->frame->editor())
263         return m_impl->frame->editor()->canRedo();
264
265     return false;
266 }
267
268 bool wxWebFrame::CanIncreaseTextSize() const
269 {
270     if (m_impl->frame) {
271         if (m_textMagnifier*TextSizeMultiplierRatio <= MaximumTextSizeMultiplier)
272             return true;
273     }
274     return false;
275 }
276
277 void wxWebFrame::IncreaseTextSize()
278 {
279     if (CanIncreaseTextSize()) {
280         m_textMagnifier = m_textMagnifier*TextSizeMultiplierRatio;
281         m_impl->frame->setZoomFactor(m_textMagnifier, true);
282     }
283 }
284
285 bool wxWebFrame::CanDecreaseTextSize() const
286 {
287     if (m_impl->frame) {
288         if (m_textMagnifier/TextSizeMultiplierRatio >= MinimumTextSizeMultiplier)
289             return true;
290     }
291     return false;
292 }
293
294 void wxWebFrame::DecreaseTextSize()
295 {        
296     if (CanDecreaseTextSize()) {
297         m_textMagnifier = m_textMagnifier/TextSizeMultiplierRatio;
298         m_impl->frame->setZoomFactor(m_textMagnifier, true);
299     }
300 }
301
302 void wxWebFrame::MakeEditable(bool enable)
303 {
304     m_isEditable = enable;
305 }
306
307
308
309 bool wxWebFrame::CanCopy()
310 {
311     if (m_impl->frame && m_impl->frame->view())
312         return (m_impl->frame->editor()->canCopy() || m_impl->frame->editor()->canDHTMLCopy());
313
314     return false;
315 }
316
317 void wxWebFrame::Copy()
318 {
319     if (CanCopy())
320         m_impl->frame->editor()->copy();
321 }
322
323 bool wxWebFrame::CanCut()
324 {
325     if (m_impl->frame && m_impl->frame->view())
326         return (m_impl->frame->editor()->canCut() || m_impl->frame->editor()->canDHTMLCut());
327
328     return false;
329 }
330
331 void wxWebFrame::Cut()
332 {
333     if (CanCut())
334         m_impl->frame->editor()->cut();
335 }
336
337 bool wxWebFrame::CanPaste()
338 {
339     if (m_impl->frame && m_impl->frame->view())
340         return (m_impl->frame->editor()->canPaste() || m_impl->frame->editor()->canDHTMLPaste());
341
342     return false;
343 }
344
345 void wxWebFrame::Paste()
346 {
347     if (CanPaste())
348         m_impl->frame->editor()->paste();
349
350 }
351
352 wxWebViewDOMElementInfo wxWebFrame::HitTest(const wxPoint& pos) const
353 {
354     wxWebViewDOMElementInfo domInfo;
355
356     if (m_impl->frame->view()) {
357         WebCore::HitTestResult result = m_impl->frame->eventHandler()->hitTestResultAtPoint(m_impl->frame->view()->windowToContents(pos), false);
358         if (result.innerNode()) {
359             domInfo.SetLink(result.absoluteLinkURL().string());
360             domInfo.SetText(result.textContent());
361             domInfo.SetImageSrc(result.absoluteImageURL().string());
362             domInfo.SetSelected(result.isSelected());
363         }
364     }
365
366     return domInfo;
367 }
368