• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2015 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 "include/base/cef_callback.h"
6 #include "include/cef_pack_resources.h"
7 #include "include/cef_request_context_handler.h"
8 #include "include/wrapper/cef_closure_task.h"
9 #include "include/wrapper/cef_stream_resource_handler.h"
10 #include "tests/ceftests/test_handler.h"
11 #include "tests/ceftests/test_util.h"
12 #include "tests/gtest/include/gtest/gtest.h"
13 #include "tests/shared/browser/client_app_browser.h"
14 #include "tests/shared/browser/resource_util.h"
15 
16 namespace {
17 
18 // Browser-side app delegate.
19 class PdfViewerBrowserTest : public client::ClientAppBrowser::Delegate {
20  public:
PdfViewerBrowserTest()21   PdfViewerBrowserTest() {}
22 
OnBeforeCommandLineProcessing(CefRefPtr<client::ClientAppBrowser> app,CefRefPtr<CefCommandLine> command_line)23   void OnBeforeCommandLineProcessing(
24       CefRefPtr<client::ClientAppBrowser> app,
25       CefRefPtr<CefCommandLine> command_line) override {
26     // Allow all plugin loading by default.
27     command_line->AppendSwitchWithValue("plugin-policy", "allow");
28   }
29 
30  private:
31   IMPLEMENT_REFCOUNTING(PdfViewerBrowserTest);
32 };
33 
34 const char kPdfHtmlUrl[] = "http://tests/pdf.html";
35 const char kPdfDirectUrl[] = "http://tests/pdf.pdf";
36 
37 // Delay waiting for iframe tests to load the PDF file.
38 #if defined(OS_LINUX)
39 const int64 kPdfLoadDelayMs = 7000;
40 #else
41 const int64 kPdfLoadDelayMs = 5000;
42 #endif
43 
44 // Browser-side test handler.
45 class PdfViewerTestHandler : public TestHandler, public CefContextMenuHandler {
46  public:
47   enum Mode {
48     // No specified context or handler (implicitly uses the global context).
49     GLOBAL_DEFAULT,
50 
51     // Global context with no handler.
52     GLOBAL_NO_HANDLER,
53 
54     // Custom context with no handler.
55     CUSTOM_NO_HANDLER,
56   };
57 
PdfViewerTestHandler(Mode mode,const std::string & url)58   PdfViewerTestHandler(Mode mode, const std::string& url)
59       : mode_(mode), url_(url) {}
60 
61   // Loading the PDF directly in the main frame instead of a sub-frame.
HasDirectPdfLoad() const62   bool HasDirectPdfLoad() const { return url_ == kPdfDirectUrl; }
63 
GetContextMenuHandler()64   CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() override {
65     return this;
66   }
67 
RunTest()68   void RunTest() override {
69     CefRefPtr<CefRequestContext> request_context;
70 
71     if (mode_ == GLOBAL_NO_HANDLER) {
72       // Use the global request context.
73       request_context = CefRequestContext::CreateContext(
74           CefRequestContext::GetGlobalContext(), nullptr);
75     } else if (mode_ == CUSTOM_NO_HANDLER) {
76       // Create the request context that will use an in-memory cache.
77       CefRequestContextSettings settings;
78       request_context = CefRequestContext::CreateContext(settings, nullptr);
79     }
80 
81     // Create the browser.
82     CreateBrowser(url_, request_context);
83 
84     // Time out the test after a reasonable period of time.
85     SetTestTimeout(5000 + kPdfLoadDelayMs);
86   }
87 
GetResourceHandler(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request)88   CefRefPtr<CefResourceHandler> GetResourceHandler(
89       CefRefPtr<CefBrowser> browser,
90       CefRefPtr<CefFrame> frame,
91       CefRefPtr<CefRequest> request) override {
92     const std::string& url = request->GetURL();
93     if (url == kPdfHtmlUrl) {
94       CefRefPtr<CefStreamReader> stream =
95           client::GetBinaryResourceReader("pdf.html");
96       return new CefStreamResourceHandler("text/html", stream);
97     } else if (url == kPdfDirectUrl) {
98       CefRefPtr<CefStreamReader> stream =
99           client::GetBinaryResourceReader("pdf.pdf");
100       return new CefStreamResourceHandler("application/pdf", stream);
101     }
102 
103     return nullptr;
104   }
105 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int httpStatusCode)106   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
107                  CefRefPtr<CefFrame> frame,
108                  int httpStatusCode) override {
109     bool is_pdf1 = false;
110     const std::string& url = frame->GetURL();
111     if (url == kPdfHtmlUrl) {
112       if (!got_on_load_end_html_)
113         got_on_load_end_html_.yes();
114       else
115         NOTREACHED();
116     } else if (url == kPdfDirectUrl) {
117       if (!got_on_load_end_pdf1_) {
118         got_on_load_end_pdf1_.yes();
119         is_pdf1 = true;
120       } else if (!got_on_load_end_pdf2_) {
121         got_on_load_end_pdf2_.yes();
122       } else {
123         NOTREACHED();
124       }
125     } else {
126       NOTREACHED();
127     }
128 
129     if (is_pdf1) {
130       // The first PDF document has loaded.
131       // TODO(chrome): Add support for custom context menus.
132       if (IsChromeRuntimeEnabled() || got_context_menu_dismissed_) {
133         // After context menu display. Destroy the test.
134         CefPostDelayedTask(
135             TID_UI, base::BindOnce(&PdfViewerTestHandler::DestroyTest, this),
136             kPdfLoadDelayMs);
137       } else {
138         // Trigger the context menu.
139         CefPostDelayedTask(
140             TID_UI,
141             base::BindOnce(&PdfViewerTestHandler::TriggerContextMenu, this,
142                            frame->GetBrowser()),
143             kPdfLoadDelayMs);
144       }
145     }
146   }
147 
TriggerContextMenu(CefRefPtr<CefBrowser> browser)148   void TriggerContextMenu(CefRefPtr<CefBrowser> browser) {
149     CefMouseEvent mouse_event;
150 
151     if (HasDirectPdfLoad()) {
152       // Somewhere in the main PDF viewing area (avoid left preview bar).
153       mouse_event.x = 400;
154       mouse_event.y = 200;
155     } else {
156       // Somewhere in the first PDF viewing area.
157       mouse_event.x = 100;
158       mouse_event.y = 100;
159     }
160 
161     // Send right-click mouse down and mouse up to tigger context menu.
162     browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_RIGHT, false, 1);
163     browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_RIGHT, true, 1);
164   }
165 
RunContextMenu(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefContextMenuParams> params,CefRefPtr<CefMenuModel> model,CefRefPtr<CefRunContextMenuCallback> callback)166   bool RunContextMenu(CefRefPtr<CefBrowser> browser,
167                       CefRefPtr<CefFrame> frame,
168                       CefRefPtr<CefContextMenuParams> params,
169                       CefRefPtr<CefMenuModel> model,
170                       CefRefPtr<CefRunContextMenuCallback> callback) override {
171     EXPECT_FALSE(got_run_context_menu_);
172     got_run_context_menu_.yes();
173 
174     // Do nothing with the context menu.
175     callback->Cancel();
176 
177     return true;
178   }
179 
OnContextMenuDismissed(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)180   void OnContextMenuDismissed(CefRefPtr<CefBrowser> browser,
181                               CefRefPtr<CefFrame> frame) override {
182     EXPECT_FALSE(got_context_menu_dismissed_);
183     got_context_menu_dismissed_.yes();
184 
185     CefPostTask(TID_UI,
186                 base::BindOnce(&PdfViewerTestHandler::DestroyTest, this));
187   }
188 
DestroyTest()189   void DestroyTest() override {
190     // TODO(chrome): Add support for custom context menus.
191     if (!IsChromeRuntimeEnabled()) {
192       EXPECT_TRUE(got_run_context_menu_);
193       EXPECT_TRUE(got_context_menu_dismissed_);
194     } else {
195       EXPECT_FALSE(got_run_context_menu_);
196       EXPECT_FALSE(got_context_menu_dismissed_);
197     }
198 
199     if (url_ == kPdfHtmlUrl) {
200       // The HTML file will load the PDF twice in iframes.
201       EXPECT_TRUE(got_on_load_end_html_);
202       EXPECT_TRUE(got_on_load_end_pdf1_);
203       EXPECT_TRUE(got_on_load_end_pdf2_);
204     } else if (url_ == kPdfDirectUrl) {
205       // Load the PDF file directly.
206       EXPECT_FALSE(got_on_load_end_html_);
207       EXPECT_TRUE(got_on_load_end_pdf1_);
208       EXPECT_FALSE(got_on_load_end_pdf2_);
209     } else {
210       NOTREACHED();
211     }
212 
213     TestHandler::DestroyTest();
214   }
215 
216   const Mode mode_;
217   const std::string url_;
218 
219   TrackCallback got_on_load_end_html_;
220   TrackCallback got_on_load_end_pdf1_;
221   TrackCallback got_on_load_end_pdf2_;
222   TrackCallback got_run_context_menu_;
223   TrackCallback got_context_menu_dismissed_;
224 
225   IMPLEMENT_REFCOUNTING(PdfViewerTestHandler);
226 };
227 
228 }  // namespace
229 
230 #define RUN_TEST(name, type, url)                                  \
231   TEST(PdfViewerTest, name) {                                      \
232     CefRefPtr<PdfViewerTestHandler> handler =                      \
233         new PdfViewerTestHandler(PdfViewerTestHandler::type, url); \
234     handler->ExecuteTest();                                        \
235     ReleaseAndWaitForDestructor(handler);                          \
236   }
237 
RUN_TEST(GlobalDefaultPdfDirect,GLOBAL_DEFAULT,kPdfDirectUrl)238 RUN_TEST(GlobalDefaultPdfDirect, GLOBAL_DEFAULT, kPdfDirectUrl)
239 RUN_TEST(GlobalDefaultPdfHtml, GLOBAL_DEFAULT, kPdfHtmlUrl)
240 
241 RUN_TEST(GlobalNoHandlerPdfDirect, GLOBAL_NO_HANDLER, kPdfDirectUrl)
242 RUN_TEST(GlobalNoHandlerPdfHtml, GLOBAL_NO_HANDLER, kPdfHtmlUrl)
243 
244 RUN_TEST(CustomNoHandlerPdfDirect, CUSTOM_NO_HANDLER, kPdfDirectUrl)
245 RUN_TEST(CustomNoHandlerPdfHtml, CUSTOM_NO_HANDLER, kPdfHtmlUrl)
246 
247 // Entry point for creating PDF viewer browser test objects.
248 // Called from client_app_delegates.cc.
249 void CreatePdfViewerBrowserTests(
250     client::ClientAppBrowser::DelegateSet& delegates) {
251   delegates.insert(new PdfViewerBrowserTest);
252 }
253