/* * Copyright (C) 2007 Kevin Ollivier All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "Document.h" #include "Editor.h" #include "Element.h" #include "EventHandler.h" #include "Frame.h" #include "FrameLoader.h" #include "FrameView.h" #include "HitTestResult.h" #include "HostWindow.h" #include "HTMLFrameOwnerElement.h" #include "markup.h" #include "Page.h" #include "PlatformString.h" #include "RenderTreeAsText.h" #include "RenderObject.h" #include "RenderView.h" #include "ScriptController.h" #include "ScriptValue.h" #include "SubstituteData.h" #include "TextEncoding.h" #include "JSDOMBinding.h" #include #include #include #include "EditorClientWx.h" #include "FrameLoaderClientWx.h" #include "wx/wxprec.h" #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "WebDOMNode.h" #include "WebDOMSelection.h" #include "WebFrame.h" #include "WebView.h" #include "WebFramePrivate.h" #include "WebViewPrivate.h" #include #include // Match Safari's min/max zoom sizes by default #define MinimumTextSizeMultiplier 0.5f #define MaximumTextSizeMultiplier 3.0f #define TextSizeMultiplierRatio 1.2f wxWebFrame::wxWebFrame(wxWebView* container, wxWebFrame* parent, WebViewFrameData* data) : m_textMagnifier(1.0), m_isInitialized(false), m_beingDestroyed(false) { m_impl = new WebFramePrivate(); WebCore::HTMLFrameOwnerElement* parentFrame = 0; if (data) { parentFrame = data->ownerElement; } WebCore::FrameLoaderClientWx* loaderClient = new WebCore::FrameLoaderClientWx(); RefPtr newFrame = WebCore::Frame::create(container->m_impl->page, parentFrame, loaderClient); m_impl->frame = newFrame.get(); if (data) newFrame->tree()->setName(data->name); // Subframes expect to be added to the FrameTree before init is called. if (parentFrame) parentFrame->document()->frame()->tree()->appendChild(newFrame.get()); loaderClient->setFrame(this); loaderClient->setWebView(container); if (data && data->ownerElement) m_impl->frame->ref(); m_impl->frame->init(); m_isInitialized = true; } wxWebFrame::~wxWebFrame() { if (m_impl) delete m_impl; } WebCore::Frame* wxWebFrame::GetFrame() { if (m_impl) return m_impl->frame; return 0; } void wxWebFrame::Stop() { if (m_impl->frame && m_impl->frame->loader()) m_impl->frame->loader()->stop(); } void wxWebFrame::Reload() { if (m_impl->frame && m_impl->frame->loader()) m_impl->frame->loader()->reload(); } wxString wxWebFrame::GetPageSource() { if (m_impl->frame) { if (m_impl->frame->view() && m_impl->frame->view()->layoutPending()) m_impl->frame->view()->layout(); WebCore::Document* doc = m_impl->frame->document(); if (doc) { wxString source = createMarkup(doc); return source; } } return wxEmptyString; } void wxWebFrame::SetPageSource(const wxString& source, const wxString& baseUrl, const wxString& mimetype) { if (m_impl->frame && m_impl->frame->loader()) { WebCore::KURL url(WebCore::KURL(), baseUrl); const wxCharBuffer charBuffer(source.utf8_str()); const char* contents = charBuffer; WTF::PassRefPtr sharedBuffer = WebCore::SharedBuffer::create(contents, strlen(contents)); WebCore::SubstituteData substituteData(sharedBuffer, mimetype, WTF::String("UTF-8"), WebCore::blankURL(), url); m_impl->frame->loader()->stop(); m_impl->frame->loader()->load(WebCore::ResourceRequest(url), substituteData, false); } } wxString wxWebFrame::GetInnerText() { if (m_impl->frame->view() && m_impl->frame->view()->layoutPending()) m_impl->frame->view()->layout(); WebCore::Element *documentElement = m_impl->frame->document()->documentElement(); return documentElement->innerText(); } wxString wxWebFrame::GetAsMarkup() { if (!m_impl->frame || !m_impl->frame->document()) return wxEmptyString; return createMarkup(m_impl->frame->document()); } wxString wxWebFrame::GetExternalRepresentation() { if (m_impl->frame->view() && m_impl->frame->view()->layoutPending()) m_impl->frame->view()->layout(); return externalRepresentation(m_impl->frame); } wxString wxWebFrame::GetSelectionAsHTML() { if (m_impl->frame) return m_impl->frame->selection()->toNormalizedRange()->toHTML(); return wxEmptyString; } wxString wxWebFrame::GetSelectionAsText() { if (m_impl->frame) return m_impl->frame->selection()->toNormalizedRange()->text(); return wxEmptyString; } wxWebKitSelection wxWebFrame::GetSelection() { if (m_impl->frame) return wxWebKitSelection(m_impl->frame->selection()); return 0; } wxString wxWebFrame::RunScript(const wxString& javascript) { wxString returnValue = wxEmptyString; if (m_impl->frame && m_impl->frame->loader()) { bool hasLoaded = m_impl->frame->loader()->frameHasLoaded(); wxASSERT_MSG(hasLoaded, wxT("Document must be loaded before calling RunScript.")); if (hasLoaded) { WebCore::ScriptController* controller = m_impl->frame->script(); bool jsEnabled = controller->canExecuteScripts(WebCore::AboutToExecuteScript); wxASSERT_MSG(jsEnabled, wxT("RunScript requires JavaScript to be enabled.")); if (jsEnabled) { JSC::JSValue result = controller->executeScript(javascript, true).jsValue(); if (result) returnValue = wxString(result.toString(m_impl->frame->script()->globalObject(WebCore::mainThreadNormalWorld())->globalExec()).utf8().data(), wxConvUTF8); } } } return returnValue; } bool wxWebFrame::ExecuteEditCommand(const wxString& command, const wxString& parameter) { if (m_impl->frame && IsEditable()) return m_impl->frame->editor()->command(command).execute(parameter); } EditState wxWebFrame::GetEditCommandState(const wxString& command) const { if (m_impl->frame && IsEditable()) { WebCore::TriState state = m_impl->frame->editor()->command(command).state(); if (state == WebCore::TrueTriState) return EditStateTrue; if (state == WebCore::FalseTriState) return EditStateFalse; return EditStateMixed; } return EditStateFalse; } wxString wxWebFrame::GetEditCommandValue(const wxString& command) const { if (m_impl->frame && IsEditable()) return m_impl->frame->editor()->command(command).value(); return wxEmptyString; } bool wxWebFrame::FindString(const wxString& string, bool forward, bool caseSensitive, bool wrapSelection, bool startInSelection) { if (m_impl->frame) return m_impl->frame->editor()->findString(string, forward, caseSensitive, wrapSelection, startInSelection); return false; } void wxWebFrame::LoadURL(const wxString& url) { if (m_impl->frame && m_impl->frame->loader()) { WebCore::KURL kurl = WebCore::KURL(WebCore::KURL(), url, WebCore::UTF8Encoding()); // NB: This is an ugly fix, but CURL won't load sub-resources if the // protocol is omitted; sadly, it will not emit an error, either, so // there's no way for us to catch this problem the correct way yet. if (kurl.protocol().isEmpty()) { // is it a file on disk? if (wxFileExists(url)) { kurl.setProtocol("file"); kurl.setPath("//" + kurl.path()); } else { kurl.setProtocol("http"); kurl.setPath("//" + kurl.path()); } } m_impl->frame->loader()->load(kurl, false); } } bool wxWebFrame::GoBack() { if (m_impl->frame && m_impl->frame->page()) return m_impl->frame->page()->goBack(); return false; } bool wxWebFrame::GoForward() { if (m_impl->frame && m_impl->frame->page()) return m_impl->frame->page()->goForward(); return false; } bool wxWebFrame::CanGoBack() { if (m_impl->frame && m_impl->frame->page()) return m_impl->frame->page()->canGoBackOrForward(-1); return false; } bool wxWebFrame::CanGoForward() { if (m_impl->frame && m_impl->frame->page()) return m_impl->frame->page()->canGoBackOrForward(1); return false; } void wxWebFrame::Undo() { if (m_impl->frame && m_impl->frame->editor() && CanUndo()) return m_impl->frame->editor()->undo(); } void wxWebFrame::Redo() { if (m_impl->frame && m_impl->frame->editor() && CanRedo()) return m_impl->frame->editor()->redo(); } bool wxWebFrame::CanUndo() { if (m_impl->frame && m_impl->frame->editor()) return m_impl->frame->editor()->canUndo(); return false; } bool wxWebFrame::CanRedo() { if (m_impl->frame && m_impl->frame->editor()) return m_impl->frame->editor()->canRedo(); return false; } bool wxWebFrame::CanIncreaseTextSize() const { if (m_impl->frame && m_impl->frame->view()) { if (m_textMagnifier*TextSizeMultiplierRatio <= MaximumTextSizeMultiplier) return true; } return false; } void wxWebFrame::IncreaseTextSize() { if (CanIncreaseTextSize()) { m_textMagnifier = m_textMagnifier*TextSizeMultiplierRatio; m_impl->frame->setTextZoomFactor(m_textMagnifier); } } bool wxWebFrame::CanDecreaseTextSize() const { if (m_impl->frame && m_impl->frame->view()) { if (m_textMagnifier/TextSizeMultiplierRatio >= MinimumTextSizeMultiplier) return true; } return false; } void wxWebFrame::DecreaseTextSize() { if (CanDecreaseTextSize()) { m_textMagnifier = m_textMagnifier/TextSizeMultiplierRatio; m_impl->frame->setTextZoomFactor(m_textMagnifier); } } void wxWebFrame::ResetTextSize() { m_textMagnifier = 1.0; if (m_impl->frame) m_impl->frame->setTextZoomFactor(m_textMagnifier); } void wxWebFrame::MakeEditable(bool enable) { if (enable != IsEditable() && m_impl->frame && m_impl->frame->page()) m_impl->frame->page()->setEditable(enable); } bool wxWebFrame::IsEditable() const { if (m_impl->frame && m_impl->frame->page()) return m_impl->frame->page()->isEditable(); return false; } bool wxWebFrame::CanCopy() { if (m_impl->frame && m_impl->frame->view()) return (m_impl->frame->editor()->canCopy() || m_impl->frame->editor()->canDHTMLCopy()); return false; } void wxWebFrame::Copy() { if (CanCopy()) m_impl->frame->editor()->copy(); } bool wxWebFrame::CanCut() { if (m_impl->frame && m_impl->frame->view()) return (m_impl->frame->editor()->canCut() || m_impl->frame->editor()->canDHTMLCut()); return false; } void wxWebFrame::Cut() { if (CanCut()) m_impl->frame->editor()->cut(); } bool wxWebFrame::CanPaste() { if (m_impl->frame && m_impl->frame->view()) return (m_impl->frame->editor()->canPaste() || m_impl->frame->editor()->canDHTMLPaste()); return false; } void wxWebFrame::Paste() { if (CanPaste()) m_impl->frame->editor()->paste(); } wxWebViewDOMElementInfo wxWebFrame::HitTest(const wxPoint& pos) const { wxWebViewDOMElementInfo domInfo; if (m_impl->frame->view()) { WebCore::HitTestResult result = m_impl->frame->eventHandler()->hitTestResultAtPoint(m_impl->frame->view()->windowToContents(pos), false); if (result.innerNode()) { domInfo.SetLink(result.absoluteLinkURL().string()); domInfo.SetText(result.textContent()); domInfo.SetImageSrc(result.absoluteImageURL().string()); domInfo.SetSelected(result.isSelected()); } } return domInfo; } bool wxWebFrame::ShouldClose() const { if (m_impl->frame) return m_impl->frame->loader()->shouldClose(); return true; } wxWebKitCompatibilityMode wxWebFrame::GetCompatibilityMode() const { if (m_impl->frame && m_impl->frame->document()) return (wxWebKitCompatibilityMode)m_impl->frame->document()->compatibilityMode(); return QuirksMode; } void wxWebFrame::GrantUniversalAccess() { if (m_impl->frame && m_impl->frame->document()) m_impl->frame->document()->securityOrigin()->grantUniversalAccess(); }