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/common/chrome_content_client.h"
6 
7 #include <string>
8 
9 #include "base/strings/string_split.h"
10 #include "base/strings/string_util.h"
11 #include "base/test/scoped_command_line.h"
12 #include "base/threading/platform_thread.h"
13 #include "build/build_config.h"
14 #include "content/public/common/content_switches.h"
15 #include "content/public/common/origin_util.h"
16 #include "content/public/test/test_utils.h"
17 #include "extensions/common/constants.h"
18 #include "ppapi/buildflags/buildflags.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "third_party/blink/public/common/loader/network_utils.h"
21 #include "url/gurl.h"
22 #include "url/origin.h"
23 #include "url/url_util.h"
24 
25 namespace chrome_common {
26 
27 #if BUILDFLAG(ENABLE_PLUGINS)
TEST(ChromeContentClientTest,FindMostRecent)28 TEST(ChromeContentClientTest, FindMostRecent) {
29   std::vector<std::unique_ptr<content::PepperPluginInfo>> version_vector;
30   // Test an empty vector.
31   EXPECT_EQ(nullptr, ChromeContentClient::FindMostRecentPlugin(version_vector));
32 
33   // Now test the vector with one element.
34   content::PepperPluginInfo info;
35   info.version = "1.0.0.0";
36   version_vector.push_back(std::make_unique<content::PepperPluginInfo>(info));
37 
38   content::PepperPluginInfo* most_recent =
39       ChromeContentClient::FindMostRecentPlugin(version_vector);
40   EXPECT_EQ("1.0.0.0", most_recent->version);
41 
42   content::PepperPluginInfo info5;
43   info5.version = "5.0.12.1";
44   content::PepperPluginInfo info6_12;
45   info6_12.version = "6.0.0.12";
46   content::PepperPluginInfo info6_13;
47   info6_13.version = "6.0.0.13";
48 
49   // Test highest version is picked.
50   version_vector.clear();
51   version_vector.push_back(std::make_unique<content::PepperPluginInfo>(info5));
52   version_vector.push_back(
53       std::make_unique<content::PepperPluginInfo>(info6_12));
54   version_vector.push_back(
55       std::make_unique<content::PepperPluginInfo>(info6_13));
56 
57   most_recent = ChromeContentClient::FindMostRecentPlugin(version_vector);
58   EXPECT_EQ("6.0.0.13", most_recent->version);
59 
60   // Test that order does not matter, validates tests below.
61   version_vector.clear();
62   version_vector.push_back(
63       std::make_unique<content::PepperPluginInfo>(info6_13));
64   version_vector.push_back(
65       std::make_unique<content::PepperPluginInfo>(info6_12));
66   version_vector.push_back(std::make_unique<content::PepperPluginInfo>(info5));
67 
68   most_recent = ChromeContentClient::FindMostRecentPlugin(version_vector);
69   EXPECT_EQ("6.0.0.13", most_recent->version);
70 
71   // Test real scenarios.
72   content::PepperPluginInfo component_flash;
73   component_flash.version = "4.3.2.1";
74   component_flash.is_external = false;
75   component_flash.name = "component_flash";
76 
77   content::PepperPluginInfo system_flash;
78   system_flash.version = "4.3.2.1";
79   system_flash.is_external = true;
80   system_flash.name = "system_flash";
81 
82   // The order here should be:
83   // 1. System Flash.
84   // 2. Component update.
85   version_vector.clear();
86   version_vector.push_back(
87       std::make_unique<content::PepperPluginInfo>(system_flash));
88   version_vector.push_back(
89       std::make_unique<content::PepperPluginInfo>(component_flash));
90   most_recent = ChromeContentClient::FindMostRecentPlugin(version_vector);
91   EXPECT_STREQ("system_flash", most_recent->name.c_str());
92 }
93 #endif  // BUILDFLAG(ENABLE_PLUGINS)
94 
TEST(ChromeContentClientTest,AdditionalSchemes)95 TEST(ChromeContentClientTest, AdditionalSchemes) {
96   EXPECT_TRUE(url::IsStandard(
97       extensions::kExtensionScheme,
98       url::Component(0, strlen(extensions::kExtensionScheme))));
99 
100   GURL extension_url(
101       "chrome-extension://abcdefghijklmnopqrstuvwxyzabcdef/foo.html");
102   url::Origin origin = url::Origin::Create(extension_url);
103   EXPECT_EQ("chrome-extension://abcdefghijklmnopqrstuvwxyzabcdef",
104             origin.Serialize());
105 
106   EXPECT_TRUE(
107       blink::network_utils::IsOriginSecure(GURL("chrome-native://newtab/")));
108 
109   GURL chrome_url(content::GetWebUIURL("dummyurl"));
110   EXPECT_TRUE(blink::network_utils::IsOriginSecure(chrome_url));
111   EXPECT_FALSE(content::OriginCanAccessServiceWorkers(chrome_url));
112   EXPECT_TRUE(
113       content::IsPotentiallyTrustworthyOrigin(url::Origin::Create(chrome_url)));
114 }
115 
116 class OriginTrialInitializationTestThread
117     : public base::PlatformThread::Delegate {
118  public:
OriginTrialInitializationTestThread(ChromeContentClient * chrome_client)119   explicit OriginTrialInitializationTestThread(
120       ChromeContentClient* chrome_client)
121       : chrome_client_(chrome_client) {}
122 
ThreadMain()123   void ThreadMain() override { AccessPolicy(chrome_client_, &policy_objects_); }
124 
125   // Static helper which can also be called from the main thread.
AccessPolicy(ChromeContentClient * content_client,std::vector<blink::OriginTrialPolicy * > * policy_objects)126   static void AccessPolicy(
127       ChromeContentClient* content_client,
128       std::vector<blink::OriginTrialPolicy*>* policy_objects) {
129     // Repeatedly access the lazily-created origin trial policy
130     for (int i = 0; i < 20; i++) {
131       blink::OriginTrialPolicy* policy = content_client->GetOriginTrialPolicy();
132       policy_objects->push_back(policy);
133       base::PlatformThread::YieldCurrentThread();
134     }
135   }
136 
policy_objects() const137   const std::vector<blink::OriginTrialPolicy*>* policy_objects() const {
138     return &policy_objects_;
139   }
140 
141  private:
142   ChromeContentClient* chrome_client_;
143   std::vector<blink::OriginTrialPolicy*> policy_objects_;
144 
145   DISALLOW_COPY_AND_ASSIGN(OriginTrialInitializationTestThread);
146 };
147 
148 // Test that the lazy initialization of Origin Trial policy is resistant to
149 // races with concurrent access. Failures (especially flaky) indicate that the
150 // race prevention is no longer sufficient.
TEST(ChromeContentClientTest,OriginTrialPolicyConcurrentInitialization)151 TEST(ChromeContentClientTest, OriginTrialPolicyConcurrentInitialization) {
152   ChromeContentClient content_client;
153   std::vector<blink::OriginTrialPolicy*> policy_objects;
154   OriginTrialInitializationTestThread thread(&content_client);
155   base::PlatformThreadHandle handle;
156 
157   ASSERT_TRUE(base::PlatformThread::Create(0, &thread, &handle));
158 
159   // Repeatedly access the lazily-created origin trial policy
160   OriginTrialInitializationTestThread::AccessPolicy(&content_client,
161                                                     &policy_objects);
162 
163   base::PlatformThread::Join(handle);
164 
165   ASSERT_EQ(20UL, policy_objects.size());
166 
167   blink::OriginTrialPolicy* first_policy = policy_objects[0];
168 
169   const std::vector<blink::OriginTrialPolicy*>* all_policy_objects[] = {
170       &policy_objects, thread.policy_objects(),
171   };
172 
173   for (const std::vector<blink::OriginTrialPolicy*>* thread_policy_objects :
174        all_policy_objects) {
175     EXPECT_GE(20UL, thread_policy_objects->size());
176     for (blink::OriginTrialPolicy* policy : *(thread_policy_objects)) {
177       EXPECT_EQ(first_policy, policy);
178     }
179   }
180 }
181 
182 }  // namespace chrome_common
183