- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / renderer / chrome_content_renderer_client_unittest.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/renderer/chrome_content_renderer_client.h"
6
7 #include <vector>
8
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/common/extensions/extension.h"
11 #include "chrome/common/extensions/extension_builder.h"
12 #include "chrome/renderer/searchbox/search_bouncer.h"
13 #include "content/public/common/webplugininfo.h"
14 #include "extensions/common/manifest_constants.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/WebKit/public/platform/WebString.h"
17 #include "third_party/WebKit/public/platform/WebVector.h"
18 #include "third_party/WebKit/public/web/WebPluginParams.h"
19 #include "url/gurl.h"
20
21 using WebKit::WebPluginParams;
22 using WebKit::WebString;
23 using WebKit::WebVector;
24 using chrome::ChromeContentRendererClient;
25 using content::WebPluginInfo;
26 using content::WebPluginMimeType;
27
28 namespace chrome {
29
30 namespace {
31 const bool kNaClRestricted = false;
32 const bool kNaClUnrestricted = true;
33 const bool kExtensionRestricted = false;
34 const bool kExtensionUnrestricted = true;
35 const bool kExtensionNotFromWebStore = false;
36 const bool kExtensionFromWebStore = true;
37 const bool kNotHostedApp = false;
38 const bool kHostedApp = true;
39
40 const char kExtensionUrl[] = "chrome-extension://extension_id/background.html";
41
42 const char kPhotosAppURL1[] = "https://foo.plus.google.com";
43 const char kPhotosAppURL2[] = "https://foo.plus.sandbox.google.com";
44 const char kPhotosManifestURL1[] = "https://ssl.gstatic.com/s2/oz/nacl/foo";
45 const char kPhotosManifestURL2[] = "https://ssl.gstatic.com/photos/nacl/foo";
46
47 const char kChatAppURL1[] = "https://foo.talkgadget.google.com";
48 const char kChatAppURL2[] = "https://foo.talk.google.com";
49 const char kChatManifestURL[] = "https://ssl.gstatic.com/chat/apps/fx";
50
51 bool AllowsDevInterfaces(const WebPluginParams& params) {
52   for (size_t i = 0; i < params.attributeNames.size(); ++i) {
53     if (params.attributeNames[i] == WebString::fromUTF8("@dev"))
54       return true;
55   }
56   return false;
57 }
58
59 void AddFakeDevAttribute(WebPluginParams* params) {
60   WebVector<WebString> names(static_cast<size_t>(1));
61   WebVector<WebString> values(static_cast<size_t>(1));
62   names[0] = WebString::fromUTF8("@dev");
63   values[0] = WebString();
64   params->attributeNames.swap(names);
65   params->attributeValues.swap(values);
66 }
67
68 void AddContentTypeHandler(content::WebPluginInfo* info,
69                            const char* mime_type,
70                            const char* manifest_url) {
71   content::WebPluginMimeType mime_type_info;
72   mime_type_info.mime_type = mime_type;
73   mime_type_info.additional_param_names.push_back(UTF8ToUTF16("nacl"));
74   mime_type_info.additional_param_values.push_back(
75       UTF8ToUTF16(manifest_url));
76   info->mime_types.push_back(mime_type_info);
77 }
78 }  // namespace
79
80 typedef testing::Test ChromeContentRendererClientTest;
81
82
83 scoped_refptr<const extensions::Extension> CreateTestExtension(
84     bool is_unrestricted, bool is_from_webstore, bool is_hosted_app,
85     const std::string& app_url) {
86   extensions::Manifest::Location location = is_unrestricted ?
87       extensions::Manifest::UNPACKED :
88       extensions::Manifest::INTERNAL;
89   int flags = is_from_webstore ?
90       extensions::Extension::FROM_WEBSTORE:
91       extensions::Extension::NO_FLAGS;
92
93   base::DictionaryValue manifest;
94   manifest.SetString("name", "NaCl Extension");
95   manifest.SetString("version", "1");
96   manifest.SetInteger("manifest_version", 2);
97   if (is_hosted_app) {
98     base::ListValue* url_list = new base::ListValue();
99     url_list->Append(base::Value::CreateStringValue(app_url));
100     manifest.Set(extensions::manifest_keys::kWebURLs, url_list);
101     manifest.SetString(extensions::manifest_keys::kLaunchWebURL, app_url);
102   }
103   std::string error;
104   return extensions::Extension::Create(base::FilePath(), location, manifest,
105                                        flags, &error);
106 }
107
108 scoped_refptr<const extensions::Extension> CreateExtension(
109     bool is_unrestricted, bool is_from_webstore) {
110   return CreateTestExtension(
111       is_unrestricted, is_from_webstore, kNotHostedApp, std::string());
112 }
113
114 scoped_refptr<const extensions::Extension> CreateHostedApp(
115     bool is_unrestricted, bool is_from_webstore, const std::string& app_url) {
116   return CreateTestExtension(is_unrestricted, is_from_webstore, kHostedApp,
117                              app_url);
118 }
119
120 TEST_F(ChromeContentRendererClientTest, NaClRestriction) {
121   // Unknown content types have no NaCl module.
122   {
123     WebPluginInfo info;
124     EXPECT_EQ(GURL(),
125               ChromeContentRendererClient::GetNaClContentHandlerURL(
126                   "application/x-foo", info));
127   }
128   // Known content types have a NaCl module.
129   {
130     WebPluginInfo info;
131     AddContentTypeHandler(&info, "application/x-foo", "www.foo.com");
132     EXPECT_EQ(GURL("www.foo.com"),
133               ChromeContentRendererClient::GetNaClContentHandlerURL(
134                   "application/x-foo", info));
135   }
136   // --enable-nacl allows all NaCl apps, with 'dev' interfaces.
137   {
138     WebPluginParams params;
139     EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
140         GURL(),
141         GURL(),
142         kNaClUnrestricted,
143         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
144         &params));
145     EXPECT_TRUE(AllowsDevInterfaces(params));
146   }
147   // Unrestricted extensions are allowed without --enable-nacl, with 'dev'
148   // interfaces if called from an extension url.
149   {
150     WebPluginParams params;
151     EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
152         GURL(),
153         GURL(kExtensionUrl),
154         kNaClRestricted,
155         CreateExtension(kExtensionUnrestricted, kExtensionNotFromWebStore)
156             .get(),
157         &params));
158     EXPECT_TRUE(AllowsDevInterfaces(params));
159   }
160   // CWS extensions are allowed without --enable-nacl, without 'dev'
161   // interfaces if called from an extension url.
162   {
163     WebPluginParams params;
164     EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
165         GURL(),
166         GURL(kExtensionUrl),
167         kNaClRestricted,
168         CreateExtension(kExtensionRestricted, kExtensionFromWebStore).get(),
169         &params));
170     EXPECT_FALSE(AllowsDevInterfaces(params));
171   }
172   // CWS extensions can't get 'dev' interfaces with --enable-nacl.
173   {
174     WebPluginParams params;
175     EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
176         GURL(),
177         GURL(kExtensionUrl),
178         kNaClUnrestricted,
179         CreateExtension(kExtensionRestricted, kExtensionFromWebStore).get(),
180         &params));
181     EXPECT_FALSE(AllowsDevInterfaces(params));
182   }
183   // CWS extensions can't get 'dev' interfaces by injecting a fake
184   // '@dev' attribute.
185   {
186     WebPluginParams params;
187     AddFakeDevAttribute(&params);
188     EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
189         GURL(),
190         GURL(kExtensionUrl),
191         kNaClRestricted,
192         CreateExtension(kExtensionRestricted, kExtensionFromWebStore).get(),
193         &params));
194     EXPECT_FALSE(AllowsDevInterfaces(params));
195   }
196   // The NaCl PDF extension is allowed without --enable-nacl, with 'dev'
197   // interfaces, from all URLs.
198   {
199     WebPluginParams params;
200     EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
201         GURL("chrome-extension://acadkphlmlegjaadjagenfimbpphcgnh"),
202         GURL(),
203         kNaClRestricted,
204         CreateExtension(kExtensionRestricted, kExtensionFromWebStore).get(),
205         &params));
206     EXPECT_TRUE(AllowsDevInterfaces(params));
207   }
208   // Whitelisted URLs are allowed without --enable-nacl, without 'dev'
209   // interfaces. There is a whitelist for the app URL and the manifest URL.
210   {
211     WebPluginParams params;
212     // Whitelisted Photos app is allowed (two app URLs, two manifest URLs)
213     EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
214         GURL(kPhotosManifestURL1),
215         GURL(kPhotosAppURL1),
216         kNaClRestricted,
217         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
218         &params));
219     EXPECT_FALSE(AllowsDevInterfaces(params));
220     EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
221         GURL(kPhotosManifestURL1),
222         GURL(kPhotosAppURL2),
223         kNaClRestricted,
224         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
225         &params));
226     EXPECT_FALSE(AllowsDevInterfaces(params));
227     EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
228         GURL(kPhotosManifestURL2),
229         GURL(kPhotosAppURL1),
230         kNaClRestricted,
231         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
232         &params));
233     EXPECT_FALSE(AllowsDevInterfaces(params));
234     EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
235         GURL(kPhotosManifestURL2),
236         GURL(kPhotosAppURL2),
237         kNaClRestricted,
238         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
239         &params));
240     EXPECT_FALSE(AllowsDevInterfaces(params));
241     // Whitelisted Chat app is allowed.
242     EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
243         GURL(kChatManifestURL),
244         GURL(kChatAppURL1),
245         kNaClRestricted,
246         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
247         &params));
248     EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
249         GURL(kChatManifestURL),
250         GURL(kChatAppURL2),
251         kNaClRestricted,
252         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
253         &params));
254
255     // Whitelisted manifest URL, bad app URLs, NOT allowed.
256     EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
257         GURL(kPhotosManifestURL1),
258         GURL("http://plus.google.com/foo"),  // http scheme
259         kNaClRestricted,
260         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
261         &params));
262     EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
263         GURL(kPhotosManifestURL1),
264         GURL("http://plus.sandbox.google.com/foo"),  // http scheme
265         kNaClRestricted,
266         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
267         &params));
268     EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
269         GURL(kPhotosManifestURL1),
270         GURL("https://plus.google.evil.com/foo"),  // bad host
271         kNaClRestricted,
272         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
273         &params));
274     // Whitelisted app URL, bad manifest URL, NOT allowed.
275     EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
276         GURL("http://ssl.gstatic.com/s2/oz/nacl/foo"),  // http scheme
277         GURL(kPhotosAppURL1),
278         kNaClRestricted,
279         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
280         &params));
281     EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
282         GURL("https://ssl.gstatic.evil.com/s2/oz/nacl/foo"),  // bad host
283         GURL(kPhotosAppURL1),
284         kNaClRestricted,
285         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
286         &params));
287     EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
288         GURL("https://ssl.gstatic.com/wrong/s2/oz/nacl/foo"),  // bad path
289         GURL(kPhotosAppURL1),
290         kNaClRestricted,
291         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
292         &params));
293   }
294   // Whitelisted URLs can't get 'dev' interfaces with --enable-nacl.
295   {
296     WebPluginParams params;
297     EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
298         GURL(kPhotosManifestURL1),
299         GURL(kPhotosAppURL1),
300         kNaClUnrestricted,
301         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
302         &params));
303     EXPECT_FALSE(AllowsDevInterfaces(params));
304   }
305   // Whitelisted URLs can't get 'dev' interfaces by injecting a fake
306   // '@dev' attribute.
307   {
308     WebPluginParams params;
309     AddFakeDevAttribute(&params);
310     EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
311         GURL(kPhotosManifestURL1),
312         GURL(kPhotosAppURL1),
313         kNaClRestricted,
314         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
315         &params));
316     EXPECT_FALSE(AllowsDevInterfaces(params));
317   }
318   // Non-whitelisted URLs are blocked without --enable-nacl.
319   {
320     WebPluginParams params;
321     EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
322         GURL(),
323         GURL("https://plus.google.com.evil.com/foo1"),
324         kNaClRestricted,
325         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
326         &params));
327     EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
328         GURL(),
329         GURL("https://plus.google.com.evil.com/foo2"),
330         kNaClRestricted,
331         CreateExtension(kExtensionRestricted, kExtensionFromWebStore).get(),
332         &params));
333     EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
334         GURL(),
335         GURL("https://talkgadget.google.com.evil.com/foo3"),
336         kNaClRestricted,
337         CreateExtension(kExtensionUnrestricted, kExtensionNotFromWebStore)
338             .get(),
339         &params));
340     EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
341         GURL(),
342         GURL("https://talkgadget.google.com.evil.com/foo4"),
343         kNaClRestricted,
344         CreateExtension(kExtensionUnrestricted, kExtensionFromWebStore).get(),
345         &params));
346   }
347   // Non chrome-extension:// URLs belonging to hosted apps are allowed.
348   {
349     WebPluginParams params;
350     EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
351         GURL(),
352         GURL("http://example.com/test.html"),
353         kNaClRestricted,
354         CreateHostedApp(kExtensionRestricted,
355                         kExtensionNotFromWebStore,
356                         "http://example.com/").get(),
357         &params));
358     EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
359         GURL(),
360         GURL("http://example.evil.com/test.html"),
361         kNaClRestricted,
362         CreateHostedApp(kExtensionRestricted,
363                         kExtensionNotFromWebStore,
364                         "http://example.com/").get(),
365         &params));
366   }
367 }
368
369 TEST_F(ChromeContentRendererClientTest, AllowPepperMediaStreamAPI) {
370   ChromeContentRendererClient test;
371 #if !defined(OS_ANDROID)
372   EXPECT_TRUE(test.AllowPepperMediaStreamAPI(GURL(kChatAppURL1)));
373   EXPECT_TRUE(test.AllowPepperMediaStreamAPI(GURL(kChatAppURL2)));
374 #else
375   EXPECT_FALSE(test.AllowPepperMediaStreamAPI(GURL(kChatAppURL1)));
376   EXPECT_FALSE(test.AllowPepperMediaStreamAPI(GURL(kChatAppURL2)));
377 #endif
378   EXPECT_FALSE(test.AllowPepperMediaStreamAPI(
379       GURL("http://talkgadget.google.com")));
380   EXPECT_FALSE(test.AllowPepperMediaStreamAPI(
381       GURL("https://talkgadget.evil.com")));
382 }
383
384 TEST_F(ChromeContentRendererClientTest, ShouldSuppressErrorPage) {
385   ChromeContentRendererClient client;
386   client.search_bouncer_.reset(new SearchBouncer);
387   client.search_bouncer_->OnSetSearchURLs(
388       std::vector<GURL>(), GURL("http://example.com/n"));
389   EXPECT_FALSE(client.ShouldSuppressErrorPage(GURL("http://example.com")));
390   EXPECT_TRUE(client.ShouldSuppressErrorPage(GURL("http://example.com/n")));
391 }
392
393 }  // namespace chrome