Home | History | Annotate | Download | only in wx
      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 
     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 
    113 wxWebFrame::~wxWebFrame()
    114 {
    115     if (m_impl)
    116         delete m_impl;
    117 }
    118 
    119 WebCore::Frame* wxWebFrame::GetFrame()
    120 {
    121     if (m_impl)
    122         return m_impl->frame;
    123 
    124     return 0;
    125 }
    126 
    127 void wxWebFrame::Stop()
    128 {
    129     if (m_impl->frame && m_impl->frame->loader())
    130         m_impl->frame->loader()->stop();
    131 }
    132 
    133 void wxWebFrame::Reload()
    134 {
    135     if (m_impl->frame && m_impl->frame->loader())
    136         m_impl->frame->loader()->reload();
    137 }
    138 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    278 void wxWebFrame::Undo()
    279 {
    280     if (m_impl->frame && m_impl->frame->editor() && CanUndo())
    281         return m_impl->frame->editor()->undo();
    282 }
    283 
    284 void wxWebFrame::Redo()
    285 {
    286     if (m_impl->frame && m_impl->frame->editor() && CanRedo())
    287         return m_impl->frame->editor()->redo();
    288 }
    289 
    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 
    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 
    306 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 
    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 
    323 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 
    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 
    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 
    347 void wxWebFrame::MakeEditable(bool enable)
    348 {
    349     m_isEditable = enable;
    350 }
    351 
    352 
    353 
    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 
    362 void wxWebFrame::Copy()
    363 {
    364     if (CanCopy())
    365         m_impl->frame->editor()->copy();
    366 }
    367 
    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 
    376 void wxWebFrame::Cut()
    377 {
    378     if (CanCut())
    379         m_impl->frame->editor()->cut();
    380 }
    381 
    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 
    390 void wxWebFrame::Paste()
    391 {
    392     if (CanPaste())
    393         m_impl->frame->editor()->paste();
    394 
    395 }
    396 
    397 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 
    414 bool wxWebFrame::ShouldClose() const
    415 {
    416     if (m_impl->frame)
    417         return m_impl->frame->shouldClose();
    418 
    419     return true;
    420 }
    421 
    422 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