Merge branch 'webview-js-retval'
Integrate GSoC 2017 work by Jose Lorenzo on allowing returning values from JavaScript code via wxWebView::RunScript().
This commit is contained in:
@@ -105,6 +105,7 @@ All:
|
|||||||
|
|
||||||
All (GUI):
|
All (GUI):
|
||||||
|
|
||||||
|
- Allow wxWebView::RunScript() return values (Jose Lorenzo, GSoC 2017).
|
||||||
- Allow using fractional pen widths with wxGraphicsContext (Adrien Tétar).
|
- Allow using fractional pen widths with wxGraphicsContext (Adrien Tétar).
|
||||||
- Improve wxSVGFileDC to support more of wxDC API (Maarten Bent).
|
- Improve wxSVGFileDC to support more of wxDC API (Maarten Bent).
|
||||||
- Add support for wxAuiManager and wxAuiPaneInfo to XRC (Andrea Zanellato).
|
- Add support for wxAuiManager and wxAuiPaneInfo to XRC (Andrea Zanellato).
|
||||||
|
70
include/wx/gtk/private/webkit.h
Normal file
70
include/wx/gtk/private/webkit.h
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Name: wx/gtk/private/webkit.h
|
||||||
|
// Purpose: wxWebKitGtk RAII wrappers declaration
|
||||||
|
// Author: Jose Lorenzo
|
||||||
|
// Created: 2017-08-21
|
||||||
|
// Copyright: (c) 2017 Jose Lorenzo <josee.loren@gmail.com>
|
||||||
|
// Licence: wxWindows licence
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef _WX_GTK_PRIVATE_WEBKIT_H_
|
||||||
|
#define _WX_GTK_PRIVATE_WEBKIT_H_
|
||||||
|
|
||||||
|
#include "wx/buffer.h"
|
||||||
|
|
||||||
|
#include <webkit2/webkit2.h>
|
||||||
|
#include <JavaScriptCore/JSStringRef.h>
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// RAII wrapper of WebKitJavascriptResult taking care of freeing it
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class wxWebKitJavascriptResult
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit wxWebKitJavascriptResult(WebKitJavascriptResult *r)
|
||||||
|
: m_jsresult(r)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~wxWebKitJavascriptResult()
|
||||||
|
{
|
||||||
|
webkit_javascript_result_unref(m_jsresult);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator WebKitJavascriptResult *() const { return m_jsresult; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
WebKitJavascriptResult *m_jsresult;
|
||||||
|
|
||||||
|
wxDECLARE_NO_COPY_CLASS(wxWebKitJavascriptResult);
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// RAII wrapper of JSStringRef, also providing conversion to wxString
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class wxJSStringRef
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit wxJSStringRef(JSStringRef r) : m_jssref(r) { }
|
||||||
|
~wxJSStringRef() { JSStringRelease(m_jssref); }
|
||||||
|
|
||||||
|
wxString ToWxString() const
|
||||||
|
{
|
||||||
|
const size_t length = JSStringGetMaximumUTF8CStringSize(m_jssref);
|
||||||
|
|
||||||
|
wxCharBuffer str(length);
|
||||||
|
|
||||||
|
JSStringGetUTF8CString(m_jssref, str.data(), length);
|
||||||
|
|
||||||
|
return wxString::FromUTF8(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
JSStringRef m_jssref;
|
||||||
|
|
||||||
|
wxDECLARE_NO_COPY_CLASS(wxJSStringRef);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _WX_GTK_PRIVATE_WEBKIT_H_
|
@@ -114,7 +114,7 @@ public:
|
|||||||
virtual wxString GetSelectedSource() const wxOVERRIDE;
|
virtual wxString GetSelectedSource() const wxOVERRIDE;
|
||||||
virtual void ClearSelection() wxOVERRIDE;
|
virtual void ClearSelection() wxOVERRIDE;
|
||||||
|
|
||||||
virtual void RunScript(const wxString& javascript) wxOVERRIDE;
|
virtual bool RunScript(const wxString& javascript, wxString* output = NULL) wxOVERRIDE;
|
||||||
|
|
||||||
//Virtual Filesystem Support
|
//Virtual Filesystem Support
|
||||||
virtual void RegisterHandler(wxSharedPtr<wxWebViewHandler> handler) wxOVERRIDE;
|
virtual void RegisterHandler(wxSharedPtr<wxWebViewHandler> handler) wxOVERRIDE;
|
||||||
@@ -160,6 +160,7 @@ private:
|
|||||||
#if wxUSE_WEBVIEW_WEBKIT2
|
#if wxUSE_WEBVIEW_WEBKIT2
|
||||||
bool CanExecuteEditingCommand(const gchar* command) const;
|
bool CanExecuteEditingCommand(const gchar* command) const;
|
||||||
void SetupWebExtensionServer();
|
void SetupWebExtensionServer();
|
||||||
|
bool RunScriptSync(const wxString& javascript, wxString* output = NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
WebKitWebView *m_web_view;
|
WebKitWebView *m_web_view;
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
#include "wx/msw/webview_missing.h"
|
#include "wx/msw/webview_missing.h"
|
||||||
#include "wx/sharedptr.h"
|
#include "wx/sharedptr.h"
|
||||||
#include "wx/vector.h"
|
#include "wx/vector.h"
|
||||||
|
#include "wx/msw/private.h"
|
||||||
|
|
||||||
struct IHTMLDocument2;
|
struct IHTMLDocument2;
|
||||||
struct IHTMLElement;
|
struct IHTMLElement;
|
||||||
@@ -121,7 +122,7 @@ public:
|
|||||||
virtual wxString GetSelectedSource() const wxOVERRIDE;
|
virtual wxString GetSelectedSource() const wxOVERRIDE;
|
||||||
virtual void ClearSelection() wxOVERRIDE;
|
virtual void ClearSelection() wxOVERRIDE;
|
||||||
|
|
||||||
virtual void RunScript(const wxString& javascript) wxOVERRIDE;
|
virtual bool RunScript(const wxString& javascript, wxString* output = NULL) wxOVERRIDE;
|
||||||
|
|
||||||
//Virtual Filesystem Support
|
//Virtual Filesystem Support
|
||||||
virtual void RegisterHandler(wxSharedPtr<wxWebViewHandler> handler) wxOVERRIDE;
|
virtual void RegisterHandler(wxSharedPtr<wxWebViewHandler> handler) wxOVERRIDE;
|
||||||
@@ -143,6 +144,10 @@ public:
|
|||||||
void onActiveXEvent(wxActiveXEvent& evt);
|
void onActiveXEvent(wxActiveXEvent& evt);
|
||||||
void onEraseBg(wxEraseEvent&) {}
|
void onEraseBg(wxEraseEvent&) {}
|
||||||
|
|
||||||
|
// Establish sufficiently modern emulation level for the browser control to
|
||||||
|
// allow RunScript() to return any kind of values.
|
||||||
|
static bool MSWSetModernEmulationLevel(bool modernLevel = true);
|
||||||
|
|
||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@@ -112,7 +112,7 @@ public:
|
|||||||
virtual wxString GetSelectedSource() const wxOVERRIDE;
|
virtual wxString GetSelectedSource() const wxOVERRIDE;
|
||||||
virtual void ClearSelection() wxOVERRIDE;
|
virtual void ClearSelection() wxOVERRIDE;
|
||||||
|
|
||||||
void RunScript(const wxString& javascript) wxOVERRIDE;
|
bool RunScript(const wxString& javascript, wxString* output = NULL) wxOVERRIDE;
|
||||||
|
|
||||||
//Virtual Filesystem Support
|
//Virtual Filesystem Support
|
||||||
virtual void RegisterHandler(wxSharedPtr<wxWebViewHandler> handler) wxOVERRIDE;
|
virtual void RegisterHandler(wxSharedPtr<wxWebViewHandler> handler) wxOVERRIDE;
|
||||||
|
167
include/wx/private/jsscriptwrapper.h
Normal file
167
include/wx/private/jsscriptwrapper.h
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Name: wx/private/jsscriptwrapper.h
|
||||||
|
// Purpose: JS Script Wrapper for wxWebView
|
||||||
|
// Author: Jose Lorenzo
|
||||||
|
// Created: 2017-08-12
|
||||||
|
// Copyright: (c) 2017 Jose Lorenzo <josee.loren@gmail.com>
|
||||||
|
// Licence: wxWindows licence
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef _WX_PRIVATE_JSSCRIPTWRAPPER_H_
|
||||||
|
#define _WX_PRIVATE_JSSCRIPTWRAPPER_H_
|
||||||
|
|
||||||
|
#include "wx/regex.h"
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Helper for wxWebView::RunScript()
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// This class provides GetWrappedCode(), GetOutputCode() and GetCleanUpCode()
|
||||||
|
// functions that should be executed in the backend-appropriate way by each
|
||||||
|
// wxWebView implementation in order to actually execute the user-provided
|
||||||
|
// JavaScript code, retrieve its result (if it executed successfully) and
|
||||||
|
// perform the cleanup at the end.
|
||||||
|
class wxJSScriptWrapper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wxJSScriptWrapper(const wxString& js, int* runScriptCount)
|
||||||
|
: m_escapedCode(js)
|
||||||
|
{
|
||||||
|
// We assign the return value of JavaScript snippet we execute to the
|
||||||
|
// variable with this name in order to be able to access it later if
|
||||||
|
// needed.
|
||||||
|
//
|
||||||
|
// Note that we use a different name for it for each call to
|
||||||
|
// RunScript() (which creates a new wxJSScriptWrapper every time) to
|
||||||
|
// avoid any possible conflict between different calls.
|
||||||
|
m_outputVarName = wxString::Format("__wxOut%i", (*runScriptCount)++);
|
||||||
|
|
||||||
|
// Adds one escape level if there is a single quote, double quotes or
|
||||||
|
// escape characters
|
||||||
|
wxRegEx escapeDoubleQuotes("(\\\\*)(['\"\n\r\v\t\b\f])");
|
||||||
|
escapeDoubleQuotes.Replace(&m_escapedCode,"\\1\\1\\\\\\2");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the code to execute, its returned value will be either boolean true,
|
||||||
|
// if it executed successfully, or the exception message if an error
|
||||||
|
// occurred.
|
||||||
|
//
|
||||||
|
// Execute GetOutputCode() later to get the real output after successful
|
||||||
|
// execution of this code.
|
||||||
|
wxString GetWrappedCode() const
|
||||||
|
{
|
||||||
|
return wxString::Format
|
||||||
|
(
|
||||||
|
"try { var %s = eval(\"%s\"); true; } "
|
||||||
|
"catch (e) { e.name + \": \" + e.message; }",
|
||||||
|
m_outputVarName,
|
||||||
|
m_escapedCode
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get code returning the result of the last successful execution of the
|
||||||
|
// code returned by GetWrappedCode().
|
||||||
|
wxString GetOutputCode() const
|
||||||
|
{
|
||||||
|
#if wxUSE_WEBVIEW && wxUSE_WEBVIEW_WEBKIT && defined(__WXOSX__)
|
||||||
|
return wxString::Format
|
||||||
|
(
|
||||||
|
"if (typeof %s == 'object') JSON.stringify(%s);"
|
||||||
|
"else if (typeof %s == 'undefined') 'undefined';"
|
||||||
|
"else %s;",
|
||||||
|
m_outputVarName,
|
||||||
|
m_outputVarName,
|
||||||
|
m_outputVarName,
|
||||||
|
m_outputVarName
|
||||||
|
);
|
||||||
|
#elif wxUSE_WEBVIEW && wxUSE_WEBVIEW_IE
|
||||||
|
return wxString::Format
|
||||||
|
(
|
||||||
|
"try {"
|
||||||
|
"(%s == null || typeof %s != 'object') ? String(%s)"
|
||||||
|
": JSON.stringify(%s);"
|
||||||
|
"}"
|
||||||
|
"catch (e) {"
|
||||||
|
"try {"
|
||||||
|
"function __wx$stringifyJSON(obj) {"
|
||||||
|
"if (!(obj instanceof Object))"
|
||||||
|
"return typeof obj === \"string\""
|
||||||
|
"? \'\"\' + obj + \'\"\'"
|
||||||
|
": \'\' + obj;"
|
||||||
|
"else if (obj instanceof Array) {"
|
||||||
|
"if (obj[0] === undefined)"
|
||||||
|
"return \'[]\';"
|
||||||
|
"else {"
|
||||||
|
"var arr = [];"
|
||||||
|
"for (var i = 0; i < obj.length; i++)"
|
||||||
|
"arr.push(__wx$stringifyJSON(obj[i]));"
|
||||||
|
"return \'[\' + arr + \']\';"
|
||||||
|
"}"
|
||||||
|
"}"
|
||||||
|
"else if (typeof obj === \"object\") {"
|
||||||
|
"if (obj instanceof Date) {"
|
||||||
|
"if (!Date.prototype.toISOString) {"
|
||||||
|
"(function() {"
|
||||||
|
"function pad(number) {"
|
||||||
|
"return number < 10"
|
||||||
|
"? '0' + number"
|
||||||
|
": number;"
|
||||||
|
"}"
|
||||||
|
"Date.prototype.toISOString = function() {"
|
||||||
|
"return this.getUTCFullYear() +"
|
||||||
|
"'-' + pad(this.getUTCMonth() + 1) +"
|
||||||
|
"'-' + pad(this.getUTCDate()) +"
|
||||||
|
"'T' + pad(this.getUTCHours()) +"
|
||||||
|
"':' + pad(this.getUTCMinutes()) +"
|
||||||
|
"':' + pad(this.getUTCSeconds()) +"
|
||||||
|
"'.' + (this.getUTCMilliseconds() / 1000)"
|
||||||
|
".toFixed(3).slice(2, 5) + 'Z\"';"
|
||||||
|
"};"
|
||||||
|
"}());"
|
||||||
|
"}"
|
||||||
|
"return '\"' + obj.toISOString(); + '\"'"
|
||||||
|
"}"
|
||||||
|
"var objElements = [];"
|
||||||
|
"for (var key in obj)"
|
||||||
|
"{"
|
||||||
|
"if (typeof obj[key] === \"function\")"
|
||||||
|
"return \'{}\';"
|
||||||
|
"else {"
|
||||||
|
"objElements.push(\'\"\'"
|
||||||
|
"+ key + \'\":\' +"
|
||||||
|
"__wx$stringifyJSON(obj[key]));"
|
||||||
|
"}"
|
||||||
|
"}"
|
||||||
|
"return \'{\' + objElements + \'}\';"
|
||||||
|
"}"
|
||||||
|
"}"
|
||||||
|
"__wx$stringifyJSON(%s);"
|
||||||
|
"}"
|
||||||
|
"catch (e) { e.name + \": \" + e.message; }"
|
||||||
|
"}",
|
||||||
|
m_outputVarName,
|
||||||
|
m_outputVarName,
|
||||||
|
m_outputVarName,
|
||||||
|
m_outputVarName,
|
||||||
|
m_outputVarName
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
return m_outputVarName;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute the code returned by this function to let the output of the code
|
||||||
|
// we executed be garbage-collected.
|
||||||
|
wxString GetCleanUpCode() const
|
||||||
|
{
|
||||||
|
return wxString::Format("%s = undefined;", m_outputVarName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
wxString m_escapedCode;
|
||||||
|
wxString m_outputVarName;
|
||||||
|
|
||||||
|
wxDECLARE_NO_COPY_CLASS(wxJSScriptWrapper);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _WX_PRIVATE_JSSCRIPTWRAPPER_H_
|
@@ -117,6 +117,7 @@ public:
|
|||||||
wxWebView()
|
wxWebView()
|
||||||
{
|
{
|
||||||
m_showMenu = true;
|
m_showMenu = true;
|
||||||
|
m_runScriptCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~wxWebView() {}
|
virtual ~wxWebView() {}
|
||||||
@@ -161,7 +162,7 @@ public:
|
|||||||
virtual void Print() = 0;
|
virtual void Print() = 0;
|
||||||
virtual void RegisterHandler(wxSharedPtr<wxWebViewHandler> handler) = 0;
|
virtual void RegisterHandler(wxSharedPtr<wxWebViewHandler> handler) = 0;
|
||||||
virtual void Reload(wxWebViewReloadFlags flags = wxWEBVIEW_RELOAD_DEFAULT) = 0;
|
virtual void Reload(wxWebViewReloadFlags flags = wxWEBVIEW_RELOAD_DEFAULT) = 0;
|
||||||
virtual void RunScript(const wxString& javascript) = 0;
|
virtual bool RunScript(const wxString& javascript, wxString* output = NULL) = 0;
|
||||||
virtual void SetEditable(bool enable = true) = 0;
|
virtual void SetEditable(bool enable = true) = 0;
|
||||||
void SetPage(const wxString& html, const wxString& baseUrl)
|
void SetPage(const wxString& html, const wxString& baseUrl)
|
||||||
{
|
{
|
||||||
@@ -223,6 +224,10 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual void DoSetPage(const wxString& html, const wxString& baseUrl) = 0;
|
virtual void DoSetPage(const wxString& html, const wxString& baseUrl) = 0;
|
||||||
|
|
||||||
|
// Count the number of calls to RunScript() in order to prevent
|
||||||
|
// the_same variable from being used twice in more than one call.
|
||||||
|
int m_runScriptCount;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void InitFactoryMap();
|
static void InitFactoryMap();
|
||||||
static wxStringWebViewFactoryMap::iterator FindFactory(const wxString &backend);
|
static wxStringWebViewFactoryMap::iterator FindFactory(const wxString &backend);
|
||||||
|
@@ -460,11 +460,98 @@ public:
|
|||||||
virtual void Reload(wxWebViewReloadFlags flags = wxWEBVIEW_RELOAD_DEFAULT) = 0;
|
virtual void Reload(wxWebViewReloadFlags flags = wxWEBVIEW_RELOAD_DEFAULT) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Runs the given javascript code.
|
Sets emulation level to more modern level.
|
||||||
@note When using wxWEBVIEW_BACKEND_IE you must wait for the current
|
|
||||||
page to finish loading before calling RunScript().
|
This function is useful to enable some minimally modern emulation level
|
||||||
|
of the system browser control used for wxWebView implementation under
|
||||||
|
MSW, rather than using the currently default, IE7-compatible,
|
||||||
|
emulation level. Currently the modern emulation level is only IE8, but
|
||||||
|
this could change in the future and shouldn't be relied on.
|
||||||
|
|
||||||
|
Please notice that this function works by modifying the per-user part
|
||||||
|
of MSW registry, which has several implications: first, it is
|
||||||
|
sufficient to call it only once (per user) as the changes done by it
|
||||||
|
are persistent and, second, if you do not want them to be persistent,
|
||||||
|
you need to call it with @false argument explicitly.
|
||||||
|
|
||||||
|
In particular, this function should be called to allow RunScript() to
|
||||||
|
work for JavaScript code returning arbitrary objects, which is not
|
||||||
|
supported at the default emulation level.
|
||||||
|
|
||||||
|
This function is MSW-specific and doesn't exist under other platforms.
|
||||||
|
|
||||||
|
See https://msdn.microsoft.com/en-us/library/ee330730#browser_emulation
|
||||||
|
for more information about browser control emulation levels.
|
||||||
|
|
||||||
|
@param modernLevel @true to set level to a level modern enough to allow
|
||||||
|
all wxWebView features to work (currently IE8), @false to reset the
|
||||||
|
emulation level to its default, compatible value.
|
||||||
|
@return @true on success, @false on failure (a warning message is also
|
||||||
|
logged in the latter case).
|
||||||
|
|
||||||
|
@since 3.1.1
|
||||||
*/
|
*/
|
||||||
virtual void RunScript(const wxString& javascript) = 0;
|
bool MSWSetModernEmulationLevel(bool modernLevel = true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Runs the given JavaScript code.
|
||||||
|
|
||||||
|
JavaScript code is executed inside the browser control and has full
|
||||||
|
access to DOM and other browser-provided functionality. For example,
|
||||||
|
this code
|
||||||
|
@code
|
||||||
|
webview->RunScript("document.write('Hello from wxWidgets!')");
|
||||||
|
@endcode
|
||||||
|
will replace the current page contents with the provided string.
|
||||||
|
|
||||||
|
If @a output is non-null, it is filled with the result of executing
|
||||||
|
this code on success, e.g. a JavaScript value such as a string, a
|
||||||
|
number (integer or floating point), a boolean or JSON representation
|
||||||
|
for non-primitive types such as arrays and objects. For example:
|
||||||
|
@code
|
||||||
|
wxString result;
|
||||||
|
if ( webview->RunScript
|
||||||
|
(
|
||||||
|
"document.getElementById('some_id').innderHTML",
|
||||||
|
&result
|
||||||
|
) )
|
||||||
|
{
|
||||||
|
... result contains the contents of the given element ...
|
||||||
|
}
|
||||||
|
//else: the element with this ID probably doesn't exist.
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
This function has a few platform-specific limitations:
|
||||||
|
|
||||||
|
- When using WebKit v1 in wxGTK2, retrieving the result of JavaScript
|
||||||
|
execution is unsupported and this function will always return false
|
||||||
|
if @a output is non-null to indicate this. This functionality is
|
||||||
|
fully supported when using WebKit v2 or later in wxGTK3.
|
||||||
|
|
||||||
|
- When using WebKit under macOS, code execution is limited to at most
|
||||||
|
10MiB of memory and 10 seconds of execution time.
|
||||||
|
|
||||||
|
- When using IE backend under MSW, scripts can only be executed when
|
||||||
|
the current page is fully loaded (i.e. @c wxEVT_WEBVIEW_LOADED event
|
||||||
|
was received). A script tag inside the page HTML is required in order
|
||||||
|
to run JavaScript.
|
||||||
|
|
||||||
|
Also notice that under MSW converting JavaScript objects to JSON is not
|
||||||
|
supported in the default emulation mode. wxWebView implements its own
|
||||||
|
object-to-JSON conversion as a fallback for this case, however it is
|
||||||
|
not as full-featured, well-tested or performing as the implementation
|
||||||
|
of this functionality in the browser control itself, so it is
|
||||||
|
recommended to use MSWSetModernEmulationLevel() to change emulation
|
||||||
|
level to a more modern one in which JSON conversion is done by the
|
||||||
|
control itself.
|
||||||
|
|
||||||
|
@param javascript JavaScript code to execute.
|
||||||
|
@param output Pointer to a string to be filled with the result value or
|
||||||
|
@NULL if it is not needed. This parameter is new since wxWidgets
|
||||||
|
version 3.1.1.
|
||||||
|
@return @true if there is a result, @false if there is an error.
|
||||||
|
*/
|
||||||
|
virtual bool RunScript(const wxString& javascript, wxString* output = NULL) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Set the editable property of the web control. Enabling allows the user
|
Set the editable property of the web control. Enabling allows the user
|
||||||
|
@@ -30,6 +30,9 @@
|
|||||||
#include "wx/notifmsg.h"
|
#include "wx/notifmsg.h"
|
||||||
#include "wx/settings.h"
|
#include "wx/settings.h"
|
||||||
#include "wx/webview.h"
|
#include "wx/webview.h"
|
||||||
|
#if wxUSE_WEBVIEW_IE
|
||||||
|
#include "wx/msw/webview_ie.h"
|
||||||
|
#endif
|
||||||
#include "wx/webviewarchivehandler.h"
|
#include "wx/webviewarchivehandler.h"
|
||||||
#include "wx/webviewfshandler.h"
|
#include "wx/webviewfshandler.h"
|
||||||
#include "wx/infobar.h"
|
#include "wx/infobar.h"
|
||||||
@@ -63,7 +66,7 @@ class WebApp : public wxApp
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WebApp() :
|
WebApp() :
|
||||||
m_url("http://www.wxwidgets.org")
|
m_url("https://www.wxwidgets.org")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,6 +118,7 @@ public:
|
|||||||
void OnDocumentLoaded(wxWebViewEvent& evt);
|
void OnDocumentLoaded(wxWebViewEvent& evt);
|
||||||
void OnNewWindow(wxWebViewEvent& evt);
|
void OnNewWindow(wxWebViewEvent& evt);
|
||||||
void OnTitleChanged(wxWebViewEvent& evt);
|
void OnTitleChanged(wxWebViewEvent& evt);
|
||||||
|
void OnSetPage(wxCommandEvent& evt);
|
||||||
void OnViewSourceRequest(wxCommandEvent& evt);
|
void OnViewSourceRequest(wxCommandEvent& evt);
|
||||||
void OnViewTextRequest(wxCommandEvent& evt);
|
void OnViewTextRequest(wxCommandEvent& evt);
|
||||||
void OnToolsClicked(wxCommandEvent& evt);
|
void OnToolsClicked(wxCommandEvent& evt);
|
||||||
@@ -133,7 +137,23 @@ public:
|
|||||||
void OnScrollLineDown(wxCommandEvent&) { m_browser->LineDown(); }
|
void OnScrollLineDown(wxCommandEvent&) { m_browser->LineDown(); }
|
||||||
void OnScrollPageUp(wxCommandEvent&) { m_browser->PageUp(); }
|
void OnScrollPageUp(wxCommandEvent&) { m_browser->PageUp(); }
|
||||||
void OnScrollPageDown(wxCommandEvent&) { m_browser->PageDown(); }
|
void OnScrollPageDown(wxCommandEvent&) { m_browser->PageDown(); }
|
||||||
void OnRunScript(wxCommandEvent& evt);
|
void RunScript(const wxString& javascript);
|
||||||
|
void OnRunScriptString(wxCommandEvent& evt);
|
||||||
|
void OnRunScriptInteger(wxCommandEvent& evt);
|
||||||
|
void OnRunScriptDouble(wxCommandEvent& evt);
|
||||||
|
void OnRunScriptBool(wxCommandEvent& evt);
|
||||||
|
void OnRunScriptObject(wxCommandEvent& evt);
|
||||||
|
void OnRunScriptArray(wxCommandEvent& evt);
|
||||||
|
void OnRunScriptDOM(wxCommandEvent& evt);
|
||||||
|
void OnRunScriptUndefined(wxCommandEvent& evt);
|
||||||
|
void OnRunScriptNull(wxCommandEvent& evt);
|
||||||
|
void OnRunScriptDate(wxCommandEvent& evt);
|
||||||
|
#if wxUSE_WEBVIEW_IE
|
||||||
|
void OnRunScriptObjectWithEmulationLevel(wxCommandEvent& evt);
|
||||||
|
void OnRunScriptDateWithEmulationLevel(wxCommandEvent& evt);
|
||||||
|
void OnRunScriptArrayWithEmulationLevel(wxCommandEvent& evt);
|
||||||
|
#endif
|
||||||
|
void OnRunScriptCustom(wxCommandEvent& evt);
|
||||||
void OnClearSelection(wxCommandEvent& evt);
|
void OnClearSelection(wxCommandEvent& evt);
|
||||||
void OnDeleteSelection(wxCommandEvent& evt);
|
void OnDeleteSelection(wxCommandEvent& evt);
|
||||||
void OnSelectAll(wxCommandEvent& evt);
|
void OnSelectAll(wxCommandEvent& evt);
|
||||||
@@ -186,6 +206,22 @@ private:
|
|||||||
wxMenuItem* m_scroll_line_down;
|
wxMenuItem* m_scroll_line_down;
|
||||||
wxMenuItem* m_scroll_page_up;
|
wxMenuItem* m_scroll_page_up;
|
||||||
wxMenuItem* m_scroll_page_down;
|
wxMenuItem* m_scroll_page_down;
|
||||||
|
wxMenuItem* m_script_string;
|
||||||
|
wxMenuItem* m_script_integer;
|
||||||
|
wxMenuItem* m_script_double;
|
||||||
|
wxMenuItem* m_script_bool;
|
||||||
|
wxMenuItem* m_script_object;
|
||||||
|
wxMenuItem* m_script_array;
|
||||||
|
wxMenuItem* m_script_dom;
|
||||||
|
wxMenuItem* m_script_undefined;
|
||||||
|
wxMenuItem* m_script_null;
|
||||||
|
wxMenuItem* m_script_date;
|
||||||
|
#if wxUSE_WEBVIEW_IE
|
||||||
|
wxMenuItem* m_script_object_el;
|
||||||
|
wxMenuItem* m_script_date_el;
|
||||||
|
wxMenuItem* m_script_array_el;
|
||||||
|
#endif
|
||||||
|
wxMenuItem* m_script_custom;
|
||||||
wxMenuItem* m_selection_clear;
|
wxMenuItem* m_selection_clear;
|
||||||
wxMenuItem* m_selection_delete;
|
wxMenuItem* m_selection_delete;
|
||||||
wxMenuItem* m_find;
|
wxMenuItem* m_find;
|
||||||
@@ -199,6 +235,9 @@ private:
|
|||||||
wxMenuHistoryMap m_histMenuItems;
|
wxMenuHistoryMap m_histMenuItems;
|
||||||
wxString m_findText;
|
wxString m_findText;
|
||||||
int m_findFlags, m_findCount;
|
int m_findFlags, m_findCount;
|
||||||
|
|
||||||
|
// Last executed JavaScript snippet, for convenience.
|
||||||
|
wxString m_javascript;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SourceViewDialog : public wxDialog
|
class SourceViewDialog : public wxDialog
|
||||||
@@ -346,6 +385,7 @@ WebFrame::WebFrame(const wxString& url) :
|
|||||||
// Create the Tools menu
|
// Create the Tools menu
|
||||||
m_tools_menu = new wxMenu();
|
m_tools_menu = new wxMenu();
|
||||||
wxMenuItem* print = m_tools_menu->Append(wxID_ANY , _("Print"));
|
wxMenuItem* print = m_tools_menu->Append(wxID_ANY , _("Print"));
|
||||||
|
wxMenuItem* setPage = m_tools_menu->Append(wxID_ANY , _("Set page text"));
|
||||||
wxMenuItem* viewSource = m_tools_menu->Append(wxID_ANY , _("View Source"));
|
wxMenuItem* viewSource = m_tools_menu->Append(wxID_ANY , _("View Source"));
|
||||||
wxMenuItem* viewText = m_tools_menu->Append(wxID_ANY, _("View Text"));
|
wxMenuItem* viewText = m_tools_menu->Append(wxID_ANY, _("View Text"));
|
||||||
m_tools_menu->AppendSeparator();
|
m_tools_menu->AppendSeparator();
|
||||||
@@ -393,7 +433,24 @@ WebFrame::WebFrame(const wxString& url) :
|
|||||||
m_scroll_page_down = scroll_menu->Append(wxID_ANY, "Page d&own");
|
m_scroll_page_down = scroll_menu->Append(wxID_ANY, "Page d&own");
|
||||||
m_tools_menu->AppendSubMenu(scroll_menu, "Scroll");
|
m_tools_menu->AppendSubMenu(scroll_menu, "Scroll");
|
||||||
|
|
||||||
wxMenuItem* script = m_tools_menu->Append(wxID_ANY, _("Run Script"));
|
wxMenu* script_menu = new wxMenu;
|
||||||
|
m_script_string = script_menu->Append(wxID_ANY, "Return String");
|
||||||
|
m_script_integer = script_menu->Append(wxID_ANY, "Return integer");
|
||||||
|
m_script_double = script_menu->Append(wxID_ANY, "Return double");
|
||||||
|
m_script_bool = script_menu->Append(wxID_ANY, "Return bool");
|
||||||
|
m_script_object = script_menu->Append(wxID_ANY, "Return JSON object");
|
||||||
|
m_script_array = script_menu->Append(wxID_ANY, "Return array");
|
||||||
|
m_script_dom = script_menu->Append(wxID_ANY, "Modify DOM");
|
||||||
|
m_script_undefined = script_menu->Append(wxID_ANY, "Return undefined");
|
||||||
|
m_script_null = script_menu->Append(wxID_ANY, "Return null");
|
||||||
|
m_script_date = script_menu->Append(wxID_ANY, "Return Date");
|
||||||
|
#if wxUSE_WEBVIEW_IE
|
||||||
|
m_script_object_el = script_menu->Append(wxID_ANY, "Return JSON object changing emulation level");
|
||||||
|
m_script_date_el = script_menu->Append(wxID_ANY, "Return Date changing emulation level");
|
||||||
|
m_script_array_el = script_menu->Append(wxID_ANY, "Return array changing emulation level");
|
||||||
|
#endif
|
||||||
|
m_script_custom = script_menu->Append(wxID_ANY, "Custom script");
|
||||||
|
m_tools_menu->AppendSubMenu(script_menu, _("Run Script"));
|
||||||
|
|
||||||
//Selection menu
|
//Selection menu
|
||||||
wxMenu* selection = new wxMenu();
|
wxMenu* selection = new wxMenu();
|
||||||
@@ -460,6 +517,8 @@ WebFrame::WebFrame(const wxString& url) :
|
|||||||
wxWebViewEventHandler(WebFrame::OnTitleChanged), NULL, this);
|
wxWebViewEventHandler(WebFrame::OnTitleChanged), NULL, this);
|
||||||
|
|
||||||
// Connect the menu events
|
// Connect the menu events
|
||||||
|
Connect(setPage->GetId(), wxEVT_MENU,
|
||||||
|
wxCommandEventHandler(WebFrame::OnSetPage), NULL, this );
|
||||||
Connect(viewSource->GetId(), wxEVT_MENU,
|
Connect(viewSource->GetId(), wxEVT_MENU,
|
||||||
wxCommandEventHandler(WebFrame::OnViewSourceRequest), NULL, this );
|
wxCommandEventHandler(WebFrame::OnViewSourceRequest), NULL, this );
|
||||||
Connect(viewText->GetId(), wxEVT_MENU,
|
Connect(viewText->GetId(), wxEVT_MENU,
|
||||||
@@ -502,8 +561,36 @@ WebFrame::WebFrame(const wxString& url) :
|
|||||||
wxCommandEventHandler(WebFrame::OnScrollPageUp), NULL, this );
|
wxCommandEventHandler(WebFrame::OnScrollPageUp), NULL, this );
|
||||||
Connect(m_scroll_page_down->GetId(), wxEVT_MENU,
|
Connect(m_scroll_page_down->GetId(), wxEVT_MENU,
|
||||||
wxCommandEventHandler(WebFrame::OnScrollPageDown), NULL, this );
|
wxCommandEventHandler(WebFrame::OnScrollPageDown), NULL, this );
|
||||||
Connect(script->GetId(), wxEVT_MENU,
|
Connect(m_script_string->GetId(), wxEVT_MENU,
|
||||||
wxCommandEventHandler(WebFrame::OnRunScript), NULL, this );
|
wxCommandEventHandler(WebFrame::OnRunScriptString), NULL, this );
|
||||||
|
Connect(m_script_integer->GetId(), wxEVT_MENU,
|
||||||
|
wxCommandEventHandler(WebFrame::OnRunScriptInteger), NULL, this );
|
||||||
|
Connect(m_script_double->GetId(), wxEVT_MENU,
|
||||||
|
wxCommandEventHandler(WebFrame::OnRunScriptDouble), NULL, this );
|
||||||
|
Connect(m_script_bool->GetId(), wxEVT_MENU,
|
||||||
|
wxCommandEventHandler(WebFrame::OnRunScriptBool), NULL, this );
|
||||||
|
Connect(m_script_object->GetId(), wxEVT_MENU,
|
||||||
|
wxCommandEventHandler(WebFrame::OnRunScriptObject), NULL, this );
|
||||||
|
Connect(m_script_array->GetId(), wxEVT_MENU,
|
||||||
|
wxCommandEventHandler(WebFrame::OnRunScriptArray), NULL, this );
|
||||||
|
Connect(m_script_dom->GetId(), wxEVT_MENU,
|
||||||
|
wxCommandEventHandler(WebFrame::OnRunScriptDOM), NULL, this );
|
||||||
|
Connect(m_script_undefined->GetId(), wxEVT_MENU,
|
||||||
|
wxCommandEventHandler(WebFrame::OnRunScriptUndefined), NULL, this );
|
||||||
|
Connect(m_script_null->GetId(), wxEVT_MENU,
|
||||||
|
wxCommandEventHandler(WebFrame::OnRunScriptNull), NULL, this );
|
||||||
|
Connect(m_script_date->GetId(), wxEVT_MENU,
|
||||||
|
wxCommandEventHandler(WebFrame::OnRunScriptDate), NULL, this );
|
||||||
|
#if wxUSE_WEBVIEW_IE
|
||||||
|
Connect(m_script_object_el->GetId(), wxEVT_MENU,
|
||||||
|
wxCommandEventHandler(WebFrame::OnRunScriptObjectWithEmulationLevel), NULL, this );
|
||||||
|
Connect(m_script_date_el->GetId(), wxEVT_MENU,
|
||||||
|
wxCommandEventHandler(WebFrame::OnRunScriptDateWithEmulationLevel), NULL, this );
|
||||||
|
Connect(m_script_array_el->GetId(), wxEVT_MENU,
|
||||||
|
wxCommandEventHandler(WebFrame::OnRunScriptArrayWithEmulationLevel), NULL, this );
|
||||||
|
#endif
|
||||||
|
Connect(m_script_custom->GetId(), wxEVT_MENU,
|
||||||
|
wxCommandEventHandler(WebFrame::OnRunScriptCustom), NULL, this );
|
||||||
Connect(m_selection_clear->GetId(), wxEVT_MENU,
|
Connect(m_selection_clear->GetId(), wxEVT_MENU,
|
||||||
wxCommandEventHandler(WebFrame::OnClearSelection), NULL, this );
|
wxCommandEventHandler(WebFrame::OnClearSelection), NULL, this );
|
||||||
Connect(m_selection_delete->GetId(), wxEVT_MENU,
|
Connect(m_selection_delete->GetId(), wxEVT_MENU,
|
||||||
@@ -811,6 +898,16 @@ void WebFrame::OnTitleChanged(wxWebViewEvent& evt)
|
|||||||
wxLogMessage("%s", "Title changed; title='" + evt.GetString() + "'");
|
wxLogMessage("%s", "Title changed; title='" + evt.GetString() + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebFrame::OnSetPage(wxCommandEvent& WXUNUSED(evt))
|
||||||
|
{
|
||||||
|
m_browser->SetPage
|
||||||
|
(
|
||||||
|
"<html><title>New Page</title>"
|
||||||
|
"<body>Created using <tt>SetPage()</tt> method.</body></html>",
|
||||||
|
wxString()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked when user selects the "View Source" menu item
|
* Invoked when user selects the "View Source" menu item
|
||||||
*/
|
*/
|
||||||
@@ -969,13 +1066,118 @@ void WebFrame::OnHistory(wxCommandEvent& evt)
|
|||||||
m_browser->LoadHistoryItem(m_histMenuItems[evt.GetId()]);
|
m_browser->LoadHistoryItem(m_histMenuItems[evt.GetId()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebFrame::OnRunScript(wxCommandEvent& WXUNUSED(evt))
|
void WebFrame::RunScript(const wxString& javascript)
|
||||||
{
|
{
|
||||||
wxTextEntryDialog dialog(this, "Enter JavaScript to run.", wxGetTextFromUserPromptStr, "", wxOK|wxCANCEL|wxCENTRE|wxTE_MULTILINE);
|
// Remember the script we run in any case, so the next time the user opens
|
||||||
if(dialog.ShowModal() == wxID_OK)
|
// the "Run Script" dialog box, it is shown there for convenient updating.
|
||||||
|
m_javascript = javascript;
|
||||||
|
|
||||||
|
wxLogMessage("Running JavaScript:\n%s\n", javascript);
|
||||||
|
|
||||||
|
wxString result;
|
||||||
|
if ( m_browser->RunScript(javascript, &result) )
|
||||||
{
|
{
|
||||||
m_browser->RunScript(dialog.GetValue());
|
wxLogMessage("RunScript() returned \"%s\"", result);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxLogWarning("RunScript() failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebFrame::OnRunScriptString(wxCommandEvent& WXUNUSED(evt))
|
||||||
|
{
|
||||||
|
RunScript("function f(a){return a;}f('Hello World!');");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebFrame::OnRunScriptInteger(wxCommandEvent& WXUNUSED(evt))
|
||||||
|
{
|
||||||
|
RunScript("function f(a){return a;}f(123);");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebFrame::OnRunScriptDouble(wxCommandEvent& WXUNUSED(evt))
|
||||||
|
{
|
||||||
|
RunScript("function f(a){return a;}f(2.34);");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebFrame::OnRunScriptBool(wxCommandEvent& WXUNUSED(evt))
|
||||||
|
{
|
||||||
|
RunScript("function f(a){return a;}f(false);");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebFrame::OnRunScriptObject(wxCommandEvent& WXUNUSED(evt))
|
||||||
|
{
|
||||||
|
RunScript("function f(){var person = new Object();person.name = 'Foo'; \
|
||||||
|
person.lastName = 'Bar';return person;}f();");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebFrame::OnRunScriptArray(wxCommandEvent& WXUNUSED(evt))
|
||||||
|
{
|
||||||
|
RunScript("function f(){ return [\"foo\", \"bar\"]; }f();");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebFrame::OnRunScriptDOM(wxCommandEvent& WXUNUSED(evt))
|
||||||
|
{
|
||||||
|
RunScript("document.write(\"Hello World!\");");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebFrame::OnRunScriptUndefined(wxCommandEvent& WXUNUSED(evt))
|
||||||
|
{
|
||||||
|
RunScript("function f(){var person = new Object();}f();");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebFrame::OnRunScriptNull(wxCommandEvent& WXUNUSED(evt))
|
||||||
|
{
|
||||||
|
RunScript("function f(){return null;}f();");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebFrame::OnRunScriptDate(wxCommandEvent& WXUNUSED(evt))
|
||||||
|
{
|
||||||
|
RunScript("function f(){var d = new Date('10/08/2017 21:30:40'); \
|
||||||
|
var tzoffset = d.getTimezoneOffset() * 60000; \
|
||||||
|
return new Date(d.getTime() - tzoffset);}f();");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if wxUSE_WEBVIEW_IE
|
||||||
|
void WebFrame::OnRunScriptObjectWithEmulationLevel(wxCommandEvent& WXUNUSED(evt))
|
||||||
|
{
|
||||||
|
wxWebViewIE::MSWSetModernEmulationLevel();
|
||||||
|
RunScript("function f(){var person = new Object();person.name = 'Foo'; \
|
||||||
|
person.lastName = 'Bar';return person;}f();");
|
||||||
|
wxWebViewIE::MSWSetModernEmulationLevel(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebFrame::OnRunScriptDateWithEmulationLevel(wxCommandEvent& WXUNUSED(evt))
|
||||||
|
{
|
||||||
|
wxWebViewIE::MSWSetModernEmulationLevel();
|
||||||
|
RunScript("function f(){var d = new Date('10/08/2017 21:30:40'); \
|
||||||
|
var tzoffset = d.getTimezoneOffset() * 60000; return \
|
||||||
|
new Date(d.getTime() - tzoffset);}f();");
|
||||||
|
wxWebViewIE::MSWSetModernEmulationLevel(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebFrame::OnRunScriptArrayWithEmulationLevel(wxCommandEvent& WXUNUSED(evt))
|
||||||
|
{
|
||||||
|
wxWebViewIE::MSWSetModernEmulationLevel();
|
||||||
|
RunScript("function f(){ return [\"foo\", \"bar\"]; }f();");
|
||||||
|
wxWebViewIE::MSWSetModernEmulationLevel(false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void WebFrame::OnRunScriptCustom(wxCommandEvent& WXUNUSED(evt))
|
||||||
|
{
|
||||||
|
wxTextEntryDialog dialog
|
||||||
|
(
|
||||||
|
this,
|
||||||
|
"Please enter JavaScript code to execute",
|
||||||
|
wxGetTextFromUserPromptStr,
|
||||||
|
m_javascript,
|
||||||
|
wxOK | wxCANCEL | wxCENTRE | wxTE_MULTILINE
|
||||||
|
);
|
||||||
|
if( dialog.ShowModal() != wxID_OK )
|
||||||
|
return;
|
||||||
|
|
||||||
|
RunScript(dialog.GetValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebFrame::OnClearSelection(wxCommandEvent& WXUNUSED(evt))
|
void WebFrame::OnClearSelection(wxCommandEvent& WXUNUSED(evt))
|
||||||
|
@@ -949,10 +949,21 @@ wxString wxWebViewWebKit::GetPageText() const
|
|||||||
wxConvUTF8);
|
wxConvUTF8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxWebViewWebKit::RunScript(const wxString& javascript)
|
bool wxWebViewWebKit::RunScript(const wxString& javascript, wxString* output)
|
||||||
{
|
{
|
||||||
|
wxCHECK_MSG( m_web_view, false,
|
||||||
|
wxS("wxWebView must be created before calling RunScript()") );
|
||||||
|
|
||||||
|
if ( output != NULL )
|
||||||
|
{
|
||||||
|
wxLogWarning(_("Retrieving JavaScript script output is not supported with WebKit v1"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
webkit_web_view_execute_script(m_web_view,
|
webkit_web_view_execute_script(m_web_view,
|
||||||
javascript.mb_str(wxConvUTF8));
|
javascript.mb_str(wxConvUTF8));
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxWebViewWebKit::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)
|
void wxWebViewWebKit::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)
|
||||||
|
@@ -19,7 +19,13 @@
|
|||||||
#include "wx/base64.h"
|
#include "wx/base64.h"
|
||||||
#include "wx/log.h"
|
#include "wx/log.h"
|
||||||
#include "wx/gtk/private/webview_webkit2_extension.h"
|
#include "wx/gtk/private/webview_webkit2_extension.h"
|
||||||
|
#include "wx/gtk/private/string.h"
|
||||||
|
#include "wx/gtk/private/webkit.h"
|
||||||
|
#include "wx/gtk/private/error.h"
|
||||||
|
#include "wx/private/jsscriptwrapper.h"
|
||||||
#include <webkit2/webkit2.h>
|
#include <webkit2/webkit2.h>
|
||||||
|
#include <JavaScriptCore/JSValueRef.h>
|
||||||
|
#include <JavaScriptCore/JSStringRef.h>
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// GTK callbacks
|
// GTK callbacks
|
||||||
@@ -1098,13 +1104,112 @@ wxString wxWebViewWebKit::GetPageText() const
|
|||||||
return wxString();
|
return wxString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxWebViewWebKit::RunScript(const wxString& javascript)
|
extern "C"
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static void wxgtk_run_javascript_cb(GObject *,
|
||||||
|
GAsyncResult *res,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
g_object_ref(res);
|
||||||
|
|
||||||
|
GAsyncResult** res_out = static_cast<GAsyncResult**>(user_data);
|
||||||
|
*res_out = res;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
// Run the given script synchronously and return its result in output.
|
||||||
|
bool wxWebViewWebKit::RunScriptSync(const wxString& javascript, wxString* output)
|
||||||
|
{
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
webkit_web_view_run_javascript(m_web_view,
|
webkit_web_view_run_javascript(m_web_view,
|
||||||
javascript.mb_str(wxConvUTF8),
|
javascript.utf8_str(),
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
wxgtk_run_javascript_cb,
|
||||||
NULL);
|
&result);
|
||||||
|
|
||||||
|
GMainContext *main_context = g_main_context_get_thread_default();
|
||||||
|
|
||||||
|
while ( !result )
|
||||||
|
g_main_context_iteration(main_context, TRUE);
|
||||||
|
|
||||||
|
wxGtkError error;
|
||||||
|
wxWebKitJavascriptResult js_result
|
||||||
|
(
|
||||||
|
webkit_web_view_run_javascript_finish
|
||||||
|
(
|
||||||
|
m_web_view,
|
||||||
|
result,
|
||||||
|
error.Out()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Match g_object_ref() in wxgtk_run_javascript_cb()
|
||||||
|
g_object_unref(result);
|
||||||
|
|
||||||
|
if ( !js_result )
|
||||||
|
{
|
||||||
|
if ( output )
|
||||||
|
*output = error.GetMessage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSGlobalContextRef context = webkit_javascript_result_get_global_context(js_result);
|
||||||
|
JSValueRef value = webkit_javascript_result_get_value(js_result);
|
||||||
|
|
||||||
|
JSValueRef exception = NULL;
|
||||||
|
wxJSStringRef js_value
|
||||||
|
(
|
||||||
|
JSValueIsObject(context, value)
|
||||||
|
? JSValueCreateJSONString(context, value, 0, &exception)
|
||||||
|
: JSValueToStringCopy(context, value, &exception)
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( exception )
|
||||||
|
{
|
||||||
|
if ( output )
|
||||||
|
{
|
||||||
|
wxJSStringRef ex_value(JSValueToStringCopy(context, exception, NULL));
|
||||||
|
*output = ex_value.ToWxString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( output != NULL )
|
||||||
|
*output = js_value.ToWxString();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxWebViewWebKit::RunScript(const wxString& javascript, wxString* output)
|
||||||
|
{
|
||||||
|
wxJSScriptWrapper wrapJS(javascript, &m_runScriptCount);
|
||||||
|
|
||||||
|
// This string is also used as an error indicator: it's cleared if there is
|
||||||
|
// no error or used in the warning message below if there is one.
|
||||||
|
wxString result;
|
||||||
|
if ( RunScriptSync(wrapJS.GetWrappedCode(), &result)
|
||||||
|
&& result == wxS("true") )
|
||||||
|
{
|
||||||
|
if ( RunScriptSync(wrapJS.GetOutputCode(), &result) )
|
||||||
|
{
|
||||||
|
if ( output )
|
||||||
|
*output = result;
|
||||||
|
result.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
RunScriptSync(wrapJS.GetCleanUpCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !result.empty() )
|
||||||
|
{
|
||||||
|
wxLogWarning(_("Error running JavaScript: %s"), result);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxWebViewWebKit::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)
|
void wxWebViewWebKit::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)
|
||||||
|
@@ -29,6 +29,8 @@
|
|||||||
#include "wx/dynlib.h"
|
#include "wx/dynlib.h"
|
||||||
#include "wx/scopeguard.h"
|
#include "wx/scopeguard.h"
|
||||||
|
|
||||||
|
#include "wx/private/jsscriptwrapper.h"
|
||||||
|
|
||||||
#include <initguid.h>
|
#include <initguid.h>
|
||||||
#include <wininet.h>
|
#include <wininet.h>
|
||||||
|
|
||||||
@@ -853,25 +855,103 @@ wxString wxWebViewIE::GetPageText() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxWebViewIE::RunScript(const wxString& javascript)
|
bool wxWebViewIE::MSWSetModernEmulationLevel(bool modernLevel)
|
||||||
{
|
{
|
||||||
wxCOMPtr<IHTMLDocument2> document(GetDocument());
|
// Registry key where emulation level for programs are set
|
||||||
|
static const wxChar* IE_EMULATION_KEY =
|
||||||
|
wxT("SOFTWARE\\Microsoft\\Internet Explorer\\Main")
|
||||||
|
wxT("\\FeatureControl\\FEATURE_BROWSER_EMULATION");
|
||||||
|
|
||||||
if(document)
|
wxRegKey key(wxRegKey::HKCU, IE_EMULATION_KEY);
|
||||||
|
if ( !key.Exists() )
|
||||||
{
|
{
|
||||||
wxCOMPtr<IHTMLWindow2> window;
|
wxLogWarning(_("Failed to find web view emulation level in the registry"));
|
||||||
wxString language = "javascript";
|
return false;
|
||||||
HRESULT hr = document->get_parentWindow(&window);
|
}
|
||||||
if(SUCCEEDED(hr))
|
|
||||||
|
const wxString programName = wxGetFullModuleName().AfterLast('\\');
|
||||||
|
if ( modernLevel )
|
||||||
|
{
|
||||||
|
// IE8 (8000) is sufficiently modern for our needs, see
|
||||||
|
// https://msdn.microsoft.com/library/ee330730.aspx#browser_emulation
|
||||||
|
// for other values that could be used here.
|
||||||
|
if ( !key.SetValue(programName, 8000) )
|
||||||
{
|
{
|
||||||
VARIANT level;
|
wxLogWarning(_("Failed to set web view to modern emulation level"));
|
||||||
VariantInit(&level);
|
return false;
|
||||||
V_VT(&level) = VT_EMPTY;
|
|
||||||
window->execScript(wxBasicString(javascript),
|
|
||||||
wxBasicString(language),
|
|
||||||
&level);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( !key.DeleteValue(programName) )
|
||||||
|
{
|
||||||
|
wxLogWarning(_("Failed to reset web view to standard emulation level"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
bool CallEval(const wxString& code,
|
||||||
|
wxAutomationObject& scriptAO,
|
||||||
|
wxVariant* varResult)
|
||||||
|
{
|
||||||
|
wxVariant varCode(code);
|
||||||
|
return scriptAO.Invoke("eval", DISPATCH_METHOD, *varResult, 1, &varCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxWebViewIE::RunScript(const wxString& javascript, wxString* output)
|
||||||
|
{
|
||||||
|
wxCOMPtr<IHTMLDocument2> document(GetDocument());
|
||||||
|
if ( !document )
|
||||||
|
{
|
||||||
|
wxLogWarning(_("Can't run JavaScript script without a valid HTML document"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IDispatch* scriptDispatch = NULL;
|
||||||
|
if ( FAILED(document->get_Script(&scriptDispatch)) )
|
||||||
|
{
|
||||||
|
wxLogWarning(_("Can't get the JavaScript object"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxJSScriptWrapper wrapJS(javascript, &m_runScriptCount);
|
||||||
|
|
||||||
|
wxAutomationObject scriptAO(scriptDispatch);
|
||||||
|
wxVariant varResult;
|
||||||
|
|
||||||
|
wxString err;
|
||||||
|
if ( !CallEval(wrapJS.GetWrappedCode(), scriptAO, &varResult) )
|
||||||
|
{
|
||||||
|
err = _("failed to evaluate");
|
||||||
|
}
|
||||||
|
else if ( varResult.IsType("bool") && varResult.GetBool() )
|
||||||
|
{
|
||||||
|
if ( output != NULL )
|
||||||
|
{
|
||||||
|
if ( CallEval(wrapJS.GetOutputCode(), scriptAO, &varResult) )
|
||||||
|
*output = varResult.MakeString();
|
||||||
|
else
|
||||||
|
err = _("failed to retrieve execution result");
|
||||||
|
}
|
||||||
|
|
||||||
|
CallEval(wrapJS.GetCleanUpCode(), scriptAO, &varResult);
|
||||||
|
}
|
||||||
|
else // result available but not the expected "true"
|
||||||
|
{
|
||||||
|
err = varResult.MakeString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !err.empty() )
|
||||||
|
{
|
||||||
|
wxLogWarning(_("Error running JavaScript: %s"), varResult.MakeString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxWebViewIE::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)
|
void wxWebViewIE::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "wx/osx/private.h"
|
#include "wx/osx/private.h"
|
||||||
#include "wx/osx/core/cfref.h"
|
#include "wx/osx/core/cfref.h"
|
||||||
|
#include "wx/private/jsscriptwrapper.h"
|
||||||
|
|
||||||
#include "wx/hashmap.h"
|
#include "wx/hashmap.h"
|
||||||
#include "wx/filesys.h"
|
#include "wx/filesys.h"
|
||||||
@@ -408,13 +409,51 @@ wxString wxWebViewWebKit::GetSelectedText() const
|
|||||||
return wxCFStringRef::AsString([dr toString]);
|
return wxCFStringRef::AsString([dr toString]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxWebViewWebKit::RunScript(const wxString& javascript)
|
bool wxWebViewWebKit::RunScript(const wxString& javascript, wxString* output)
|
||||||
{
|
{
|
||||||
if ( !m_webView )
|
wxCHECK_MSG( m_webView, false,
|
||||||
return;
|
wxS("wxWebView must be created before calling RunScript()") );
|
||||||
|
|
||||||
[[m_webView windowScriptObject] evaluateWebScript:
|
wxJSScriptWrapper wrapJS(javascript, &m_runScriptCount);
|
||||||
wxCFStringRef( javascript ).AsNSString()];
|
|
||||||
|
NSString* result = [m_webView stringByEvaluatingJavaScriptFromString:
|
||||||
|
wxCFStringRef( wrapJS.GetWrappedCode() ).AsNSString()];
|
||||||
|
|
||||||
|
wxString err;
|
||||||
|
if ( result == nil )
|
||||||
|
{
|
||||||
|
// This is not very informative, but we just don't have any other
|
||||||
|
// information in this case.
|
||||||
|
err = _("failed to evaluate");
|
||||||
|
}
|
||||||
|
else if ( [result isEqualToString:@"true"] )
|
||||||
|
{
|
||||||
|
result = [m_webView stringByEvaluatingJavaScriptFromString:
|
||||||
|
wxCFStringRef( wrapJS.GetOutputCode() ).AsNSString()];
|
||||||
|
|
||||||
|
[m_webView stringByEvaluatingJavaScriptFromString:
|
||||||
|
wxCFStringRef( wrapJS.GetCleanUpCode() ).AsNSString()];
|
||||||
|
|
||||||
|
if ( output != NULL )
|
||||||
|
{
|
||||||
|
if ( result )
|
||||||
|
*output = wxCFStringRef::AsString(result);
|
||||||
|
else
|
||||||
|
err = _("failed to retrieve execution result");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // result available but not the expected "true"
|
||||||
|
{
|
||||||
|
err = wxCFStringRef::AsString(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !err.empty() )
|
||||||
|
{
|
||||||
|
wxLogWarning(_("Error running JavaScript: %s"), err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxWebViewWebKit::OnSize(wxSizeEvent &event)
|
void wxWebViewWebKit::OnSize(wxSizeEvent &event)
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "testprec.h"
|
#include "testprec.h"
|
||||||
|
|
||||||
#if wxUSE_WEBVIEW && (wxUSE_WEBVIEW_WEBKIT || wxUSE_WEBVIEW_IE)
|
#if wxUSE_WEBVIEW && (wxUSE_WEBVIEW_WEBKIT || wxUSE_WEBVIEW_WEBKIT2 || wxUSE_WEBVIEW_IE)
|
||||||
|
|
||||||
#ifdef __BORLANDC__
|
#ifdef __BORLANDC__
|
||||||
#pragma hdrstop
|
#pragma hdrstop
|
||||||
@@ -22,6 +22,9 @@
|
|||||||
#include "wx/uiaction.h"
|
#include "wx/uiaction.h"
|
||||||
#include "wx/webview.h"
|
#include "wx/webview.h"
|
||||||
#include "asserthelper.h"
|
#include "asserthelper.h"
|
||||||
|
#if wxUSE_WEBVIEW_IE
|
||||||
|
#include "wx/msw/webview_ie.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
class WebTestCase : public CppUnit::TestCase
|
class WebTestCase : public CppUnit::TestCase
|
||||||
{
|
{
|
||||||
@@ -36,8 +39,11 @@ private:
|
|||||||
CPPUNIT_TEST( Title );
|
CPPUNIT_TEST( Title );
|
||||||
CPPUNIT_TEST( Url );
|
CPPUNIT_TEST( Url );
|
||||||
CPPUNIT_TEST( History );
|
CPPUNIT_TEST( History );
|
||||||
|
#if !wxUSE_WEBVIEW_WEBKIT2
|
||||||
|
//This is not implemented on WEBKIT2. See implementation.
|
||||||
CPPUNIT_TEST( HistoryEnable );
|
CPPUNIT_TEST( HistoryEnable );
|
||||||
CPPUNIT_TEST( HistoryClear );
|
CPPUNIT_TEST( HistoryClear );
|
||||||
|
#endif
|
||||||
CPPUNIT_TEST( HistoryList );
|
CPPUNIT_TEST( HistoryList );
|
||||||
CPPUNIT_TEST( Editable );
|
CPPUNIT_TEST( Editable );
|
||||||
CPPUNIT_TEST( Selection );
|
CPPUNIT_TEST( Selection );
|
||||||
@@ -66,7 +72,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
//Convenience macro
|
//Convenience macro
|
||||||
#define ENSURE_LOADED WX_ASSERT_EVENT_OCCURS((*m_loaded), 1)
|
#define ENSURE_LOADED WX_ASSERT_EVENT_OCCURS_IN((*m_loaded), 1, 1000)
|
||||||
|
|
||||||
// register in the unnamed registry so that these tests are run by default
|
// register in the unnamed registry so that these tests are run by default
|
||||||
CPPUNIT_TEST_SUITE_REGISTRATION( WebTestCase );
|
CPPUNIT_TEST_SUITE_REGISTRATION( WebTestCase );
|
||||||
@@ -76,10 +82,10 @@ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( WebTestCase, "WebTestCase" );
|
|||||||
|
|
||||||
void WebTestCase::setUp()
|
void WebTestCase::setUp()
|
||||||
{
|
{
|
||||||
m_browser = wxWebView::New(wxTheApp->GetTopWindow(), wxID_ANY);
|
m_browser = wxWebView::New();
|
||||||
|
|
||||||
m_loaded = new EventCounter(m_browser, wxEVT_WEBVIEW_LOADED);
|
m_loaded = new EventCounter(m_browser, wxEVT_WEBVIEW_LOADED);
|
||||||
m_browser->LoadURL("about:blank");
|
|
||||||
|
m_browser -> Create(wxTheApp->GetTopWindow(), wxID_ANY);
|
||||||
ENSURE_LOADED;
|
ENSURE_LOADED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,8 +268,109 @@ void WebTestCase::Zoom()
|
|||||||
|
|
||||||
void WebTestCase::RunScript()
|
void WebTestCase::RunScript()
|
||||||
{
|
{
|
||||||
m_browser->RunScript("document.write(\"Hello World!\");");
|
m_browser->
|
||||||
|
SetPage("<html><head><script></script></head><body></body></html>", "");
|
||||||
|
ENSURE_LOADED;
|
||||||
|
|
||||||
|
wxString result;
|
||||||
|
#if wxUSE_WEBVIEW_IE
|
||||||
|
CPPUNIT_ASSERT(wxWebViewIE::MSWSetModernEmulationLevel());
|
||||||
|
|
||||||
|
// Define a specialized scope guard ensuring that we reset the emulation
|
||||||
|
// level to its default value even if any asserts below fail.
|
||||||
|
class ResetEmulationLevel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ResetEmulationLevel()
|
||||||
|
{
|
||||||
|
m_reset = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DoReset()
|
||||||
|
{
|
||||||
|
m_reset = false;
|
||||||
|
return wxWebViewIE::MSWSetModernEmulationLevel(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
~ResetEmulationLevel()
|
||||||
|
{
|
||||||
|
if ( m_reset )
|
||||||
|
DoReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_reset;
|
||||||
|
} resetEmulationLevel;
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(m_browser->RunScript("function f(){var person = new Object();person.name = 'Bar'; \
|
||||||
|
person.lastName = 'Foo';return person;}f();", &result));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("{\"name\":\"Bar\",\"lastName\":\"Foo\"}", result);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(m_browser->RunScript("function f(){ return [\"foo\", \"bar\"]; }f();", &result));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("[\"foo\",\"bar\"]", result);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(m_browser->RunScript("function f(){var d = new Date('10/08/2017 21:30:40'); \
|
||||||
|
var tzoffset = d.getTimezoneOffset() * 60000; return new Date(d.getTime() - tzoffset);}f();",
|
||||||
|
&result));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("\"2017-10-08T21:30:40.000Z\"", result);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(resetEmulationLevel.DoReset());
|
||||||
|
#endif // wxUSE_WEBVIEW_IE
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(m_browser->RunScript("document.write(\"Hello World!\");"));
|
||||||
CPPUNIT_ASSERT_EQUAL("Hello World!", m_browser->GetPageText());
|
CPPUNIT_ASSERT_EQUAL("Hello World!", m_browser->GetPageText());
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(m_browser->RunScript("function f(a){return a;}f('Hello World!');", &result));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(_("Hello World!"), result);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(m_browser->RunScript("function f(a){return a;}f(123);", &result));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(123, wxAtoi(result));
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(m_browser->
|
||||||
|
RunScript("function f(a){return a;}f(2.34);", &result));
|
||||||
|
double value;
|
||||||
|
result.ToDouble(&value);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(2.34, value);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(m_browser->RunScript("function f(a){return a;}f(false);", &result));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("false", result);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(m_browser->RunScript("function f(){var person = new Object();person.name = 'Foo'; \
|
||||||
|
person.lastName = 'Bar';return person;}f();", &result));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("{\"name\":\"Foo\",\"lastName\":\"Bar\"}", result);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(m_browser->RunScript("function f(){ return [\"foo\", \"bar\"]; }f();", &result));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("[\"foo\",\"bar\"]", result);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(m_browser->RunScript("function f(){var person = new Object();}f();", &result));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("undefined", result);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(m_browser->RunScript("function f(){return null;}f();", &result));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("null", result);
|
||||||
|
|
||||||
|
result = "";
|
||||||
|
CPPUNIT_ASSERT(!m_browser->RunScript("int main() { return 0; }", &result));
|
||||||
|
CPPUNIT_ASSERT(!result);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(m_browser->RunScript("function a() { return eval(\"function b() { \
|
||||||
|
return eval(\\\"function c() { return eval(\\\\\\\"function d() { \
|
||||||
|
return \\\\\\\\\\\\\\\"test\\\\\\\\\\\\\\\"; } d();\\\\\\\"); } \
|
||||||
|
c();\\\"); } b();\"); } a();", &result));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("test", result);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(m_browser->RunScript("function f(a){return a;}f(\"This is a backslash: \\\\\");",
|
||||||
|
&result));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("This is a backslash: \\", result);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(m_browser->RunScript("function f(){var d = new Date('10/08/2016 21:30:40'); \
|
||||||
|
var tzoffset = d.getTimezoneOffset() * 60000; return new Date(d.getTime() - tzoffset);}f();",
|
||||||
|
&result));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("\"2016-10-08T21:30:40.000Z\"", result);
|
||||||
|
|
||||||
|
// Check for errors too.
|
||||||
|
CPPUNIT_ASSERT(!m_browser->RunScript("syntax(error"));
|
||||||
|
CPPUNIT_ASSERT(!m_browser->RunScript("syntax(error", &result));
|
||||||
|
CPPUNIT_ASSERT(!m_browser->RunScript("x.y.z"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebTestCase::SetPage()
|
void WebTestCase::SetPage()
|
||||||
@@ -277,4 +384,4 @@ void WebTestCase::SetPage()
|
|||||||
CPPUNIT_ASSERT_EQUAL("other text", m_browser->GetPageText());
|
CPPUNIT_ASSERT_EQUAL("other text", m_browser->GetPageText());
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //wxUSE_WEBVIEW && (wxUSE_WEBVIEW_WEBKIT || wxUSE_WEBVIEW_IE)
|
#endif //wxUSE_WEBVIEW && (wxUSE_WEBVIEW_WEBKIT || wxUSE_WEBVIEW_WEBKIT2 || wxUSE_WEBVIEW_IE)
|
||||||
|
@@ -100,13 +100,13 @@ public:
|
|||||||
#define WX_ASSERT_FAILS_WITH_ASSERT(cond)
|
#define WX_ASSERT_FAILS_WITH_ASSERT(cond)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define WX_ASSERT_EVENT_OCCURS(eventcounter, count) \
|
#define WX_ASSERT_EVENT_OCCURS_IN(eventcounter, count, ms) \
|
||||||
{\
|
{\
|
||||||
wxStopWatch sw; \
|
wxStopWatch sw; \
|
||||||
wxEventLoopBase* loop = wxEventLoopBase::GetActive(); \
|
wxEventLoopBase* loop = wxEventLoopBase::GetActive(); \
|
||||||
while(eventcounter.GetCount() < count) \
|
while(eventcounter.GetCount() < count) \
|
||||||
{ \
|
{ \
|
||||||
if(sw.Time() < 100) \
|
if(sw.Time() < ms) \
|
||||||
loop->Dispatch(); \
|
loop->Dispatch(); \
|
||||||
else \
|
else \
|
||||||
{ \
|
{ \
|
||||||
@@ -119,6 +119,8 @@ public:
|
|||||||
eventcounter.Clear(); \
|
eventcounter.Clear(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define WX_ASSERT_EVENT_OCCURS(eventcounter,count) WX_ASSERT_EVENT_OCCURS_IN(eventcounter, count, 100)
|
||||||
|
|
||||||
// these functions can be used to hook into wxApp event processing and are
|
// these functions can be used to hook into wxApp event processing and are
|
||||||
// currently used by the events propagation test
|
// currently used by the events propagation test
|
||||||
class WXDLLIMPEXP_FWD_BASE wxEvent;
|
class WXDLLIMPEXP_FWD_BASE wxEvent;
|
||||||
|
Reference in New Issue
Block a user