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