1 /* 2 * Copyright (C) 1999-2001 Harri Porten (porten (at) kde.org) 3 * Copyright (C) 2001 Peter Kelly (pmk (at) 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 33 namespace WebCore { 34 35 bool 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 48 ScriptValue ScriptController::executeScript(const String& script, bool forceUserGesture) 49 { 50 return executeScript(ScriptSourceCode(script, forceUserGesture ? KURL() : m_frame->document()->url())); 51 } 52 53 ScriptValue 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 71 bool 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