1 // Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4
5 #include "tests/cefclient/browser/scheme_test.h"
6
7 #include <algorithm>
8 #include <string>
9
10 #include "include/cef_browser.h"
11 #include "include/cef_callback.h"
12 #include "include/cef_frame.h"
13 #include "include/cef_request.h"
14 #include "include/cef_resource_handler.h"
15 #include "include/cef_response.h"
16 #include "include/cef_scheme.h"
17 #include "include/wrapper/cef_helpers.h"
18 #include "tests/cefclient/browser/test_runner.h"
19 #include "tests/shared/browser/resource_util.h"
20
21 namespace client {
22 namespace scheme_test {
23
24 namespace {
25
26 // Implementation of the schema handler for client:// requests.
27 class ClientSchemeHandler : public CefResourceHandler {
28 public:
ClientSchemeHandler()29 ClientSchemeHandler() : offset_(0) {}
30
Open(CefRefPtr<CefRequest> request,bool & handle_request,CefRefPtr<CefCallback> callback)31 bool Open(CefRefPtr<CefRequest> request,
32 bool& handle_request,
33 CefRefPtr<CefCallback> callback) override {
34 DCHECK(!CefCurrentlyOn(TID_UI) && !CefCurrentlyOn(TID_IO));
35
36 // The request will be continued or canceled based on the return value.
37 handle_request = true;
38
39 bool handled = false;
40
41 std::string url = request->GetURL();
42 if (strstr(url.c_str(), "handler.html") != nullptr) {
43 // Build the response html
44 data_ =
45 "<html><head><title>Client Scheme Handler</title></head>"
46 "<body bgcolor=\"white\">"
47 "This contents of this page page are served by the "
48 "ClientSchemeHandler class handling the client:// protocol."
49 "<br/>You should see an image:"
50 "<br/><img src=\"client://tests/logo.png\"><pre>";
51
52 // Output a string representation of the request
53 const std::string& dump = test_runner::DumpRequestContents(request);
54 data_.append(dump);
55
56 data_.append(
57 "</pre><br/>Try the test form:"
58 "<form method=\"POST\" action=\"handler.html\">"
59 "<input type=\"text\" name=\"field1\">"
60 "<input type=\"text\" name=\"field2\">"
61 "<input type=\"submit\">"
62 "</form></body></html>");
63
64 handled = true;
65
66 // Set the resulting mime type
67 mime_type_ = "text/html";
68 } else if (strstr(url.c_str(), "logo.png") != nullptr) {
69 // Load the response image
70 if (LoadBinaryResource("logo.png", data_)) {
71 handled = true;
72 // Set the resulting mime type
73 mime_type_ = "image/png";
74 }
75 }
76
77 return handled;
78 }
79
GetResponseHeaders(CefRefPtr<CefResponse> response,int64 & response_length,CefString & redirectUrl)80 void GetResponseHeaders(CefRefPtr<CefResponse> response,
81 int64& response_length,
82 CefString& redirectUrl) override {
83 CEF_REQUIRE_IO_THREAD();
84
85 DCHECK(!data_.empty());
86
87 response->SetMimeType(mime_type_);
88 response->SetStatus(200);
89
90 // Set the resulting response length
91 response_length = data_.length();
92 }
93
Cancel()94 void Cancel() override { CEF_REQUIRE_IO_THREAD(); }
95
Read(void * data_out,int bytes_to_read,int & bytes_read,CefRefPtr<CefResourceReadCallback> callback)96 bool Read(void* data_out,
97 int bytes_to_read,
98 int& bytes_read,
99 CefRefPtr<CefResourceReadCallback> callback) override {
100 DCHECK(!CefCurrentlyOn(TID_UI) && !CefCurrentlyOn(TID_IO));
101
102 bool has_data = false;
103 bytes_read = 0;
104
105 if (offset_ < data_.length()) {
106 // Copy the next block of data into the buffer.
107 int transfer_size =
108 std::min(bytes_to_read, static_cast<int>(data_.length() - offset_));
109 memcpy(data_out, data_.c_str() + offset_, transfer_size);
110 offset_ += transfer_size;
111
112 bytes_read = transfer_size;
113 has_data = true;
114 }
115
116 return has_data;
117 }
118
119 private:
120 std::string data_;
121 std::string mime_type_;
122 size_t offset_;
123
124 IMPLEMENT_REFCOUNTING(ClientSchemeHandler);
125 DISALLOW_COPY_AND_ASSIGN(ClientSchemeHandler);
126 };
127
128 // Implementation of the factory for for creating schema handlers.
129 class ClientSchemeHandlerFactory : public CefSchemeHandlerFactory {
130 public:
ClientSchemeHandlerFactory()131 ClientSchemeHandlerFactory() {}
132
133 // Return a new scheme handler instance to handle the request.
Create(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const CefString & scheme_name,CefRefPtr<CefRequest> request)134 CefRefPtr<CefResourceHandler> Create(CefRefPtr<CefBrowser> browser,
135 CefRefPtr<CefFrame> frame,
136 const CefString& scheme_name,
137 CefRefPtr<CefRequest> request) override {
138 CEF_REQUIRE_IO_THREAD();
139 return new ClientSchemeHandler();
140 }
141
142 IMPLEMENT_REFCOUNTING(ClientSchemeHandlerFactory);
143 DISALLOW_COPY_AND_ASSIGN(ClientSchemeHandlerFactory);
144 };
145
146 } // namespace
147
RegisterSchemeHandlers()148 void RegisterSchemeHandlers() {
149 CefRegisterSchemeHandlerFactory("client", "tests",
150 new ClientSchemeHandlerFactory());
151 }
152
153 } // namespace scheme_test
154 } // namespace client
155