ScriptControllerBase.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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. #include "config.h"
  21. #include "ScriptController.h"
  22. #include "ContentSecurityPolicy.h"
  23. #include "Document.h"
  24. #include "DocumentLoader.h"
  25. #include "Frame.h"
  26. #include "FrameLoader.h"
  27. #include "FrameLoaderClient.h"
  28. #include "Page.h"
  29. #include "ScriptSourceCode.h"
  30. #include "ScriptValue.h"
  31. #include "SecurityOrigin.h"
  32. #include "Settings.h"
  33. #include "UserGestureIndicator.h"
  34. #include <wtf/text/TextPosition.h>
  35. namespace WebCore {
  36. bool ScriptController::canExecuteScripts(ReasonForCallingCanExecuteScripts reason)
  37. {
  38. if (m_frame->document() && m_frame->document()->isSandboxed(SandboxScripts)) {
  39. // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
  40. if (reason == AboutToExecuteScript)
  41. m_frame->document()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Blocked script execution in '" + m_frame->document()->url().stringCenterEllipsizedToLength() + "' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.");
  42. return false;
  43. }
  44. if (m_frame->document() && m_frame->document()->isViewSource()) {
  45. ASSERT(m_frame->document()->securityOrigin()->isUnique());
  46. return true;
  47. }
  48. Settings* settings = m_frame->settings();
  49. const bool allowed = m_frame->loader()->client()->allowScript(settings && settings->isScriptEnabled());
  50. if (!allowed && reason == AboutToExecuteScript)
  51. m_frame->loader()->client()->didNotAllowScript();
  52. return allowed;
  53. }
  54. ScriptValue ScriptController::executeScript(const String& script, bool forceUserGesture)
  55. {
  56. UserGestureIndicator gestureIndicator(forceUserGesture ? DefinitelyProcessingNewUserGesture : PossiblyProcessingUserGesture);
  57. return executeScript(ScriptSourceCode(script, m_frame->document()->url()));
  58. }
  59. ScriptValue ScriptController::executeScript(const ScriptSourceCode& sourceCode)
  60. {
  61. if (!canExecuteScripts(AboutToExecuteScript) || isPaused())
  62. return ScriptValue();
  63. RefPtr<Frame> protect(m_frame); // Script execution can destroy the frame, and thus the ScriptController.
  64. return evaluate(sourceCode);
  65. }
  66. bool ScriptController::executeIfJavaScriptURL(const KURL& url, ShouldReplaceDocumentIfJavaScriptURL shouldReplaceDocumentIfJavaScriptURL)
  67. {
  68. if (!protocolIsJavaScript(url))
  69. return false;
  70. if (!m_frame->page()
  71. || !m_frame->document()->contentSecurityPolicy()->allowJavaScriptURLs(m_frame->document()->url(), eventHandlerPosition().m_line))
  72. return true;
  73. // We need to hold onto the Frame here because executing script can
  74. // destroy the frame.
  75. RefPtr<Frame> protector(m_frame);
  76. RefPtr<Document> ownerDocument(m_frame->document());
  77. const int javascriptSchemeLength = sizeof("javascript:") - 1;
  78. String decodedURL = decodeURLEscapeSequences(url.string());
  79. ScriptValue result = executeScript(decodedURL.substring(javascriptSchemeLength));
  80. // If executing script caused this frame to be removed from the page, we
  81. // don't want to try to replace its document!
  82. if (!m_frame->page())
  83. return true;
  84. String scriptResult;
  85. JSDOMWindowShell* shell = windowShell(mainThreadNormalWorld());
  86. JSC::ExecState* exec = shell->window()->globalExec();
  87. if (!result.getString(exec, scriptResult))
  88. return true;
  89. // FIXME: We should always replace the document, but doing so
  90. // synchronously can cause crashes:
  91. // http://bugs.webkit.org/show_bug.cgi?id=16782
  92. if (shouldReplaceDocumentIfJavaScriptURL == ReplaceDocumentIfJavaScriptURL) {
  93. // We're still in a frame, so there should be a DocumentLoader.
  94. ASSERT(m_frame->document()->loader());
  95. // DocumentWriter::replaceDocument can cause the DocumentLoader to get deref'ed and possible destroyed,
  96. // so protect it with a RefPtr.
  97. if (RefPtr<DocumentLoader> loader = m_frame->document()->loader())
  98. loader->writer()->replaceDocument(scriptResult, ownerDocument.get());
  99. }
  100. return true;
  101. }
  102. } // namespace WebCore