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 "base/command_line.h"
6#include "base/path_service.h"
7#include "base/strings/stringprintf.h"
8#include "base/strings/utf_string_conversions.h"
9#include "chrome/browser/chrome_notification_types.h"
10#include "chrome/browser/content_settings/cookie_settings.h"
11#include "chrome/browser/content_settings/host_content_settings_map.h"
12#include "chrome/browser/content_settings/tab_specific_content_settings.h"
13#include "chrome/browser/net/url_request_mock_util.h"
14#include "chrome/browser/plugins/chrome_plugin_service_filter.h"
15#include "chrome/browser/profiles/profile.h"
16#include "chrome/browser/ui/browser.h"
17#include "chrome/browser/ui/browser_commands.h"
18#include "chrome/browser/ui/tabs/tab_strip_model.h"
19#include "chrome/common/chrome_switches.h"
20#include "chrome/common/render_messages.h"
21#include "chrome/test/base/in_process_browser_test.h"
22#include "chrome/test/base/test_switches.h"
23#include "chrome/test/base/ui_test_utils.h"
24#include "content/public/browser/browser_thread.h"
25#include "content/public/browser/notification_observer.h"
26#include "content/public/browser/notification_service.h"
27#include "content/public/browser/plugin_service.h"
28#include "content/public/browser/render_frame_host.h"
29#include "content/public/browser/render_process_host.h"
30#include "content/public/browser/render_view_host.h"
31#include "content/public/browser/web_contents.h"
32#include "content/public/common/content_switches.h"
33#include "content/public/test/browser_test_utils.h"
34#include "content/public/test/test_utils.h"
35#include "net/test/spawned_test_server/spawned_test_server.h"
36#include "net/test/url_request/url_request_mock_http_job.h"
37
38#include "widevine_cdm_version.h"  // In SHARED_INTERMEDIATE_DIR.
39
40#if defined(OS_MACOSX)
41#include "base/mac/scoped_nsautorelease_pool.h"
42#endif
43
44using content::BrowserThread;
45using net::URLRequestMockHTTPJob;
46
47class ContentSettingsTest : public InProcessBrowserTest {
48 public:
49  ContentSettingsTest()
50      : https_server_(net::SpawnedTestServer::TYPE_HTTPS,
51                      net::SpawnedTestServer::SSLOptions(
52                          net::SpawnedTestServer::SSLOptions::CERT_OK),
53                      base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))) {
54  }
55
56  virtual void SetUpOnMainThread() OVERRIDE {
57    BrowserThread::PostTask(
58        BrowserThread::IO, FROM_HERE,
59        base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
60  }
61
62  // Check the cookie for the given URL in an incognito window.
63  void CookieCheckIncognitoWindow(const GURL& url, bool cookies_enabled) {
64    ASSERT_TRUE(content::GetCookies(browser()->profile(), url).empty());
65
66    Browser* incognito = CreateIncognitoBrowser();
67    ASSERT_TRUE(content::GetCookies(incognito->profile(), url).empty());
68    ui_test_utils::NavigateToURL(incognito, url);
69    ASSERT_EQ(cookies_enabled,
70              !content::GetCookies(incognito->profile(), url).empty());
71
72    // Ensure incognito cookies don't leak to regular profile.
73    ASSERT_TRUE(content::GetCookies(browser()->profile(), url).empty());
74
75    // Ensure cookies get wiped after last incognito window closes.
76    content::WindowedNotificationObserver signal(
77        chrome::NOTIFICATION_BROWSER_CLOSED,
78        content::Source<Browser>(incognito));
79
80    chrome::CloseWindow(incognito);
81
82#if defined(OS_MACOSX)
83    // BrowserWindowController depends on the auto release pool being recycled
84    // in the message loop to delete itself, which frees the Browser object
85    // which fires this event.
86    AutoreleasePool()->Recycle();
87#endif
88
89    signal.Wait();
90
91    incognito = CreateIncognitoBrowser();
92    ASSERT_TRUE(content::GetCookies(incognito->profile(), url).empty());
93    chrome::CloseWindow(incognito);
94  }
95
96  void PreBasic(const GURL& url) {
97    ASSERT_TRUE(GetCookies(browser()->profile(), url).empty());
98
99    CookieCheckIncognitoWindow(url, true);
100
101    ui_test_utils::NavigateToURL(browser(), url);
102    ASSERT_FALSE(GetCookies(browser()->profile(), url).empty());
103  }
104
105  void Basic(const GURL& url) {
106    ASSERT_FALSE(GetCookies(browser()->profile(), url).empty());
107  }
108
109  net::SpawnedTestServer https_server_;
110};
111
112// Sanity check on cookies before we do other tests. While these can be written
113// in content_browsertests, we want to verify Chrome's cookie storage and how it
114// handles incognito windows.
115IN_PROC_BROWSER_TEST_F(ContentSettingsTest, PRE_BasicCookies) {
116  ASSERT_TRUE(test_server()->Start());
117  GURL http_url = test_server()->GetURL("files/setcookie.html");
118  PreBasic(http_url);
119}
120
121IN_PROC_BROWSER_TEST_F(ContentSettingsTest, BasicCookies) {
122  ASSERT_TRUE(test_server()->Start());
123  GURL http_url = test_server()->GetURL("files/setcookie.html");
124  Basic(http_url);
125}
126
127IN_PROC_BROWSER_TEST_F(ContentSettingsTest, PRE_BasicCookiesHttps) {
128  ASSERT_TRUE(https_server_.Start());
129  GURL https_url = https_server_.GetURL("files/setcookie.html");
130  PreBasic(https_url);
131}
132
133IN_PROC_BROWSER_TEST_F(ContentSettingsTest, BasicCookiesHttps) {
134  ASSERT_TRUE(https_server_.Start());
135  GURL https_url = https_server_.GetURL("files/setcookie.html");
136  Basic(https_url);
137}
138
139// Verify that cookies are being blocked.
140IN_PROC_BROWSER_TEST_F(ContentSettingsTest, PRE_BlockCookies) {
141  ASSERT_TRUE(test_server()->Start());
142  CookieSettings::Factory::GetForProfile(browser()->profile())->
143      SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
144  GURL url = test_server()->GetURL("files/setcookie.html");
145  ui_test_utils::NavigateToURL(browser(), url);
146  ASSERT_TRUE(GetCookies(browser()->profile(), url).empty());
147  CookieCheckIncognitoWindow(url, false);
148}
149
150// Ensure that the setting persists.
151IN_PROC_BROWSER_TEST_F(ContentSettingsTest, BlockCookies) {
152  ASSERT_EQ(
153      CONTENT_SETTING_BLOCK,
154      CookieSettings::Factory::GetForProfile(browser()->profile())->
155          GetDefaultCookieSetting(NULL));
156}
157
158// Verify that cookies can be allowed and set using exceptions for particular
159// website(s) when all others are blocked.
160IN_PROC_BROWSER_TEST_F(ContentSettingsTest, AllowCookiesUsingExceptions) {
161  ASSERT_TRUE(test_server()->Start());
162  GURL url = test_server()->GetURL("files/setcookie.html");
163  CookieSettings* settings =
164      CookieSettings::Factory::GetForProfile(browser()->profile()).get();
165  settings->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
166
167  ui_test_utils::NavigateToURL(browser(), url);
168  ASSERT_TRUE(GetCookies(browser()->profile(), url).empty());
169
170  settings->SetCookieSetting(
171      ContentSettingsPattern::FromURL(url),
172      ContentSettingsPattern::Wildcard(), CONTENT_SETTING_ALLOW);
173
174  ui_test_utils::NavigateToURL(browser(), url);
175  ASSERT_FALSE(GetCookies(browser()->profile(), url).empty());
176}
177
178// Verify that cookies can be blocked for a specific website using exceptions.
179IN_PROC_BROWSER_TEST_F(ContentSettingsTest, BlockCookiesUsingExceptions) {
180  ASSERT_TRUE(test_server()->Start());
181  GURL url = test_server()->GetURL("files/setcookie.html");
182  CookieSettings* settings =
183      CookieSettings::Factory::GetForProfile(browser()->profile()).get();
184  settings->SetCookieSetting(ContentSettingsPattern::FromURL(url),
185                             ContentSettingsPattern::Wildcard(),
186                             CONTENT_SETTING_BLOCK);
187
188  ui_test_utils::NavigateToURL(browser(), url);
189  ASSERT_TRUE(GetCookies(browser()->profile(), url).empty());
190
191  ASSERT_TRUE(https_server_.Start());
192  GURL unblocked_url = https_server_.GetURL("files/cookie1.html");
193
194  ui_test_utils::NavigateToURL(browser(), unblocked_url);
195  ASSERT_FALSE(GetCookies(browser()->profile(), unblocked_url).empty());
196}
197
198// This fails on ChromeOS because kRestoreOnStartup is ignored and the startup
199// preference is always "continue where I left off.
200#if !defined(OS_CHROMEOS)
201
202// Verify that cookies can be allowed and set using exceptions for particular
203// website(s) only for a session when all others are blocked.
204IN_PROC_BROWSER_TEST_F(ContentSettingsTest,
205                       PRE_AllowCookiesForASessionUsingExceptions) {
206  // NOTE: don't use test_server here, since we need the port to be the same
207  // across the restart.
208  GURL url = URLRequestMockHTTPJob::GetMockUrl(
209      base::FilePath(FILE_PATH_LITERAL("setcookie.html")));
210  CookieSettings* settings =
211      CookieSettings::Factory::GetForProfile(browser()->profile()).get();
212  settings->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
213
214  ui_test_utils::NavigateToURL(browser(), url);
215  ASSERT_TRUE(GetCookies(browser()->profile(), url).empty());
216
217  settings->SetCookieSetting(
218      ContentSettingsPattern::FromURL(url),
219      ContentSettingsPattern::Wildcard(), CONTENT_SETTING_SESSION_ONLY);
220  ui_test_utils::NavigateToURL(browser(), url);
221  ASSERT_FALSE(GetCookies(browser()->profile(), url).empty());
222}
223
224IN_PROC_BROWSER_TEST_F(ContentSettingsTest,
225                       AllowCookiesForASessionUsingExceptions) {
226  GURL url = URLRequestMockHTTPJob::GetMockUrl(
227      base::FilePath(FILE_PATH_LITERAL("setcookie.html")));
228  ASSERT_TRUE(GetCookies(browser()->profile(), url).empty());
229}
230
231#endif // !CHROME_OS
232
233// Regression test for http://crbug.com/63649.
234IN_PROC_BROWSER_TEST_F(ContentSettingsTest, RedirectLoopCookies) {
235  ASSERT_TRUE(test_server()->Start());
236
237  GURL test_url = test_server()->GetURL("files/redirect-loop.html");
238
239  CookieSettings::Factory::GetForProfile(browser()->profile())->
240      SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
241
242  ui_test_utils::NavigateToURL(browser(), test_url);
243
244  content::WebContents* web_contents =
245      browser()->tab_strip_model()->GetActiveWebContents();
246  ASSERT_EQ(base::UTF8ToUTF16(test_url.spec() + " failed to load"),
247            web_contents->GetTitle());
248
249  EXPECT_TRUE(TabSpecificContentSettings::FromWebContents(web_contents)->
250      IsContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES));
251}
252
253IN_PROC_BROWSER_TEST_F(ContentSettingsTest, ContentSettingsBlockDataURLs) {
254  GURL url("data:text/html,<title>Data URL</title><script>alert(1)</script>");
255
256  browser()->profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
257      CONTENT_SETTINGS_TYPE_JAVASCRIPT, CONTENT_SETTING_BLOCK);
258
259  ui_test_utils::NavigateToURL(browser(), url);
260
261  content::WebContents* web_contents =
262      browser()->tab_strip_model()->GetActiveWebContents();
263  ASSERT_EQ(base::UTF8ToUTF16("Data URL"), web_contents->GetTitle());
264
265  EXPECT_TRUE(TabSpecificContentSettings::FromWebContents(web_contents)->
266      IsContentBlocked(CONTENT_SETTINGS_TYPE_JAVASCRIPT));
267}
268
269// Tests that if redirect across origins occurs, the new process still gets the
270// content settings before the resource headers.
271IN_PROC_BROWSER_TEST_F(ContentSettingsTest, RedirectCrossOrigin) {
272  ASSERT_TRUE(test_server()->Start());
273
274  net::HostPortPair host_port = test_server()->host_port_pair();
275  DCHECK_EQ(host_port.host(), std::string("127.0.0.1"));
276
277  std::string redirect(base::StringPrintf(
278      "http://localhost:%d/files/redirect-cross-origin.html",
279      host_port.port()));
280  GURL test_url = test_server()->GetURL("server-redirect?" + redirect);
281
282  CookieSettings::Factory::GetForProfile(browser()->profile())->
283      SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
284
285  ui_test_utils::NavigateToURL(browser(), test_url);
286
287  content::WebContents* web_contents =
288      browser()->tab_strip_model()->GetActiveWebContents();
289
290  EXPECT_TRUE(TabSpecificContentSettings::FromWebContents(web_contents)->
291      IsContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES));
292}
293
294// On Aura NPAPI only works on Windows.
295#if !defined(USE_AURA) || defined(OS_WIN)
296
297class ClickToPlayPluginTest : public ContentSettingsTest {
298 public:
299  ClickToPlayPluginTest() {}
300
301#if defined(OS_MACOSX)
302  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
303    base::FilePath plugin_dir;
304    PathService::Get(base::DIR_MODULE, &plugin_dir);
305    plugin_dir = plugin_dir.AppendASCII("plugins");
306    // The plugins directory isn't read by default on the Mac, so it needs to be
307    // explicitly registered.
308    command_line->AppendSwitchPath(switches::kExtraPluginDir, plugin_dir);
309  }
310#endif
311};
312
313IN_PROC_BROWSER_TEST_F(ClickToPlayPluginTest, Basic) {
314  browser()->profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
315      CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_BLOCK);
316
317  GURL url = ui_test_utils::GetTestUrl(
318      base::FilePath(), base::FilePath().AppendASCII("clicktoplay.html"));
319  ui_test_utils::NavigateToURL(browser(), url);
320
321  base::string16 expected_title(base::ASCIIToUTF16("OK"));
322  content::TitleWatcher title_watcher(
323      browser()->tab_strip_model()->GetActiveWebContents(), expected_title);
324
325  content::WebContents* web_contents =
326      browser()->tab_strip_model()->GetActiveWebContents();
327  ChromePluginServiceFilter* filter = ChromePluginServiceFilter::GetInstance();
328  int process_id = web_contents->GetMainFrame()->GetProcess()->GetID();
329  base::FilePath path(FILE_PATH_LITERAL("blah"));
330  EXPECT_FALSE(filter->CanLoadPlugin(process_id, path));
331  filter->AuthorizeAllPlugins(web_contents, true, std::string());
332  EXPECT_TRUE(filter->CanLoadPlugin(process_id, path));
333
334  EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
335}
336
337// Verify that plugins can be allowed on a domain by adding an exception
338IN_PROC_BROWSER_TEST_F(ClickToPlayPluginTest, AllowException) {
339  GURL url = ui_test_utils::GetTestUrl(
340      base::FilePath(), base::FilePath().AppendASCII("clicktoplay.html"));
341
342  browser()->profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
343      CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_BLOCK);
344  browser()->profile()->GetHostContentSettingsMap()
345      ->SetContentSetting(ContentSettingsPattern::FromURL(url),
346                          ContentSettingsPattern::Wildcard(),
347                          CONTENT_SETTINGS_TYPE_PLUGINS,
348                          std::string(),
349                          CONTENT_SETTING_ALLOW);
350
351  base::string16 expected_title(base::ASCIIToUTF16("OK"));
352  content::TitleWatcher title_watcher(
353      browser()->tab_strip_model()->GetActiveWebContents(), expected_title);
354  ui_test_utils::NavigateToURL(browser(), url);
355  EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
356}
357
358// Verify that plugins can be blocked on a domain by adding an exception.
359IN_PROC_BROWSER_TEST_F(ClickToPlayPluginTest, BlockException) {
360  GURL url = ui_test_utils::GetTestUrl(
361      base::FilePath(), base::FilePath().AppendASCII("clicktoplay.html"));
362
363  browser()->profile()->GetHostContentSettingsMap()
364      ->SetContentSetting(ContentSettingsPattern::FromURL(url),
365                          ContentSettingsPattern::Wildcard(),
366                          CONTENT_SETTINGS_TYPE_PLUGINS,
367                          std::string(),
368                          CONTENT_SETTING_BLOCK);
369
370  base::string16 expected_title(base::ASCIIToUTF16("Click To Play"));
371  content::TitleWatcher title_watcher(
372      browser()->tab_strip_model()->GetActiveWebContents(), expected_title);
373  ui_test_utils::NavigateToURL(browser(), url);
374  EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
375}
376
377// Crashes on Mac Asan.  http://crbug.com/239169
378#if defined(OS_MACOSX)
379#define MAYBE_LoadAllBlockedPlugins DISABLED_LoadAllBlockedPlugins
380// TODO(jschuh): Flaky plugin tests. crbug.com/244653
381#elif defined(OS_WIN) && defined(ARCH_CPU_X86_64)
382#define MAYBE_LoadAllBlockedPlugins DISABLED_LoadAllBlockedPlugins
383#else
384#define MAYBE_LoadAllBlockedPlugins LoadAllBlockedPlugins
385#endif
386IN_PROC_BROWSER_TEST_F(ClickToPlayPluginTest, MAYBE_LoadAllBlockedPlugins) {
387  browser()->profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
388      CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_BLOCK);
389
390  GURL url = ui_test_utils::GetTestUrl(
391      base::FilePath(),
392      base::FilePath().AppendASCII("load_all_blocked_plugins.html"));
393  ui_test_utils::NavigateToURL(browser(), url);
394
395  base::string16 expected_title1(base::ASCIIToUTF16("1"));
396  content::TitleWatcher title_watcher1(
397      browser()->tab_strip_model()->GetActiveWebContents(), expected_title1);
398
399  ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
400      browser()->tab_strip_model()->GetActiveWebContents(), true,
401      std::string());
402  EXPECT_EQ(expected_title1, title_watcher1.WaitAndGetTitle());
403
404  base::string16 expected_title2(base::ASCIIToUTF16("2"));
405  content::TitleWatcher title_watcher2(
406      browser()->tab_strip_model()->GetActiveWebContents(), expected_title2);
407
408  ASSERT_TRUE(content::ExecuteScript(
409      browser()->tab_strip_model()->GetActiveWebContents(), "window.inject()"));
410
411  EXPECT_EQ(expected_title2, title_watcher2.WaitAndGetTitle());
412}
413
414// If this flakes, use http://crbug.com/113057.
415// TODO(jschuh): Hanging plugin tests. crbug.com/244653
416#if !defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
417IN_PROC_BROWSER_TEST_F(ClickToPlayPluginTest, NoCallbackAtLoad) {
418  browser()->profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
419      CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_BLOCK);
420
421  GURL url("data:application/vnd.npapi-test,CallOnStartup();");
422  ui_test_utils::NavigateToURL(browser(), url);
423
424  std::string script("CallOnStartup = function() { ");
425  script.append("document.documentElement.appendChild");
426  script.append("(document.createElement(\"head\")); ");
427  script.append("document.title = \"OK\"; }");
428
429  // Inject the callback function into the HTML page generated by the browser.
430  ASSERT_TRUE(content::ExecuteScript(
431      browser()->tab_strip_model()->GetActiveWebContents(), script));
432
433  base::string16 expected_title(base::ASCIIToUTF16("OK"));
434  content::TitleWatcher title_watcher(
435      browser()->tab_strip_model()->GetActiveWebContents(), expected_title);
436
437  ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
438      browser()->tab_strip_model()->GetActiveWebContents(), true,
439      std::string());
440
441  EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
442}
443#endif
444
445IN_PROC_BROWSER_TEST_F(ClickToPlayPluginTest, DeleteSelfAtLoad) {
446  browser()->profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
447      CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_BLOCK);
448
449  GURL url = ui_test_utils::GetTestUrl(
450      base::FilePath(),
451      base::FilePath().AppendASCII("plugin_delete_self_at_load.html"));
452  ui_test_utils::NavigateToURL(browser(), url);
453
454  base::string16 expected_title(base::ASCIIToUTF16("OK"));
455  content::TitleWatcher title_watcher(
456      browser()->tab_strip_model()->GetActiveWebContents(), expected_title);
457
458  ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
459      browser()->tab_strip_model()->GetActiveWebContents(), true,
460      std::string());
461
462  EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
463}
464
465#endif  // !defined(USE_AURA) || defined(OS_WIN)
466
467#if defined(ENABLE_PLUGINS)
468class PepperContentSettingsSpecialCasesTest : public ContentSettingsTest {
469 protected:
470  static const char* const kExternalClearKeyMimeType;
471
472  // Registers any CDM plugins not registered by default.
473  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
474#if defined(ENABLE_PEPPER_CDMS)
475    // Platform-specific filename relative to the chrome executable.
476#if defined(OS_WIN)
477    const char kLibraryName[] = "clearkeycdmadapter.dll";
478#else  // !defined(OS_WIN)
479#if defined(OS_MACOSX)
480    const char kLibraryName[] = "clearkeycdmadapter.plugin";
481#elif defined(OS_POSIX)
482    const char kLibraryName[] = "libclearkeycdmadapter.so";
483#endif  // defined(OS_MACOSX)
484#endif  // defined(OS_WIN)
485
486    // Append the switch to register the External Clear Key CDM.
487    base::FilePath::StringType pepper_plugins = BuildPepperPluginRegistration(
488        kLibraryName, "Clear Key CDM", kExternalClearKeyMimeType);
489#if defined(WIDEVINE_CDM_AVAILABLE) && defined(WIDEVINE_CDM_IS_COMPONENT)
490    // The CDM must be registered when it is a component.
491    pepper_plugins.append(FILE_PATH_LITERAL(","));
492    pepper_plugins.append(
493        BuildPepperPluginRegistration(kWidevineCdmAdapterFileName,
494                                      kWidevineCdmDisplayName,
495                                      kWidevineCdmPluginMimeType));
496#endif  // defined(WIDEVINE_CDM_AVAILABLE) && defined(WIDEVINE_CDM_IS_COMPONENT)
497    command_line->AppendSwitchNative(switches::kRegisterPepperPlugins,
498                                     pepper_plugins);
499#endif  // defined(ENABLE_PEPPER_CDMS)
500
501#if !defined(DISABLE_NACL)
502    // Ensure NaCl can run.
503    command_line->AppendSwitch(switches::kEnableNaCl);
504#endif
505  }
506
507  void RunLoadPepperPluginTest(const char* mime_type, bool expect_loaded) {
508    const char* expected_result = expect_loaded ? "Loaded" : "Not Loaded";
509    content::WebContents* web_contents =
510        browser()->tab_strip_model()->GetActiveWebContents();
511
512    base::string16 expected_title(base::ASCIIToUTF16(expected_result));
513    content::TitleWatcher title_watcher(web_contents, expected_title);
514
515    // GetTestUrl assumes paths, so we must append query parameters to result.
516    GURL file_url = ui_test_utils::GetTestUrl(
517        base::FilePath(),
518        base::FilePath().AppendASCII("load_pepper_plugin.html"));
519    GURL url(file_url.spec() +
520             base::StringPrintf("?mimetype=%s", mime_type));
521    ui_test_utils::NavigateToURL(browser(), url);
522
523    EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
524    EXPECT_EQ(!expect_loaded,
525              TabSpecificContentSettings::FromWebContents(web_contents)->
526                  IsContentBlocked(CONTENT_SETTINGS_TYPE_PLUGINS));
527  }
528
529  void RunJavaScriptBlockedTest(const char* html_file,
530                                bool expect_is_javascript_content_blocked) {
531    // Because JavaScript is blocked, <title> will be the only title set.
532    // Checking for it ensures that the page loaded, though that is not always
533    // sufficient - see below.
534    const char* const kExpectedTitle = "Initial Title";
535    content::WebContents* web_contents =
536        browser()->tab_strip_model()->GetActiveWebContents();
537    TabSpecificContentSettings* tab_settings =
538        TabSpecificContentSettings::FromWebContents(web_contents);
539    base::string16 expected_title(base::ASCIIToUTF16(kExpectedTitle));
540    content::TitleWatcher title_watcher(web_contents, expected_title);
541
542    // Because JavaScript is blocked, we cannot rely on JavaScript to set a
543    // title, telling us the test is complete.
544    // As a result, it is possible to reach the IsContentBlocked() checks below
545    // before the blocked content can be reported to the browser process.
546    // See http://crbug.com/306702.
547    // Therefore, when expecting blocked content, we must wait until it has been
548    // reported by checking IsContentBlocked() when notified that
549    // NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED. (It is not sufficient to wait
550    // for just the notification because the same notification is reported for
551    // other reasons and the notification contains no indication of what
552    // caused it.)
553    content::WindowedNotificationObserver javascript_content_blocked_observer(
554              chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
555              base::Bind(&TabSpecificContentSettings::IsContentBlocked,
556                                   base::Unretained(tab_settings),
557                                   CONTENT_SETTINGS_TYPE_JAVASCRIPT));
558
559    GURL url = ui_test_utils::GetTestUrl(
560        base::FilePath(), base::FilePath().AppendASCII(html_file));
561    ui_test_utils::NavigateToURL(browser(), url);
562
563    // Always wait for the page to load.
564    EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
565
566    if (expect_is_javascript_content_blocked) {
567      javascript_content_blocked_observer.Wait();
568    } else {
569      // Since there is no notification that content is not blocked and no
570      // content is blocked when |expect_is_javascript_content_blocked| is
571      // false, javascript_content_blocked_observer would never succeed.
572      // There is no way to ensure blocked content would not have been reported
573      // after the check below. For coverage of this scenario, we must rely on
574      // the TitleWatcher adding sufficient delay most of the time.
575    }
576
577    EXPECT_EQ(expect_is_javascript_content_blocked,
578              tab_settings->IsContentBlocked(CONTENT_SETTINGS_TYPE_JAVASCRIPT));
579    EXPECT_FALSE(tab_settings->IsContentBlocked(CONTENT_SETTINGS_TYPE_PLUGINS));
580  }
581
582 private:
583  // Builds the string to pass to kRegisterPepperPlugins for a single
584  // plugin using the provided parameters and a dummy version.
585  // Multiple results may be passed to kRegisterPepperPlugins, separated by ",".
586  base::FilePath::StringType BuildPepperPluginRegistration(
587      const char* library_name,
588      const char* display_name,
589      const char* mime_type) {
590    base::FilePath plugin_dir;
591    EXPECT_TRUE(PathService::Get(base::DIR_MODULE, &plugin_dir));
592
593    base::FilePath plugin_lib = plugin_dir.AppendASCII(library_name);
594    EXPECT_TRUE(base::PathExists(plugin_lib));
595
596    base::FilePath::StringType pepper_plugin = plugin_lib.value();
597    pepper_plugin.append(FILE_PATH_LITERAL("#"));
598#if defined(OS_WIN)
599    pepper_plugin.append(base::ASCIIToWide(display_name));
600#else
601    pepper_plugin.append(display_name);
602#endif
603    pepper_plugin.append(FILE_PATH_LITERAL("#A CDM#0.1.0.0;"));
604#if defined(OS_WIN)
605    pepper_plugin.append(base::ASCIIToWide(mime_type));
606#else
607    pepper_plugin.append(mime_type);
608#endif
609
610    return pepper_plugin;
611  }
612};
613
614const char* const
615PepperContentSettingsSpecialCasesTest::kExternalClearKeyMimeType =
616    "application/x-ppapi-clearkey-cdm";
617
618class PepperContentSettingsSpecialCasesPluginsBlockedTest
619    : public PepperContentSettingsSpecialCasesTest {
620 public:
621  virtual void SetUpOnMainThread() OVERRIDE {
622    PepperContentSettingsSpecialCasesTest::SetUpOnMainThread();
623    browser()->profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
624        CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_BLOCK);
625  }
626};
627
628class PepperContentSettingsSpecialCasesJavaScriptBlockedTest
629    : public PepperContentSettingsSpecialCasesTest {
630 public:
631  virtual void SetUpOnMainThread() OVERRIDE {
632    PepperContentSettingsSpecialCasesTest::SetUpOnMainThread();
633    browser()->profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
634        CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_ALLOW);
635    browser()->profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
636        CONTENT_SETTINGS_TYPE_JAVASCRIPT, CONTENT_SETTING_BLOCK);
637  }
638};
639
640#if defined(ENABLE_PEPPER_CDMS)
641// A sanity check to verify that the plugin that is used as a baseline below
642// can be loaded.
643IN_PROC_BROWSER_TEST_F(PepperContentSettingsSpecialCasesTest, Baseline) {
644#if defined(OS_WIN) && defined(USE_ASH)
645  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
646  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
647    return;
648#endif
649  browser()->profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
650      CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_ALLOW);
651
652  RunLoadPepperPluginTest(kExternalClearKeyMimeType, true);
653}
654#endif  // defined(ENABLE_PEPPER_CDMS)
655
656// The following tests verify that Pepper plugins that use JavaScript settings
657// instead of Plug-ins settings still work when Plug-ins are blocked.
658
659#if defined(ENABLE_PEPPER_CDMS)
660// The plugin successfully loaded above is blocked.
661IN_PROC_BROWSER_TEST_F(PepperContentSettingsSpecialCasesPluginsBlockedTest,
662                       Normal) {
663#if defined(OS_WIN) && defined(USE_ASH)
664  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
665  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
666    return;
667#endif
668  RunLoadPepperPluginTest(kExternalClearKeyMimeType, false);
669}
670
671#if defined(WIDEVINE_CDM_AVAILABLE)
672IN_PROC_BROWSER_TEST_F(PepperContentSettingsSpecialCasesPluginsBlockedTest,
673                       WidevineCdm) {
674#if defined(OS_WIN) && defined(USE_ASH)
675  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
676  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
677    return;
678#endif
679  RunLoadPepperPluginTest(kWidevineCdmPluginMimeType, true);
680}
681#endif  // defined(WIDEVINE_CDM_AVAILABLE)
682#endif  // defined(ENABLE_PEPPER_CDMS)
683
684#if !defined(DISABLE_NACL)
685IN_PROC_BROWSER_TEST_F(PepperContentSettingsSpecialCasesPluginsBlockedTest,
686                       NaCl) {
687#if defined(OS_WIN) && defined(USE_ASH)
688  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
689  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
690    return;
691#endif
692  RunLoadPepperPluginTest("application/x-nacl", true);
693}
694#endif  // !defined(DISABLE_NACL)
695
696// The following tests verify that those same Pepper plugins do not work when
697// JavaScript is blocked.
698
699#if defined(ENABLE_PEPPER_CDMS)
700// A plugin with no special behavior is not blocked when JavaScript is blocked.
701IN_PROC_BROWSER_TEST_F(PepperContentSettingsSpecialCasesJavaScriptBlockedTest,
702                       Normal) {
703#if defined(OS_WIN) && defined(USE_ASH)
704  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
705  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
706    return;
707#endif
708  RunJavaScriptBlockedTest("load_clearkey_no_js.html", false);
709}
710
711#if defined(WIDEVINE_CDM_AVAILABLE)
712IN_PROC_BROWSER_TEST_F(PepperContentSettingsSpecialCasesJavaScriptBlockedTest,
713                       WidevineCdm) {
714#if defined(OS_WIN) && defined(USE_ASH)
715  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
716  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
717    return;
718#endif
719  RunJavaScriptBlockedTest("load_widevine_no_js.html", true);
720}
721#endif  // defined(WIDEVINE_CDM_AVAILABLE)
722#endif  // defined(ENABLE_PEPPER_CDMS)
723
724#if !defined(DISABLE_NACL)
725IN_PROC_BROWSER_TEST_F(PepperContentSettingsSpecialCasesJavaScriptBlockedTest,
726                       NaCl) {
727#if defined(OS_WIN) && defined(USE_ASH)
728  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
729  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
730    return;
731#endif
732  RunJavaScriptBlockedTest("load_nacl_no_js.html", true);
733}
734#endif  // !defined(DISABLE_NACL)
735
736#endif  // defined(ENABLE_PLUGINS)
737