blob: 86bf6604d5684037f2176d4b4e363a0800dcaba1 [file] [log] [blame]
/*
* 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 <runtime/JSValue.h>
#include <runtime/UString.h>
#include <wtf/text/CString.h>
#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 <wx/defs.h>
#include <wx/dcbuffer.h>
// 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<WebCore::Frame> 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<WebCore::SharedBuffer> 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();
}