1/* 2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 4 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21#include "config.h" 22#include "ScriptController.h" 23 24#include "ContentSecurityPolicy.h" 25#include "DocumentLoader.h" 26#include "Frame.h" 27#include "FrameLoaderClient.h" 28#include "Page.h" 29#include "ScriptSourceCode.h" 30#include "ScriptValue.h" 31#include "Settings.h" 32 33namespace WebCore { 34 35bool ScriptController::canExecuteScripts(ReasonForCallingCanExecuteScripts reason) 36{ 37 // FIXME: We should get this information from the document instead of the frame. 38 if (m_frame->loader()->isSandboxed(SandboxScripts)) 39 return false; 40 41 Settings* settings = m_frame->settings(); 42 const bool allowed = m_frame->loader()->client()->allowJavaScript(settings && settings->isJavaScriptEnabled()); 43 if (!allowed && reason == AboutToExecuteScript) 44 m_frame->loader()->client()->didNotAllowScript(); 45 return allowed; 46} 47 48ScriptValue ScriptController::executeScript(const String& script, bool forceUserGesture) 49{ 50 return executeScript(ScriptSourceCode(script, forceUserGesture ? KURL() : m_frame->document()->url())); 51} 52 53ScriptValue ScriptController::executeScript(const ScriptSourceCode& sourceCode) 54{ 55 if (!canExecuteScripts(AboutToExecuteScript) || isPaused()) 56 return ScriptValue(); 57 58 bool wasInExecuteScript = m_inExecuteScript; 59 m_inExecuteScript = true; 60 61 ScriptValue result = evaluate(sourceCode); 62 63 if (!wasInExecuteScript) { 64 m_inExecuteScript = false; 65 Document::updateStyleForAllDocuments(); 66 } 67 68 return result; 69} 70 71bool ScriptController::executeIfJavaScriptURL(const KURL& url, ShouldReplaceDocumentIfJavaScriptURL shouldReplaceDocumentIfJavaScriptURL) 72{ 73 if (!protocolIsJavaScript(url)) 74 return false; 75 76 if (!m_frame->page() 77 || !m_frame->page()->javaScriptURLsAreAllowed() 78 || !m_frame->document()->contentSecurityPolicy()->allowJavaScriptURLs() 79 || m_frame->inViewSourceMode()) 80 return true; 81 82 // We need to hold onto the Frame here because executing script can 83 // destroy the frame. 84 RefPtr<Frame> protector(m_frame); 85 86 const int javascriptSchemeLength = sizeof("javascript:") - 1; 87 88 String decodedURL = decodeURLEscapeSequences(url.string()); 89 ScriptValue result = executeScript(decodedURL.substring(javascriptSchemeLength), false); 90 91 // If executing script caused this frame to be removed from the page, we 92 // don't want to try to replace its document! 93 if (!m_frame->page()) 94 return true; 95 96 String scriptResult; 97#if USE(JSC) 98 JSDOMWindowShell* shell = windowShell(mainThreadNormalWorld()); 99 JSC::ExecState* exec = shell->window()->globalExec(); 100 if (!result.getString(exec, scriptResult)) 101 return true; 102#else 103 if (!result.getString(scriptResult)) 104 return true; 105#endif 106 107 // FIXME: We should always replace the document, but doing so 108 // synchronously can cause crashes: 109 // http://bugs.webkit.org/show_bug.cgi?id=16782 110 if (shouldReplaceDocumentIfJavaScriptURL == ReplaceDocumentIfJavaScriptURL) { 111 // We're still in a frame, so there should be a DocumentLoader. 112 ASSERT(m_frame->document()->loader()); 113 114 // DocumentWriter::replaceDocument can cause the DocumentLoader to get deref'ed and possible destroyed, 115 // so protect it with a RefPtr. 116 if (RefPtr<DocumentLoader> loader = m_frame->document()->loader()) 117 loader->writer()->replaceDocument(scriptResult); 118 } 119 return true; 120} 121 122} // namespace WebCore 123