• 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 "tests/ceftests/extensions/extension_test_handler.h"
6 
7 #include "tests/ceftests/test_util.h"
8 #include "tests/shared/browser/extension_util.h"
9 
10 namespace {
11 
12 const char kExtensionPath[] = "view-extension";
13 
14 // Test extension load/unload.
15 class ViewLoadUnloadTestHandler : public ExtensionTestHandler {
16  public:
ViewLoadUnloadTestHandler(RequestContextType request_context_type)17   explicit ViewLoadUnloadTestHandler(RequestContextType request_context_type)
18       : ExtensionTestHandler(request_context_type) {
19     // Only creating the extension browser.
20     set_create_main_browser(false);
21   }
22 
23   // CefExtensionHandler methods:
OnExtensionLoaded(CefRefPtr<CefExtension> extension)24   void OnExtensionLoaded(CefRefPtr<CefExtension> extension) override {
25     EXPECT_TRUE(CefCurrentlyOn(TID_UI));
26     EXPECT_TRUE(extension);
27     EXPECT_TRUE(extension->IsLoaded());
28     EXPECT_TRUE(extension->GetLoaderContext());
29     EXPECT_TRUE(
30         loader_request_context()->IsSame(extension->GetLoaderContext()));
31     VerifyExtension(extension);
32 
33     EXPECT_FALSE(got_loaded_);
34     got_loaded_.yes();
35 
36     EXPECT_FALSE(extension_);
37     extension_ = extension;
38 
39     CreateBrowserForExtension();
40   }
41 
OnExtensionUnloaded(CefRefPtr<CefExtension> extension)42   void OnExtensionUnloaded(CefRefPtr<CefExtension> extension) override {
43     EXPECT_TRUE(CefCurrentlyOn(TID_UI));
44     EXPECT_TRUE(extension);
45     EXPECT_FALSE(extension->IsLoaded());
46     EXPECT_FALSE(extension->GetLoaderContext());
47 
48     EXPECT_FALSE(got_unloaded_);
49     got_unloaded_.yes();
50 
51     EXPECT_TRUE(extension_);
52     EXPECT_TRUE(extension_->IsSame(extension));
53 
54     // The extension should no longer be registered with the context.
55     if (loader_request_context())
56       VerifyExtensionInContext(extension, loader_request_context(), false,
57                                true);
58     if (request_context() && !request_context_same_loader())
59       VerifyExtensionInContext(extension, request_context(), false, false);
60 
61     extension_ = nullptr;
62 
63     // Execute asynchronously so call stacks have a chance to unwind.
64     // Will close the browser windows.
65     CefPostTask(TID_UI,
66                 base::BindOnce(&ViewLoadUnloadTestHandler::DestroyTest, this));
67   }
68 
69   // CefLoadHandler methods:
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading,bool canGoBack,bool canGoForward)70   void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
71                             bool isLoading,
72                             bool canGoBack,
73                             bool canGoForward) override {
74     EXPECT_FALSE(browser->GetHost()->IsBackgroundHost());
75 
76     CefRefPtr<CefExtension> extension = browser->GetHost()->GetExtension();
77     EXPECT_TRUE(extension);
78     EXPECT_TRUE(extension_->IsSame(extension));
79 
80     if (isLoading) {
81       EXPECT_FALSE(extension_browser_);
82       extension_browser_ = browser;
83     } else {
84       EXPECT_TRUE(browser->IsSame(extension_browser_));
85 
86       const std::string& url = browser->GetMainFrame()->GetURL();
87       EXPECT_STREQ(extension_url_.c_str(), url.c_str());
88 
89       EXPECT_FALSE(got_load_done_);
90       got_load_done_.yes();
91 
92       TriggerDestroyTestIfDone();
93     }
94   }
95 
96   // CefResourceRequestHandler methods:
GetResourceHandler(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request)97   CefRefPtr<CefResourceHandler> GetResourceHandler(
98       CefRefPtr<CefBrowser> browser,
99       CefRefPtr<CefFrame> frame,
100       CefRefPtr<CefRequest> request) override {
101     EXPECT_FALSE(browser->GetHost()->IsBackgroundHost());
102     EXPECT_TRUE(browser->IsSame(extension_browser_));
103 
104     CefRefPtr<CefExtension> extension = browser->GetHost()->GetExtension();
105     EXPECT_TRUE(extension);
106     EXPECT_TRUE(extension_->IsSame(extension));
107 
108     const std::string& url = request->GetURL();
109     EXPECT_STREQ(extension_url_.c_str(), url.c_str());
110 
111     EXPECT_FALSE(got_url_request_);
112     got_url_request_.yes();
113 
114     // Handle the resource request.
115     return RoutingTestHandler::GetResourceHandler(browser, frame, request);
116   }
117 
118  protected:
OnLoadExtensions()119   void OnLoadExtensions() override {
120     LoadExtension(kExtensionPath, CreateManifest());
121   }
122 
OnMessage(CefRefPtr<CefBrowser> browser,const std::string & message)123   bool OnMessage(CefRefPtr<CefBrowser> browser,
124                  const std::string& message) override {
125     EXPECT_FALSE(browser->GetHost()->IsBackgroundHost());
126     EXPECT_STREQ("extension_onload", message.c_str());
127 
128     CefRefPtr<CefExtension> extension = browser->GetHost()->GetExtension();
129     EXPECT_TRUE(extension);
130     EXPECT_TRUE(extension_->IsSame(extension));
131 
132     EXPECT_TRUE(browser->IsSame(extension_browser_));
133 
134     EXPECT_FALSE(got_body_onload_);
135     got_body_onload_.yes();
136 
137     TriggerDestroyTestIfDone();
138     return true;
139   }
140 
OnDestroyTest()141   void OnDestroyTest() override {
142     extension_browser_ = nullptr;
143 
144     EXPECT_TRUE(got_loaded_);
145     EXPECT_TRUE(got_url_request_);
146     EXPECT_TRUE(got_body_onload_);
147     EXPECT_TRUE(got_load_done_);
148     EXPECT_TRUE(got_unloaded_);
149   }
150 
151   // Create the default manifest.
CreateManifest() const152   CefRefPtr<CefDictionaryValue> CreateManifest() const {
153     return CreateDefaultManifest(ApiPermissionsList());
154   }
155 
156   // Verify |extension| contents.
VerifyExtension(CefRefPtr<CefExtension> extension) const157   void VerifyExtension(CefRefPtr<CefExtension> extension) const {
158     EXPECT_STREQ(("extensions/" + std::string(kExtensionPath)).c_str(),
159                  client::extension_util::GetInternalExtensionResourcePath(
160                      extension->GetPath())
161                      .c_str());
162 
163     CefRefPtr<CefDictionaryValue> expected_manifest = CreateManifest();
164     TestDictionaryEqual(expected_manifest, extension->GetManifest());
165 
166     VerifyExtensionInContext(extension, loader_request_context(), true, true);
167     if (!request_context_same_loader())
168       VerifyExtensionInContext(extension, request_context(), true, false);
169   }
170 
CreateBrowserForExtension()171   void CreateBrowserForExtension() {
172     const std::string& identifier = extension_->GetIdentifier();
173     EXPECT_FALSE(identifier.empty());
174     const std::string& origin =
175         client::extension_util::GetExtensionOrigin(identifier);
176     EXPECT_FALSE(origin.empty());
177 
178     // Add extension resources.
179     extension_url_ = origin + "extension.html";
180     AddResource(extension_url_,
181                 "<html><body onLoad=" + GetMessageJS("extension_onload") +
182                     ">Extension</body></html>",
183                 "text/html");
184 
185     // Create a browser to host the extension.
186     CreateBrowser(extension_url_, request_context());
187   }
188 
TriggerDestroyTestIfDone()189   void TriggerDestroyTestIfDone() {
190     if (got_body_onload_ && got_load_done_) {
191       TriggerDestroyTest();
192     }
193   }
194 
TriggerDestroyTest()195   virtual void TriggerDestroyTest() {
196     // Execute asynchronously so call stacks have a chance to unwind.
197     CefPostTask(TID_UI,
198                 base::BindOnce(&ViewLoadUnloadTestHandler::UnloadExtension,
199                                this, extension_));
200   }
201 
202   CefRefPtr<CefExtension> extension_;
203   std::string extension_url_;
204   CefRefPtr<CefBrowser> extension_browser_;
205 
206   TrackCallback got_loaded_;
207   TrackCallback got_url_request_;
208   TrackCallback got_body_onload_;
209   TrackCallback got_load_done_;
210   TrackCallback got_unloaded_;
211 
212   IMPLEMENT_REFCOUNTING(ViewLoadUnloadTestHandler);
213   DISALLOW_COPY_AND_ASSIGN(ViewLoadUnloadTestHandler);
214 };
215 
216 }  // namespace
217 
218 EXTENSION_TEST_GROUP_ALL(ViewLoadUnload, ViewLoadUnloadTestHandler)
219 
220 namespace {
221 
222 // Same as above but without the unload. Only do this with a custom context to
223 // avoid poluting the global context.
224 class ViewLoadNoUnloadTestHandler : public ViewLoadUnloadTestHandler {
225  public:
ViewLoadNoUnloadTestHandler(RequestContextType request_context_type)226   explicit ViewLoadNoUnloadTestHandler(RequestContextType request_context_type)
227       : ViewLoadUnloadTestHandler(request_context_type) {}
228 
229  protected:
TriggerDestroyTest()230   void TriggerDestroyTest() override {
231     // Release everything that references the request context. This should
232     // trigger unload of the extension.
233     CloseBrowser(extension_browser_, false);
234     extension_browser_ = nullptr;
235     ReleaseRequestContexts();
236   }
237 };
238 
239 }  // namespace
240 
241 EXTENSION_TEST_GROUP_MINIMAL_CUSTOM(ViewLoadNoUnload,
242                                     ViewLoadNoUnloadTestHandler)
243