• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2017 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/wrapper/cef_closure_task.h"
7 
8 #include "tests/ceftests/routing_test_handler.h"
9 #include "tests/gtest/include/gtest/gtest.h"
10 
11 namespace {
12 
13 const char kTestUrl1[] = "https://tests/DisplayTestHandler.START";
14 const char kTestUrl2[] = "https://tests/DisplayTestHandler.NAVIGATE";
15 const char kTestMsg[] = "DisplayTestHandler.Status";
16 
17 // Default OSR widget size.
18 const int kOsrWidth = 600;
19 const int kOsrHeight = 400;
20 
21 class DisplayTestHandler : public RoutingTestHandler, public CefRenderHandler {
22  public:
DisplayTestHandler()23   DisplayTestHandler() : status_(START) {}
24 
GetRenderHandler()25   CefRefPtr<CefRenderHandler> GetRenderHandler() override { return this; }
26 
GetViewRect(CefRefPtr<CefBrowser> browser,CefRect & rect)27   void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override {
28     rect = CefRect(0, 0, kOsrWidth, kOsrHeight);
29   }
30 
GetScreenInfo(CefRefPtr<CefBrowser> browser,CefScreenInfo & screen_info)31   bool GetScreenInfo(CefRefPtr<CefBrowser> browser,
32                      CefScreenInfo& screen_info) override {
33     screen_info.rect = CefRect(0, 0, kOsrWidth, kOsrHeight);
34     screen_info.available_rect = screen_info.rect;
35     return true;
36   }
37 
OnPaint(CefRefPtr<CefBrowser> browser,CefRenderHandler::PaintElementType type,const CefRenderHandler::RectList & dirtyRects,const void * buffer,int width,int height)38   void OnPaint(CefRefPtr<CefBrowser> browser,
39                CefRenderHandler::PaintElementType type,
40                const CefRenderHandler::RectList& dirtyRects,
41                const void* buffer,
42                int width,
43                int height) override {
44     if (!got_paint_[status_]) {
45       got_paint_[status_].yes();
46 
47       if (status_ == START) {
48         OnStartIfDone();
49       } else if (status_ == SHOW) {
50         CefPostTask(TID_UI,
51                     base::BindOnce(&DisplayTestHandler::DestroyTest, this));
52       } else {
53         ADD_FAILURE();
54       }
55     }
56   }
57 
RunTest()58   void RunTest() override {
59     // Add the resources that we will navigate to/from.
60     AddResource(kTestUrl1, GetPageContents("Page1", "START"), "text/html");
61     AddResource(kTestUrl2, GetPageContents("Page2", "NAVIGATE"), "text/html");
62 
63     // Create the browser.
64     CreateOSRBrowser(kTestUrl1);
65 
66     // Time out the test after a reasonable period of time.
67     SetTestTimeout(5000);
68   }
69 
OnQuery(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id,const CefString & request,bool persistent,CefRefPtr<Callback> callback)70   bool OnQuery(CefRefPtr<CefBrowser> browser,
71                CefRefPtr<CefFrame> frame,
72                int64 query_id,
73                const CefString& request,
74                bool persistent,
75                CefRefPtr<Callback> callback) override {
76     const std::string& request_str = request.ToString();
77     if (request_str.find(kTestMsg) == 0) {
78       const std::string& status = request_str.substr(sizeof(kTestMsg));
79       if (status == "START") {
80         got_start_msg_.yes();
81         OnStartIfDone();
82       } else if (status == "NAVIGATE") {
83         got_navigate_msg_.yes();
84         // Wait a bit to verify no OnPaint callback.
85         CefPostDelayedTask(
86             TID_UI, base::BindOnce(&DisplayTestHandler::OnNavigate, this), 250);
87       }
88     }
89     callback->Success("");
90     return true;
91   }
92 
DestroyTest()93   void DestroyTest() override {
94     EXPECT_TRUE(got_paint_[START]);
95     EXPECT_FALSE(got_paint_[NAVIGATE]);
96     EXPECT_TRUE(got_paint_[SHOW]);
97 
98     EXPECT_TRUE(got_start_msg_);
99     EXPECT_TRUE(got_navigate_msg_);
100 
101     EXPECT_EQ(status_, SHOW);
102 
103     RoutingTestHandler::DestroyTest();
104   }
105 
106  private:
CreateOSRBrowser(const CefString & url)107   void CreateOSRBrowser(const CefString& url) {
108     CefWindowInfo windowInfo;
109     CefBrowserSettings settings;
110 
111 #if defined(OS_WIN)
112     windowInfo.SetAsWindowless(GetDesktopWindow());
113 #else
114     windowInfo.SetAsWindowless(kNullWindowHandle);
115 #endif
116 
117     CefBrowserHost::CreateBrowser(windowInfo, this, url, settings, nullptr,
118                                   nullptr);
119   }
120 
GetPageContents(const std::string & name,const std::string & status)121   std::string GetPageContents(const std::string& name,
122                               const std::string& status) {
123     return "<html><body>" + name + "<script>window.testQuery({request:'" +
124            std::string(kTestMsg) + ":" + status + "'});</script></body></html>";
125   }
126 
OnStartIfDone()127   void OnStartIfDone() {
128     if (got_start_msg_ && got_paint_[START]) {
129       CefPostTask(TID_UI, base::BindOnce(&DisplayTestHandler::OnStart, this));
130     }
131   }
132 
OnStart()133   void OnStart() {
134     EXPECT_EQ(status_, START);
135 
136     // Hide the browser. OnPaint should not be called again until
137     // WasHidden(false) is explicitly called.
138     GetBrowser()->GetHost()->WasHidden(true);
139     status_ = NAVIGATE;
140 
141     GetBrowser()->GetMainFrame()->LoadURL(kTestUrl2);
142   }
143 
OnNavigate()144   void OnNavigate() {
145     EXPECT_EQ(status_, NAVIGATE);
146 
147     // Show the browser.
148     status_ = SHOW;
149     GetBrowser()->GetHost()->WasHidden(false);
150 
151     // Force a call to OnPaint.
152     GetBrowser()->GetHost()->Invalidate(PET_VIEW);
153   }
154 
155   enum Status {
156     START,
157     NAVIGATE,
158     SHOW,
159     STATUS_COUNT,
160   };
161   Status status_;
162 
163   TrackCallback got_paint_[STATUS_COUNT];
164   TrackCallback got_start_msg_;
165   TrackCallback got_navigate_msg_;
166 
167   IMPLEMENT_REFCOUNTING(DisplayTestHandler);
168 };
169 
170 }  // namespace
171 
172 // Test that browser visibility is not changed due to navigation.
TEST(OSRTest,NavigateWhileHidden)173 TEST(OSRTest, NavigateWhileHidden) {
174   CefRefPtr<DisplayTestHandler> handler = new DisplayTestHandler();
175   handler->ExecuteTest();
176   ReleaseAndWaitForDestructor(handler);
177 }
178 
179 namespace {
180 
181 const char kOsrPopupJSOtherClientMainUrl[] =
182     "http://www.tests-pjse.com/main.html";
183 
184 class OsrPopupJSOtherClientTestHandler : public TestHandler,
185                                          public CefRenderHandler {
186  public:
OsrPopupJSOtherClientTestHandler(CefRefPtr<CefClient> other)187   OsrPopupJSOtherClientTestHandler(CefRefPtr<CefClient> other) {
188     other_ = other;
189   }
190 
GetRenderHandler()191   virtual CefRefPtr<CefRenderHandler> GetRenderHandler() override {
192     return this;
193   }
194 
GetViewRect(CefRefPtr<CefBrowser> browser,CefRect & rect)195   virtual void GetViewRect(CefRefPtr<CefBrowser> browser,
196                            CefRect& rect) override {
197     rect = CefRect(0, 0, kOsrWidth, kOsrHeight);
198   }
199 
OnPaint(CefRefPtr<CefBrowser> browser,PaintElementType type,const RectList & dirtyRects,const void * buffer,int width,int height)200   virtual void OnPaint(CefRefPtr<CefBrowser> browser,
201                        PaintElementType type,
202                        const RectList& dirtyRects,
203                        const void* buffer,
204                        int width,
205                        int height) override {}
206 
RunTest()207   void RunTest() override {
208     AddResource(kOsrPopupJSOtherClientMainUrl, "<html>Main</html>",
209                 "text/html");
210 
211     // Create the browser.
212     CreateOSRBrowser(kOsrPopupJSOtherClientMainUrl);
213 
214     // Time out the test after a reasonable period of time.
215     SetTestTimeout();
216   }
217 
OnBeforePopup(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const CefString & target_url,const CefString & target_frame_name,cef_window_open_disposition_t target_disposition,bool user_gesture,const CefPopupFeatures & popupFeatures,CefWindowInfo & windowInfo,CefRefPtr<CefClient> & client,CefBrowserSettings & settings,CefRefPtr<CefDictionaryValue> & extra_info,bool * no_javascript_access)218   bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
219                      CefRefPtr<CefFrame> frame,
220                      const CefString& target_url,
221                      const CefString& target_frame_name,
222                      cef_window_open_disposition_t target_disposition,
223                      bool user_gesture,
224                      const CefPopupFeatures& popupFeatures,
225                      CefWindowInfo& windowInfo,
226                      CefRefPtr<CefClient>& client,
227                      CefBrowserSettings& settings,
228                      CefRefPtr<CefDictionaryValue>& extra_info,
229                      bool* no_javascript_access) override {
230 #if defined(OS_WIN)
231     windowInfo.SetAsWindowless(GetDesktopWindow());
232 #else
233     windowInfo.SetAsWindowless(kNullWindowHandle);
234 #endif
235 
236     client = other_;
237 
238     got_before_popup_.yes();
239     return false;
240   }
241 
Close(CefRefPtr<CefBrowser> browser)242   void Close(CefRefPtr<CefBrowser> browser) {
243     browser->StopLoad();
244     CloseBrowser(browser, true);
245   }
246 
OnAfterCreated(CefRefPtr<CefBrowser> browser)247   void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
248     TestHandler::OnAfterCreated(browser);
249     if (browser->IsPopup()) {
250       got_after_created_popup_.yes();
251     }
252   }
253 
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading,bool canGoBack,bool canGoForward)254   void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
255                             bool isLoading,
256                             bool canGoBack,
257                             bool canGoForward) override {
258     if (isLoading)
259       return;
260 
261     if (browser->IsPopup()) {
262       got_load_end_popup_.yes();
263       CefPostDelayedTask(
264           TID_UI,
265           base::BindOnce(&OsrPopupJSOtherClientTestHandler::Close, this,
266                          browser),
267           100);
268     } else {
269       browser->GetMainFrame()->LoadURL("javascript:window.open('about:blank')");
270     }
271   }
272 
OnBeforeClose(CefRefPtr<CefBrowser> browser)273   void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
274     TestHandler::OnBeforeClose(browser);
275     other_ = nullptr;
276     if (browser->IsPopup()) {
277       got_before_close_popup_.yes();
278       DestroyTest();
279     }
280   }
281 
282  private:
CreateOSRBrowser(const CefString & url)283   void CreateOSRBrowser(const CefString& url) {
284     CefWindowInfo windowInfo;
285     CefBrowserSettings settings;
286 
287 #if defined(OS_WIN)
288     windowInfo.SetAsWindowless(GetDesktopWindow());
289 #else
290     windowInfo.SetAsWindowless(kNullWindowHandle);
291 #endif
292 
293     CefBrowserHost::CreateBrowser(windowInfo, this, url, settings, nullptr,
294                                   nullptr);
295   }
296 
DestroyTest()297   void DestroyTest() override {
298     EXPECT_TRUE(got_after_created_popup_);
299     EXPECT_TRUE(got_load_end_popup_);
300     EXPECT_TRUE(got_before_close_popup_);
301     EXPECT_TRUE(got_before_popup_);
302     TestHandler::DestroyTest();
303   }
304 
305   TrackCallback got_before_popup_;
306   TrackCallback got_after_created_popup_;
307   TrackCallback got_load_end_popup_;
308   TrackCallback got_before_close_popup_;
309   CefRefPtr<CefClient> other_;
310 
311   IMPLEMENT_REFCOUNTING(OsrPopupJSOtherClientTestHandler);
312 };
313 
314 class OsrPopupJSOtherCefClient : public CefClient,
315                                  public CefLoadHandler,
316                                  public CefLifeSpanHandler,
317                                  public CefRenderHandler {
318  public:
OsrPopupJSOtherCefClient()319   OsrPopupJSOtherCefClient() { handler_ = nullptr; }
320 
SetHandler(CefRefPtr<OsrPopupJSOtherClientTestHandler> handler)321   void SetHandler(CefRefPtr<OsrPopupJSOtherClientTestHandler> handler) {
322     handler_ = handler;
323   }
324 
GetLoadHandler()325   virtual CefRefPtr<CefLoadHandler> GetLoadHandler() override { return this; }
326 
GetRenderHandler()327   virtual CefRefPtr<CefRenderHandler> GetRenderHandler() override {
328     return this;
329   }
330 
GetLifeSpanHandler()331   virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override {
332     return this;
333   }
334 
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading,bool canGoBack,bool canGoForward)335   virtual void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
336                                     bool isLoading,
337                                     bool canGoBack,
338                                     bool canGoForward) override {
339     if (handler_) {
340       handler_->OnLoadingStateChange(browser, isLoading, canGoBack,
341                                      canGoForward);
342     }
343   }
344 
OnAfterCreated(CefRefPtr<CefBrowser> browser)345   virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
346     handler_->OnAfterCreated(browser);
347   }
348 
OnBeforeClose(CefRefPtr<CefBrowser> browser)349   virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
350     handler_->OnBeforeClose(browser);
351     handler_ = nullptr;
352   }
353 
OnBeforePopup(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const CefString & target_url,const CefString & target_frame_name,cef_window_open_disposition_t target_disposition,bool user_gesture,const CefPopupFeatures & popupFeatures,CefWindowInfo & windowInfo,CefRefPtr<CefClient> & client,CefBrowserSettings & settings,CefRefPtr<CefDictionaryValue> & extra_info,bool * no_javascript_access)354   virtual bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
355                              CefRefPtr<CefFrame> frame,
356                              const CefString& target_url,
357                              const CefString& target_frame_name,
358                              cef_window_open_disposition_t target_disposition,
359                              bool user_gesture,
360                              const CefPopupFeatures& popupFeatures,
361                              CefWindowInfo& windowInfo,
362                              CefRefPtr<CefClient>& client,
363                              CefBrowserSettings& settings,
364                              CefRefPtr<CefDictionaryValue>& extra_info,
365                              bool* no_javascript_access) override {
366     return true;
367   }
368 
GetViewRect(CefRefPtr<CefBrowser> browser,CefRect & rect)369   virtual void GetViewRect(CefRefPtr<CefBrowser> browser,
370                            CefRect& rect) override {
371     rect = CefRect(0, 0, kOsrWidth, kOsrHeight);
372   }
373 
OnPaint(CefRefPtr<CefBrowser> browser,PaintElementType type,const RectList & dirtyRects,const void * buffer,int width,int height)374   virtual void OnPaint(CefRefPtr<CefBrowser> browser,
375                        PaintElementType type,
376                        const RectList& dirtyRects,
377                        const void* buffer,
378                        int width,
379                        int height) override {}
380 
381  private:
382   CefRefPtr<OsrPopupJSOtherClientTestHandler> handler_;
383 
384   IMPLEMENT_REFCOUNTING(OsrPopupJSOtherCefClient);
385 };
386 
387 }  // namespace
388 
389 // Test creation of an OSR-popup with another client.
TEST(OSRTest,OsrPopupJSOtherClient)390 TEST(OSRTest, OsrPopupJSOtherClient) {
391   CefRefPtr<OsrPopupJSOtherCefClient> client = new OsrPopupJSOtherCefClient();
392   CefRefPtr<OsrPopupJSOtherClientTestHandler> handler =
393       new OsrPopupJSOtherClientTestHandler(client);
394   client->SetHandler(handler);
395   handler->ExecuteTest();
396   ReleaseAndWaitForDestructor(handler);
397 }
398