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 "BackForwardList.h"
28 #include "CString.h"
29 #include "Document.h"
30 #include "Editor.h"
31 #include "Element.h"
32 #include "EventHandler.h"
33 #include "Frame.h"
34 #include "FrameLoader.h"
35 #include "FrameView.h"
36 #include "HitTestResult.h"
37 #include "HostWindow.h"
38 #include "HTMLFrameOwnerElement.h"
39 #include "markup.h"
40 #include "Page.h"
41 #include "PlatformString.h"
42 #include "RenderTreeAsText.h"
43 #include "RenderObject.h"
44 #include "RenderView.h"
45 #include "ScriptController.h"
46 #include "ScriptValue.h"
47 #include "SubstituteData.h"
48 #include "TextEncoding.h"
49
50 #include "JSDOMBinding.h"
51 #include <runtime/JSValue.h>
52 #include <runtime/UString.h>
53
54 #include "EditorClientWx.h"
55 #include "FrameLoaderClientWx.h"
56
57 #include "wx/wxprec.h"
58 #ifndef WX_PRECOMP
59 #include "wx/wx.h"
60 #endif
61
62 #include "WebFrame.h"
63 #include "WebView.h"
64 #include "WebFramePrivate.h"
65 #include "WebViewPrivate.h"
66
67 #include <wx/defs.h>
68 #include <wx/dcbuffer.h>
69
70 // Match Safari's min/max zoom sizes by default
71 #define MinimumTextSizeMultiplier 0.5f
72 #define MaximumTextSizeMultiplier 3.0f
73 #define TextSizeMultiplierRatio 1.2f
74
wxWebFrame(wxWebView * container,wxWebFrame * parent,WebViewFrameData * data)75 wxWebFrame::wxWebFrame(wxWebView* container, wxWebFrame* parent, WebViewFrameData* data) :
76 m_textMagnifier(1.0),
77 m_isEditable(false),
78 m_isInitialized(false),
79 m_beingDestroyed(false)
80 {
81
82 m_impl = new WebFramePrivate();
83
84 WebCore::HTMLFrameOwnerElement* parentFrame = 0;
85
86 if (data) {
87 parentFrame = data->ownerElement;
88 }
89
90 WebCore::FrameLoaderClientWx* loaderClient = new WebCore::FrameLoaderClientWx();
91 RefPtr<WebCore::Frame> newFrame = WebCore::Frame::create(container->m_impl->page, parentFrame, loaderClient);
92
93 m_impl->frame = newFrame.get();
94
95 if (data)
96 newFrame->tree()->setName(data->name);
97
98 // Subframes expect to be added to the FrameTree before init is called.
99 if (parentFrame)
100 parentFrame->document()->frame()->tree()->appendChild(newFrame.get());
101
102 loaderClient->setFrame(this);
103 loaderClient->setWebView(container);
104
105 if (data && data->ownerElement)
106 m_impl->frame->ref();
107
108 m_impl->frame->init();
109
110 m_isInitialized = true;
111 }
112
~wxWebFrame()113 wxWebFrame::~wxWebFrame()
114 {
115 if (m_impl)
116 delete m_impl;
117 }
118
GetFrame()119 WebCore::Frame* wxWebFrame::GetFrame()
120 {
121 if (m_impl)
122 return m_impl->frame;
123
124 return 0;
125 }
126
Stop()127 void wxWebFrame::Stop()
128 {
129 if (m_impl->frame && m_impl->frame->loader())
130 m_impl->frame->loader()->stop();
131 }
132
Reload()133 void wxWebFrame::Reload()
134 {
135 if (m_impl->frame && m_impl->frame->loader())
136 m_impl->frame->loader()->reload();
137 }
138
GetPageSource()139 wxString wxWebFrame::GetPageSource()
140 {
141 if (m_impl->frame) {
142 if (m_impl->frame->view() && m_impl->frame->view()->layoutPending())
143 m_impl->frame->view()->layout();
144
145 WebCore::Document* doc = m_impl->frame->document();
146
147 if (doc) {
148 wxString source = createMarkup(doc);
149 return source;
150 }
151 }
152 return wxEmptyString;
153 }
154
SetPageSource(const wxString & source,const wxString & baseUrl)155 void wxWebFrame::SetPageSource(const wxString& source, const wxString& baseUrl)
156 {
157 if (m_impl->frame && m_impl->frame->loader()) {
158 WebCore::KURL url(WebCore::KURL(), baseUrl);
159
160 const wxCharBuffer charBuffer(source.utf8_str());
161 const char* contents = charBuffer;
162
163 WTF::PassRefPtr<WebCore::SharedBuffer> sharedBuffer = WebCore::SharedBuffer::create(contents, strlen(contents));
164 WebCore::SubstituteData substituteData(sharedBuffer, WebCore::String("text/html"), WebCore::String("UTF-8"), WebCore::blankURL(), url);
165
166 m_impl->frame->loader()->stop();
167 m_impl->frame->loader()->load(WebCore::ResourceRequest(url), substituteData, false);
168 }
169 }
170
GetInnerText()171 wxString wxWebFrame::GetInnerText()
172 {
173 if (m_impl->frame->view() && m_impl->frame->view()->layoutPending())
174 m_impl->frame->view()->layout();
175
176 WebCore::Element *documentElement = m_impl->frame->document()->documentElement();
177 return documentElement->innerText();
178 }
179
GetAsMarkup()180 wxString wxWebFrame::GetAsMarkup()
181 {
182 if (!m_impl->frame || !m_impl->frame->document())
183 return wxEmptyString;
184
185 return createMarkup(m_impl->frame->document());
186 }
187
GetExternalRepresentation()188 wxString wxWebFrame::GetExternalRepresentation()
189 {
190 if (m_impl->frame->view() && m_impl->frame->view()->layoutPending())
191 m_impl->frame->view()->layout();
192
193 return externalRepresentation(m_impl->frame);
194 }
195
RunScript(const wxString & javascript)196 wxString wxWebFrame::RunScript(const wxString& javascript)
197 {
198 wxString returnValue = wxEmptyString;
199 if (m_impl->frame && m_impl->frame->loader()) {
200 bool hasLoaded = m_impl->frame->loader()->frameHasLoaded();
201 wxASSERT_MSG(hasLoaded, wxT("Document must be loaded before calling RunScript."));
202 if (hasLoaded) {
203 WebCore::ScriptController* controller = m_impl->frame->script();
204 bool jsEnabled = controller->canExecuteScripts();
205 wxASSERT_MSG(jsEnabled, wxT("RunScript requires JavaScript to be enabled."));
206 if (jsEnabled) {
207 JSC::JSValue result = controller->executeScript(javascript, true).jsValue();
208 if (result)
209 returnValue = wxString(result.toString(m_impl->frame->script()->globalObject(WebCore::mainThreadNormalWorld())->globalExec()).UTF8String().c_str(), wxConvUTF8);
210 }
211 }
212 }
213 return returnValue;
214 }
215
FindString(const wxString & string,bool forward,bool caseSensitive,bool wrapSelection,bool startInSelection)216 bool wxWebFrame::FindString(const wxString& string, bool forward, bool caseSensitive, bool wrapSelection, bool startInSelection)
217 {
218 if (m_impl->frame)
219 return m_impl->frame->findString(string, forward, caseSensitive, wrapSelection, startInSelection);
220
221 return false;
222 }
223
LoadURL(const wxString & url)224 void wxWebFrame::LoadURL(const wxString& url)
225 {
226 if (m_impl->frame && m_impl->frame->loader()) {
227 WebCore::KURL kurl = WebCore::KURL(WebCore::KURL(), url, WebCore::UTF8Encoding());
228 // NB: This is an ugly fix, but CURL won't load sub-resources if the
229 // protocol is omitted; sadly, it will not emit an error, either, so
230 // there's no way for us to catch this problem the correct way yet.
231 if (kurl.protocol().isEmpty()) {
232 // is it a file on disk?
233 if (wxFileExists(url)) {
234 kurl.setProtocol("file");
235 kurl.setPath("//" + kurl.path());
236 }
237 else {
238 kurl.setProtocol("http");
239 kurl.setPath("//" + kurl.path());
240 }
241 }
242 m_impl->frame->loader()->load(kurl, false);
243 }
244 }
245
GoBack()246 bool wxWebFrame::GoBack()
247 {
248 if (m_impl->frame && m_impl->frame->page())
249 return m_impl->frame->page()->goBack();
250
251 return false;
252 }
253
GoForward()254 bool wxWebFrame::GoForward()
255 {
256 if (m_impl->frame && m_impl->frame->page())
257 return m_impl->frame->page()->goForward();
258
259 return false;
260 }
261
CanGoBack()262 bool wxWebFrame::CanGoBack()
263 {
264 if (m_impl->frame && m_impl->frame->page() && m_impl->frame->page()->backForwardList())
265 return m_impl->frame->page()->backForwardList()->backItem() != NULL;
266
267 return false;
268 }
269
CanGoForward()270 bool wxWebFrame::CanGoForward()
271 {
272 if (m_impl->frame && m_impl->frame->page() && m_impl->frame->page()->backForwardList())
273 return m_impl->frame->page()->backForwardList()->forwardItem() != NULL;
274
275 return false;
276 }
277
Undo()278 void wxWebFrame::Undo()
279 {
280 if (m_impl->frame && m_impl->frame->editor() && CanUndo())
281 return m_impl->frame->editor()->undo();
282 }
283
Redo()284 void wxWebFrame::Redo()
285 {
286 if (m_impl->frame && m_impl->frame->editor() && CanRedo())
287 return m_impl->frame->editor()->redo();
288 }
289
CanUndo()290 bool wxWebFrame::CanUndo()
291 {
292 if (m_impl->frame && m_impl->frame->editor())
293 return m_impl->frame->editor()->canUndo();
294
295 return false;
296 }
297
CanRedo()298 bool wxWebFrame::CanRedo()
299 {
300 if (m_impl->frame && m_impl->frame->editor())
301 return m_impl->frame->editor()->canRedo();
302
303 return false;
304 }
305
CanIncreaseTextSize() const306 bool wxWebFrame::CanIncreaseTextSize() const
307 {
308 if (m_impl->frame) {
309 if (m_textMagnifier*TextSizeMultiplierRatio <= MaximumTextSizeMultiplier)
310 return true;
311 }
312 return false;
313 }
314
IncreaseTextSize()315 void wxWebFrame::IncreaseTextSize()
316 {
317 if (CanIncreaseTextSize()) {
318 m_textMagnifier = m_textMagnifier*TextSizeMultiplierRatio;
319 m_impl->frame->setZoomFactor(m_textMagnifier, true);
320 }
321 }
322
CanDecreaseTextSize() const323 bool wxWebFrame::CanDecreaseTextSize() const
324 {
325 if (m_impl->frame) {
326 if (m_textMagnifier/TextSizeMultiplierRatio >= MinimumTextSizeMultiplier)
327 return true;
328 }
329 return false;
330 }
331
DecreaseTextSize()332 void wxWebFrame::DecreaseTextSize()
333 {
334 if (CanDecreaseTextSize()) {
335 m_textMagnifier = m_textMagnifier/TextSizeMultiplierRatio;
336 m_impl->frame->setZoomFactor(m_textMagnifier, true);
337 }
338 }
339
ResetTextSize()340 void wxWebFrame::ResetTextSize()
341 {
342 m_textMagnifier = 1.0;
343 if (m_impl->frame)
344 m_impl->frame->setZoomFactor(m_textMagnifier, true);
345 }
346
MakeEditable(bool enable)347 void wxWebFrame::MakeEditable(bool enable)
348 {
349 m_isEditable = enable;
350 }
351
352
353
CanCopy()354 bool wxWebFrame::CanCopy()
355 {
356 if (m_impl->frame && m_impl->frame->view())
357 return (m_impl->frame->editor()->canCopy() || m_impl->frame->editor()->canDHTMLCopy());
358
359 return false;
360 }
361
Copy()362 void wxWebFrame::Copy()
363 {
364 if (CanCopy())
365 m_impl->frame->editor()->copy();
366 }
367
CanCut()368 bool wxWebFrame::CanCut()
369 {
370 if (m_impl->frame && m_impl->frame->view())
371 return (m_impl->frame->editor()->canCut() || m_impl->frame->editor()->canDHTMLCut());
372
373 return false;
374 }
375
Cut()376 void wxWebFrame::Cut()
377 {
378 if (CanCut())
379 m_impl->frame->editor()->cut();
380 }
381
CanPaste()382 bool wxWebFrame::CanPaste()
383 {
384 if (m_impl->frame && m_impl->frame->view())
385 return (m_impl->frame->editor()->canPaste() || m_impl->frame->editor()->canDHTMLPaste());
386
387 return false;
388 }
389
Paste()390 void wxWebFrame::Paste()
391 {
392 if (CanPaste())
393 m_impl->frame->editor()->paste();
394
395 }
396
HitTest(const wxPoint & pos) const397 wxWebViewDOMElementInfo wxWebFrame::HitTest(const wxPoint& pos) const
398 {
399 wxWebViewDOMElementInfo domInfo;
400
401 if (m_impl->frame->view()) {
402 WebCore::HitTestResult result = m_impl->frame->eventHandler()->hitTestResultAtPoint(m_impl->frame->view()->windowToContents(pos), false);
403 if (result.innerNode()) {
404 domInfo.SetLink(result.absoluteLinkURL().string());
405 domInfo.SetText(result.textContent());
406 domInfo.SetImageSrc(result.absoluteImageURL().string());
407 domInfo.SetSelected(result.isSelected());
408 }
409 }
410
411 return domInfo;
412 }
413
ShouldClose() const414 bool wxWebFrame::ShouldClose() const
415 {
416 if (m_impl->frame)
417 return m_impl->frame->shouldClose();
418
419 return true;
420 }
421
GetParseMode() const422 wxWebKitParseMode wxWebFrame::GetParseMode() const
423 {
424 if (m_impl->frame && m_impl->frame->document())
425 return (wxWebKitParseMode)m_impl->frame->document()->parseMode();
426
427 return NoDocument;
428 }
429