... |
... |
@@ -13,6 +13,7 @@ |
13
|
13
|
#include "wx/eventfilter.h"
|
14
|
14
|
#include "wx/filename.h"
|
15
|
15
|
#include "wx/filesys.h"
|
|
16
|
+#include "wx/mstream.h"
|
16
|
17
|
#include "wx/rtti.h"
|
17
|
18
|
#include "wx/stdpaths.h"
|
18
|
19
|
#include "wx/app.h"
|
... |
... |
@@ -30,6 +31,10 @@ |
30
|
31
|
#include <gdk/gdkx.h>
|
31
|
32
|
#endif
|
32
|
33
|
|
|
34
|
+#include <future>
|
|
35
|
+#include <map>
|
|
36
|
+#include <vector>
|
|
37
|
+
|
33
|
38
|
// With MSVC we are always using debug CEF build in debug wx builds (i.e. when
|
34
|
39
|
// _DEBUG is defined), as otherwise we'd be using incompatible variants of CRT.
|
35
|
40
|
#ifdef _DEBUG
|
... |
... |
@@ -518,6 +523,60 @@ private: |
518
|
523
|
IMPLEMENT_REFCOUNTING(ClientHandler);
|
519
|
524
|
};
|
520
|
525
|
|
|
526
|
+class wxWebViewChromiumHandlerRequest : public wxWebViewHandlerRequest
|
|
527
|
+{
|
|
528
|
+public:
|
|
529
|
+ wxWebViewChromiumHandlerRequest(CefRefPtr<CefRequest> request) : m_request(request)
|
|
530
|
+ {
|
|
531
|
+ SetData(m_request->GetPostData());
|
|
532
|
+ }
|
|
533
|
+ virtual ~wxWebViewChromiumHandlerRequest() = default;
|
|
534
|
+ virtual wxString GetRawURI() const override;
|
|
535
|
+ virtual wxInputStream* GetData() const override;
|
|
536
|
+ virtual wxString GetMethod() const override;
|
|
537
|
+ virtual wxString GetHeader(const wxString& name) const override;
|
|
538
|
+private:
|
|
539
|
+ void SetData(CefRefPtr<CefPostData> postData);
|
|
540
|
+ CefRefPtr<CefRequest> m_request;
|
|
541
|
+ std::vector<uint8_t> m_buffer;
|
|
542
|
+ wxSharedPtr<wxInputStream> m_data;
|
|
543
|
+};
|
|
544
|
+
|
|
545
|
+class wxWebViewChromiumHandlerResponse : public wxWebViewHandlerResponse
|
|
546
|
+{
|
|
547
|
+public:
|
|
548
|
+ wxWebViewChromiumHandlerResponse(CefRefPtr<CefCallback> callback) : m_callback(callback), m_status(200)
|
|
549
|
+ {
|
|
550
|
+ m_futureResult = m_promiseResult.get_future();
|
|
551
|
+ }
|
|
552
|
+ virtual ~wxWebViewChromiumHandlerResponse() = default;
|
|
553
|
+ virtual void SetStatus(int status) override;
|
|
554
|
+ virtual void SetContentType(const wxString& contentType) override;
|
|
555
|
+ virtual void SetHeader(const wxString& name, const wxString& value) override;
|
|
556
|
+ virtual void Finish(wxSharedPtr<wxWebViewHandlerResponseData> data) override;
|
|
557
|
+ virtual void FinishWithError() override;
|
|
558
|
+
|
|
559
|
+ bool GetResult();
|
|
560
|
+
|
|
561
|
+ int GetStatus() const;
|
|
562
|
+ const wxString& GetContentType() const;
|
|
563
|
+ wxInputStream *GetData() const;
|
|
564
|
+ int64_t GetLength() const;
|
|
565
|
+
|
|
566
|
+ void CopyHeaders(CefRefPtr<CefResponse> response) const;
|
|
567
|
+
|
|
568
|
+private:
|
|
569
|
+ CefRefPtr<CefCallback> m_callback;
|
|
570
|
+ // Used to store result of StartRequest if finished asynchronously
|
|
571
|
+ std::promise<bool> m_promiseResult;
|
|
572
|
+ // Used to retrieve result of StartRequest if finished asynchronously
|
|
573
|
+ std::future<bool> m_futureResult;
|
|
574
|
+ int m_status;
|
|
575
|
+ wxString m_contentType;
|
|
576
|
+ std::map<wxString, wxString> m_headers;
|
|
577
|
+ wxSharedPtr<wxWebViewHandlerResponseData> m_data;
|
|
578
|
+};
|
|
579
|
+
|
521
|
580
|
class SchemeHandler : public CefResourceHandler
|
522
|
581
|
{
|
523
|
582
|
public:
|
... |
... |
@@ -536,7 +595,14 @@ public: |
536
|
595
|
virtual void Cancel() override {}
|
537
|
596
|
|
538
|
597
|
private:
|
|
598
|
+ wxWebViewChromiumHandlerResponse *GetHandlerResponse();
|
|
599
|
+
|
539
|
600
|
wxSharedPtr<wxWebViewHandler> m_handler;
|
|
601
|
+
|
|
602
|
+ // This is passed to StartRequest(), so must be of this type, even though
|
|
603
|
+ // the stored object is always a derived wxWebViewChromiumHandlerResponse.
|
|
604
|
+ wxSharedPtr<wxWebViewHandlerResponse> m_handlerResponse;
|
|
605
|
+
|
540
|
606
|
std::string m_data;
|
541
|
607
|
std::string m_mime_type;
|
542
|
608
|
size_t m_offset;
|
... |
... |
@@ -656,9 +722,22 @@ private: |
656
|
722
|
class wxCefBrowserApp : public CefApp
|
657
|
723
|
{
|
658
|
724
|
public:
|
659
|
|
- wxCefBrowserApp()
|
660
|
|
- : m_browserProcessHandler(new wxBrowserProcessHandler{})
|
|
725
|
+ explicit wxCefBrowserApp(bool disableFileAccess)
|
|
726
|
+ : m_browserProcessHandler(new wxBrowserProcessHandler{}),
|
|
727
|
+ m_disableFileAccess(disableFileAccess)
|
|
728
|
+ {
|
|
729
|
+ }
|
|
730
|
+
|
|
731
|
+ // Allow browser to load local files.
|
|
732
|
+ void
|
|
733
|
+ OnBeforeCommandLineProcessing(const CefString &process_type,
|
|
734
|
+ CefRefPtr<CefCommandLine> command_line) override
|
661
|
735
|
{
|
|
736
|
+ if ( process_type.empty() && !m_disableFileAccess )
|
|
737
|
+ {
|
|
738
|
+ command_line->AppendSwitch("allow-file-access-from-files");
|
|
739
|
+ command_line->AppendSwitch("allow-universal-access-from-files");
|
|
740
|
+ }
|
662
|
741
|
}
|
663
|
742
|
|
664
|
743
|
CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() override
|
... |
... |
@@ -668,6 +747,7 @@ public: |
668
|
747
|
|
669
|
748
|
private:
|
670
|
749
|
CefRefPtr<CefBrowserProcessHandler> m_browserProcessHandler;
|
|
750
|
+ bool m_disableFileAccess;
|
671
|
751
|
|
672
|
752
|
IMPLEMENT_REFCOUNTING(wxCefBrowserApp);
|
673
|
753
|
};
|
... |
... |
@@ -1102,7 +1182,8 @@ bool wxWebViewChromium::InitCEF(const wxWebViewConfiguration& config) |
1102
|
1182
|
CefMainArgs args(app->argc, app->argv);
|
1103
|
1183
|
#endif
|
1104
|
1184
|
|
1105
|
|
- CefRefPtr<CefApp> cefApp{new wxCefBrowserApp{}};
|
|
1185
|
+ CefRefPtr<CefApp> cefApp{new wxCefBrowserApp(
|
|
1186
|
+ configChrome->m_disableFileAccess)};
|
1106
|
1187
|
if ( !CefInitialize(args, settings, cefApp, nullptr) )
|
1107
|
1188
|
{
|
1108
|
1189
|
wxLogError(_("Could not initialize Chromium"));
|
... |
... |
@@ -1502,7 +1583,8 @@ bool wxWebViewChromium::CanSetZoomType(wxWebViewZoomType type) const |
1502
|
1583
|
|
1503
|
1584
|
void wxWebViewChromium::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)
|
1504
|
1585
|
{
|
1505
|
|
- CefRegisterSchemeHandlerFactory( handler->GetName().ToStdWstring(), "",
|
|
1586
|
+ CefRegisterSchemeHandlerFactory( handler->GetName().ToStdWstring(),
|
|
1587
|
+ handler->GetVirtualHost().ToStdWstring(),
|
1506
|
1588
|
new SchemeHandlerFactory(handler) );
|
1507
|
1589
|
}
|
1508
|
1590
|
|
... |
... |
@@ -1890,48 +1972,158 @@ void ClientHandler::CloseDevTools(CefRefPtr<CefBrowser> browser) |
1890
|
1972
|
browser->GetHost()->CloseDevTools();
|
1891
|
1973
|
}
|
1892
|
1974
|
|
1893
|
|
-bool SchemeHandler::ProcessRequest(CefRefPtr<CefRequest> request,
|
1894
|
|
- CefRefPtr<CefCallback> callback)
|
|
1975
|
+wxString wxWebViewChromiumHandlerRequest::GetRawURI() const
|
1895
|
1976
|
{
|
1896
|
|
- bool handled = false;
|
|
1977
|
+ return m_request->GetURL().ToString();
|
|
1978
|
+}
|
1897
|
1979
|
|
1898
|
|
- base::AutoLock lock_scope(m_lock);
|
|
1980
|
+wxInputStream* wxWebViewChromiumHandlerRequest::GetData() const
|
|
1981
|
+{
|
|
1982
|
+ return m_data.get();
|
|
1983
|
+}
|
|
1984
|
+
|
|
1985
|
+wxString wxWebViewChromiumHandlerRequest::GetMethod() const
|
|
1986
|
+{
|
|
1987
|
+ return m_request->GetMethod().ToString();
|
|
1988
|
+}
|
1899
|
1989
|
|
1900
|
|
- std::string url = request->GetURL();
|
1901
|
|
- wxFSFile* file = m_handler->GetFile( url );
|
|
1990
|
+wxString wxWebViewChromiumHandlerRequest::GetHeader(const wxString& name) const
|
|
1991
|
+{
|
|
1992
|
+ CefString value = m_request->GetHeaderByName(name.ToStdString());
|
|
1993
|
+ return value.ToString();
|
|
1994
|
+}
|
1902
|
1995
|
|
1903
|
|
- if ( file )
|
|
1996
|
+void wxWebViewChromiumHandlerRequest::SetData(CefRefPtr<CefPostData> data)
|
|
1997
|
+{
|
|
1998
|
+ if ( data )
|
|
1999
|
+ {
|
|
2000
|
+ CefPostData::ElementVector elements;
|
|
2001
|
+ int offset = 0;
|
|
2002
|
+ int read_size = 0;
|
|
2003
|
+ int size = 0;
|
|
2004
|
+
|
|
2005
|
+ m_buffer.clear();
|
|
2006
|
+ data->GetElements(elements);
|
|
2007
|
+ for ( const auto& element : elements )
|
|
2008
|
+ {
|
|
2009
|
+ if ( element->GetType() == PDE_TYPE_BYTES )
|
|
2010
|
+ {
|
|
2011
|
+ read_size = element->GetBytesCount();
|
|
2012
|
+ size += read_size;
|
|
2013
|
+ m_buffer.resize(size);
|
|
2014
|
+ element->GetBytes(read_size, m_buffer.data() + offset);
|
|
2015
|
+ }
|
|
2016
|
+ }
|
|
2017
|
+ m_data.reset(new wxMemoryInputStream(m_buffer.data(), m_buffer.size()));
|
|
2018
|
+ }
|
|
2019
|
+ else
|
1904
|
2020
|
{
|
1905
|
|
- m_mime_type = (file->GetMimeType()).ToStdString();
|
|
2021
|
+ m_data.reset();
|
|
2022
|
+ }
|
|
2023
|
+}
|
|
2024
|
+
|
|
2025
|
+void wxWebViewChromiumHandlerResponse::SetStatus(int status)
|
|
2026
|
+{
|
|
2027
|
+ m_status = status;
|
|
2028
|
+}
|
1906
|
2029
|
|
1907
|
|
- size_t size = file->GetStream()->GetLength();
|
1908
|
|
- char* buf = new char[size];
|
1909
|
|
- file->GetStream()->Read( buf, size );
|
1910
|
|
- m_data = std::string( buf, buf+size );
|
|
2030
|
+void wxWebViewChromiumHandlerResponse::SetContentType(const wxString& contentType)
|
|
2031
|
+{
|
|
2032
|
+ m_contentType = contentType;
|
|
2033
|
+}
|
|
2034
|
+
|
|
2035
|
+void wxWebViewChromiumHandlerResponse::SetHeader(const wxString& name,
|
|
2036
|
+ const wxString& value)
|
|
2037
|
+{
|
|
2038
|
+ m_headers[name] = value;
|
|
2039
|
+}
|
|
2040
|
+
|
|
2041
|
+void wxWebViewChromiumHandlerResponse::Finish(wxSharedPtr<wxWebViewHandlerResponseData> data)
|
|
2042
|
+{
|
|
2043
|
+ m_data = data;
|
|
2044
|
+ m_callback->Continue();
|
|
2045
|
+ m_promiseResult.set_value(true);
|
|
2046
|
+}
|
|
2047
|
+
|
|
2048
|
+void wxWebViewChromiumHandlerResponse::FinishWithError()
|
|
2049
|
+{
|
|
2050
|
+ m_promiseResult.set_value(false);
|
|
2051
|
+}
|
|
2052
|
+
|
|
2053
|
+bool wxWebViewChromiumHandlerResponse::GetResult()
|
|
2054
|
+{
|
|
2055
|
+ return m_futureResult.get();
|
|
2056
|
+}
|
|
2057
|
+
|
|
2058
|
+int wxWebViewChromiumHandlerResponse::GetStatus() const
|
|
2059
|
+{
|
|
2060
|
+ return m_status;
|
|
2061
|
+}
|
|
2062
|
+
|
|
2063
|
+const wxString& wxWebViewChromiumHandlerResponse::GetContentType() const
|
|
2064
|
+{
|
|
2065
|
+ return m_contentType;
|
|
2066
|
+}
|
|
2067
|
+
|
|
2068
|
+wxInputStream* wxWebViewChromiumHandlerResponse::GetData() const
|
|
2069
|
+{
|
|
2070
|
+ wxInputStream* stream = nullptr;
|
|
2071
|
+ if ( m_data )
|
|
2072
|
+ {
|
|
2073
|
+ stream = m_data->GetStream();
|
|
2074
|
+ }
|
|
2075
|
+ return stream;
|
|
2076
|
+}
|
1911
|
2077
|
|
1912
|
|
- delete[] buf;
|
1913
|
|
- handled = true;
|
|
2078
|
+int64_t wxWebViewChromiumHandlerResponse::GetLength() const
|
|
2079
|
+{
|
|
2080
|
+ int64_t length = -1;
|
|
2081
|
+ wxInputStream* stream = GetData();
|
|
2082
|
+ wxFileOffset size = 0;
|
|
2083
|
+ if ( stream )
|
|
2084
|
+ {
|
|
2085
|
+ size = stream->GetLength();
|
|
2086
|
+ if ( size != wxInvalidOffset )
|
|
2087
|
+ {
|
|
2088
|
+ length = static_cast<int64_t>(size);
|
|
2089
|
+ }
|
1914
|
2090
|
}
|
|
2091
|
+ return length;
|
|
2092
|
+}
|
1915
|
2093
|
|
1916
|
|
- if ( handled )
|
|
2094
|
+void wxWebViewChromiumHandlerResponse::CopyHeaders(CefRefPtr<CefResponse> response) const
|
|
2095
|
+{
|
|
2096
|
+ for ( const auto& header : m_headers )
|
1917
|
2097
|
{
|
1918
|
|
- // Indicate the headers are available.
|
1919
|
|
- callback->Continue();
|
1920
|
|
- return true;
|
|
2098
|
+ response->SetHeaderByName(header.first.utf8_string(), header.second.utf8_string(), true);
|
1921
|
2099
|
}
|
1922
|
|
- return false;
|
|
2100
|
+}
|
|
2101
|
+
|
|
2102
|
+bool SchemeHandler::ProcessRequest(CefRefPtr<CefRequest> request,
|
|
2103
|
+ CefRefPtr<CefCallback> callback)
|
|
2104
|
+{
|
|
2105
|
+ base::AutoLock lock_scope(m_lock);
|
|
2106
|
+ wxWebViewChromiumHandlerRequest req(request);
|
|
2107
|
+
|
|
2108
|
+ m_handlerResponse.reset(new wxWebViewChromiumHandlerResponse(callback));
|
|
2109
|
+ m_handler->StartRequest(req, m_handlerResponse);
|
|
2110
|
+ return GetHandlerResponse()->GetResult();
|
1923
|
2111
|
}
|
1924
|
2112
|
|
1925
|
2113
|
void SchemeHandler::GetResponseHeaders(CefRefPtr<CefResponse> response,
|
1926
|
2114
|
int64_t& response_length,
|
1927
|
2115
|
CefString& WXUNUSED(redirectUrl))
|
1928
|
2116
|
{
|
1929
|
|
- if ( !m_mime_type.empty() )
|
1930
|
|
- response->SetMimeType( m_mime_type );
|
1931
|
|
- response->SetStatus( 200 );
|
1932
|
|
-
|
|
2117
|
+ wxWebViewChromiumHandlerResponse* handlerResponse = GetHandlerResponse();
|
|
2118
|
+ const wxString& mimeType = handlerResponse->GetContentType();
|
|
2119
|
+ if ( !mimeType.empty() )
|
|
2120
|
+ {
|
|
2121
|
+ response->SetMimeType(mimeType.ToStdString());
|
|
2122
|
+ }
|
|
2123
|
+ response->SetStatus( handlerResponse->GetStatus() );
|
|
2124
|
+ handlerResponse->CopyHeaders(response);
|
1933
|
2125
|
// Set the resulting response length
|
1934
|
|
- response_length = m_data.length();
|
|
2126
|
+ response_length = handlerResponse->GetLength();
|
1935
|
2127
|
}
|
1936
|
2128
|
|
1937
|
2129
|
bool SchemeHandler::ReadResponse(void* data_out,
|
... |
... |
@@ -1939,24 +2131,26 @@ bool SchemeHandler::ReadResponse(void* data_out, |
1939
|
2131
|
int& bytes_read,
|
1940
|
2132
|
CefRefPtr<CefCallback> WXUNUSED(callback))
|
1941
|
2133
|
{
|
1942
|
|
- bool has_data = false;
|
1943
|
2134
|
bytes_read = 0;
|
1944
|
2135
|
|
1945
|
2136
|
base::AutoLock lock_scope(m_lock);
|
1946
|
2137
|
|
1947
|
|
- if ( m_offset < m_data.length() )
|
1948
|
|
- {
|
1949
|
|
- // Copy the next block of data into the buffer.
|
1950
|
|
- int transfer_size =
|
1951
|
|
- std::min( bytes_to_read, static_cast<int>( m_data.length() - m_offset ) );
|
1952
|
|
- memcpy( data_out, m_data.c_str() + m_offset, transfer_size );
|
1953
|
|
- m_offset += transfer_size;
|
|
2138
|
+ wxWebViewChromiumHandlerResponse* handlerResponse = GetHandlerResponse();
|
|
2139
|
+ wxInputStream* stream = handlerResponse->GetData();
|
1954
|
2140
|
|
1955
|
|
- bytes_read = transfer_size;
|
1956
|
|
- has_data = true;
|
|
2141
|
+ if ( stream->CanRead() )
|
|
2142
|
+ {
|
|
2143
|
+ stream->Read(data_out, bytes_to_read);
|
|
2144
|
+ bytes_read += stream->LastRead();
|
1957
|
2145
|
}
|
1958
|
2146
|
|
1959
|
|
- return has_data;
|
|
2147
|
+ return bytes_read > 0;
|
|
2148
|
+}
|
|
2149
|
+
|
|
2150
|
+wxWebViewChromiumHandlerResponse *SchemeHandler::GetHandlerResponse()
|
|
2151
|
+{
|
|
2152
|
+ // The cast is always safe, see comment in m_handlerResponse declaration.
|
|
2153
|
+ return static_cast<wxWebViewChromiumHandlerResponse*>(m_handlerResponse.get());
|
1960
|
2154
|
}
|
1961
|
2155
|
|
1962
|
2156
|
namespace
|