Fix emulator build error
[platform/framework/web/chromium-efl.git] / components / permissions / permission_context_base_unittest.cc
1 // Copyright 2014 The Chromium Authors
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 "components/permissions/permission_context_base.h"
6
7 #include <map>
8 #include <memory>
9 #include <set>
10 #include <string>
11 #include <utility>
12 #include <vector>
13
14 #include "base/feature_list.h"
15 #include "base/functional/bind.h"
16 #include "base/metrics/field_trial.h"
17 #include "base/metrics/field_trial_params.h"
18 #include "base/run_loop.h"
19 #include "base/test/metrics/histogram_tester.h"
20 #include "base/test/scoped_feature_list.h"
21 #include "build/build_config.h"
22 #include "build/chromeos_buildflags.h"
23 #include "components/content_settings/core/browser/content_settings_uma_util.h"
24 #include "components/content_settings/core/browser/host_content_settings_map.h"
25 #include "components/content_settings/core/common/content_settings.h"
26 #include "components/content_settings/core/common/content_settings_types.h"
27 #include "components/permissions/features.h"
28 #include "components/permissions/permission_decision_auto_blocker.h"
29 #include "components/permissions/permission_request_id.h"
30 #include "components/permissions/permission_request_manager.h"
31 #include "components/permissions/permission_uma_util.h"
32 #include "components/permissions/permission_util.h"
33 #include "components/permissions/test/mock_permission_prompt_factory.h"
34 #include "components/permissions/test/test_permissions_client.h"
35 #include "components/ukm/content/source_url_recorder.h"
36 #include "components/ukm/test_ukm_recorder.h"
37 #include "content/public/browser/browser_thread.h"
38 #include "content/public/browser/navigation_entry.h"
39 #include "content/public/browser/permission_result.h"
40 #include "content/public/browser/render_frame_host.h"
41 #include "content/public/browser/web_contents.h"
42 #include "content/public/test/mock_render_process_host.h"
43 #include "content/public/test/test_renderer_host.h"
44 #include "testing/gtest/include/gtest/gtest.h"
45 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom.h"
46 #include "url/url_util.h"
47
48 namespace permissions {
49
50 using PermissionStatus = blink::mojom::PermissionStatus;
51
52 const char* const kPermissionsKillSwitchFieldStudy =
53     PermissionContextBase::kPermissionsKillSwitchFieldStudy;
54 const char* const kPermissionsKillSwitchBlockedValue =
55     PermissionContextBase::kPermissionsKillSwitchBlockedValue;
56 const char kPermissionsKillSwitchTestGroup[] = "TestGroup";
57
58 class TestPermissionContext : public PermissionContextBase {
59  public:
60   TestPermissionContext(content::BrowserContext* browser_context,
61                         const ContentSettingsType content_settings_type)
62       : PermissionContextBase(
63             browser_context,
64             content_settings_type,
65             blink::mojom::PermissionsPolicyFeature::kNotFound),
66         tab_context_updated_(false) {}
67
68   TestPermissionContext(const TestPermissionContext&) = delete;
69   TestPermissionContext& operator=(const TestPermissionContext&) = delete;
70
71   ~TestPermissionContext() override {}
72
73   const std::vector<ContentSetting>& decisions() const { return decisions_; }
74
75   bool tab_context_updated() const { return tab_context_updated_; }
76
77   // Once a decision for the requested permission has been made, run the
78   // callback.
79   void TrackPermissionDecision(ContentSetting content_setting) {
80     decisions_.push_back(content_setting);
81     // Null check required here as the quit_closure_ can also be run and reset
82     // first from within DecidePermission.
83     if (quit_closure_) {
84       std::move(quit_closure_).Run();
85     }
86   }
87
88   ContentSetting GetContentSettingFromMap(const GURL& url_a,
89                                           const GURL& url_b) {
90     auto* map = PermissionsClient::Get()->GetSettingsMap(browser_context());
91     return map->GetContentSetting(url_a.DeprecatedGetOriginAsURL(),
92                                   url_b.DeprecatedGetOriginAsURL(),
93                                   content_settings_type());
94   }
95
96   void RequestPermission(PermissionRequestData request_data,
97                          BrowserPermissionCallback callback) override {
98     base::RunLoop run_loop;
99     quit_closure_ = run_loop.QuitClosure();
100     PermissionContextBase::RequestPermission(std::move(request_data),
101                                              std::move(callback));
102     run_loop.Run();
103   }
104
105   void DecidePermission(PermissionRequestData request_data,
106                         BrowserPermissionCallback callback) override {
107     PermissionContextBase::DecidePermission(std::move(request_data),
108                                             std::move(callback));
109     if (respond_permission_) {
110       std::move(respond_permission_).Run();
111     } else {
112       // Stop the run loop from spinning indefinitely if no response callback
113       // has been set, as is the case with TestParallelRequests.
114       std::move(quit_closure_).Run();
115     }
116   }
117
118   // Set the callback to run if the permission is being responded to in the
119   // test. This is left empty where no response is needed, such as in parallel
120   // requests, invalid origin, and killswitch.
121   void SetRespondPermissionCallback(base::OnceClosure callback) {
122     respond_permission_ = std::move(callback);
123   }
124
125  protected:
126   void UpdateTabContext(const PermissionRequestID& id,
127                         const GURL& requesting_origin,
128                         bool allowed) override {
129     tab_context_updated_ = true;
130   }
131
132   bool IsRestrictedToSecureOrigins() const override { return false; }
133
134  private:
135   std::vector<ContentSetting> decisions_;
136   bool tab_context_updated_;
137   base::OnceClosure quit_closure_;
138   // Callback for responding to a permission once the request has been completed
139   // (valid URL, kill switch disabled)
140   base::OnceClosure respond_permission_;
141 };
142
143 class TestKillSwitchPermissionContext : public TestPermissionContext {
144  public:
145   TestKillSwitchPermissionContext(
146       content::BrowserContext* browser_context,
147       const ContentSettingsType content_settings_type)
148       : TestPermissionContext(browser_context, content_settings_type) {
149     ResetFieldTrialList();
150   }
151
152   TestKillSwitchPermissionContext(const TestKillSwitchPermissionContext&) =
153       delete;
154   TestKillSwitchPermissionContext& operator=(
155       const TestKillSwitchPermissionContext&) = delete;
156
157   void ResetFieldTrialList() {
158     scoped_feature_list_.Reset();
159     scoped_feature_list_.Init();
160   }
161
162  private:
163   base::test::ScopedFeatureList scoped_feature_list_;
164 };
165
166 class TestSecureOriginRestrictedPermissionContext
167     : public TestPermissionContext {
168  public:
169   TestSecureOriginRestrictedPermissionContext(
170       content::BrowserContext* browser_context,
171       const ContentSettingsType content_settings_type)
172       : TestPermissionContext(browser_context, content_settings_type) {}
173
174   TestSecureOriginRestrictedPermissionContext(
175       const TestSecureOriginRestrictedPermissionContext&) = delete;
176   TestSecureOriginRestrictedPermissionContext& operator=(
177       const TestSecureOriginRestrictedPermissionContext&) = delete;
178
179  protected:
180   bool IsRestrictedToSecureOrigins() const override { return true; }
181 };
182
183 class TestPermissionsClientBypassExtensionOriginCheck
184     : public TestPermissionsClient {
185  public:
186   bool CanBypassEmbeddingOriginCheck(const GURL& requesting_origin,
187                                      const GURL& embedding_origin) override {
188     return requesting_origin.SchemeIs("chrome-extension");
189   }
190 };
191
192 class PermissionContextBaseTests : public content::RenderViewHostTestHarness {
193  public:
194   PermissionContextBaseTests(const PermissionContextBaseTests&) = delete;
195   PermissionContextBaseTests& operator=(const PermissionContextBaseTests&) =
196       delete;
197
198  protected:
199   PermissionContextBaseTests() {}
200   ~PermissionContextBaseTests() override {}
201
202   // Accept or dismiss the permission prompt.
203   void RespondToPermission(TestPermissionContext* context,
204                            const PermissionRequestID& id,
205                            const GURL& url,
206                            ContentSetting response) {
207     DCHECK(response == CONTENT_SETTING_ALLOW ||
208            response == CONTENT_SETTING_BLOCK ||
209            response == CONTENT_SETTING_ASK);
210     using AutoResponseType = PermissionRequestManager::AutoResponseType;
211     AutoResponseType decision = AutoResponseType::DISMISS;
212     if (response == CONTENT_SETTING_ALLOW)
213       decision = AutoResponseType::ACCEPT_ALL;
214     else if (response == CONTENT_SETTING_BLOCK)
215       decision = AutoResponseType::DENY_ALL;
216     prompt_factory_->set_response_type(decision);
217   }
218
219   void TestAskAndDecide_TestContent(ContentSettingsType content_settings_type,
220                                     ContentSetting decision) {
221     ukm::InitializeSourceUrlRecorderForWebContents(web_contents());
222     ukm::TestAutoSetUkmRecorder ukm_recorder;
223     TestPermissionContext permission_context(browser_context(),
224                                              content_settings_type);
225     GURL url("https://www.google.com");
226     SetUpUrl(url);
227     base::HistogramTester histograms;
228
229     const PermissionRequestID id(
230         web_contents()->GetPrimaryMainFrame()->GetGlobalId(),
231         PermissionRequestID::RequestLocalId());
232     permission_context.SetRespondPermissionCallback(base::BindOnce(
233         &PermissionContextBaseTests::RespondToPermission,
234         base::Unretained(this), &permission_context, id, url, decision));
235     permission_context.RequestPermission(
236         PermissionRequestData(&permission_context, id,
237                               /*user_gesture=*/true, url),
238         base::BindOnce(&TestPermissionContext::TrackPermissionDecision,
239                        base::Unretained(&permission_context)));
240     ASSERT_EQ(1u, permission_context.decisions().size());
241     EXPECT_EQ(decision, permission_context.decisions()[0]);
242     EXPECT_TRUE(permission_context.tab_context_updated());
243
244     std::string decision_string;
245     absl::optional<PermissionAction> action;
246     if (decision == CONTENT_SETTING_ALLOW) {
247       decision_string = "Accepted";
248       action = PermissionAction::GRANTED;
249     } else if (decision == CONTENT_SETTING_BLOCK) {
250       decision_string = "Denied";
251       action = PermissionAction::DENIED;
252     } else if (decision == CONTENT_SETTING_ASK) {
253       decision_string = "Dismissed";
254       action = PermissionAction::DISMISSED;
255     }
256
257     if (!decision_string.empty()) {
258       histograms.ExpectUniqueSample(
259           "Permissions.Prompt." + decision_string + ".PriorDismissCount2." +
260               PermissionUtil::GetPermissionString(content_settings_type),
261           0, 1);
262       histograms.ExpectUniqueSample(
263           "Permissions.Prompt." + decision_string + ".PriorIgnoreCount2." +
264               PermissionUtil::GetPermissionString(content_settings_type),
265           0, 1);
266 #if BUILDFLAG(IS_ANDROID)
267       histograms.ExpectUniqueSample(
268           "Permissions.Action.WithDisposition.ModalDialog",
269           static_cast<int>(action.value()), 1);
270 #else
271       histograms.ExpectUniqueSample(
272           "Permissions.Action.WithDisposition.AnchoredBubble",
273           static_cast<int>(action.value()), 1);
274 #endif
275     }
276
277     EXPECT_EQ(decision, permission_context.GetContentSettingFromMap(url, url));
278
279     histograms.ExpectUniqueSample(
280         "Permissions.AutoBlocker.EmbargoPromptSuppression",
281         static_cast<int>(PermissionEmbargoStatus::NOT_EMBARGOED), 1);
282     histograms.ExpectUniqueSample(
283         "Permissions.AutoBlocker.EmbargoStatus",
284         static_cast<int>(PermissionEmbargoStatus::NOT_EMBARGOED), 1);
285
286     if (action.has_value()) {
287       auto entries = ukm_recorder.GetEntriesByName("Permission");
288       EXPECT_EQ(1u, entries.size());
289       auto* entry = entries.front();
290       ukm_recorder.ExpectEntrySourceHasUrl(entry, url);
291
292       EXPECT_NE(content_settings_uma_util::ContentSettingTypeToHistogramValue(
293                     content_settings_type),
294                 -1);
295
296       EXPECT_EQ(*ukm_recorder.GetEntryMetric(entry, "Source"),
297                 static_cast<int64_t>(PermissionSourceUI::PROMPT));
298       EXPECT_EQ(
299           *ukm_recorder.GetEntryMetric(entry, "PermissionType"),
300           static_cast<int64_t>(
301               content_settings_uma_util::ContentSettingTypeToHistogramValue(
302                   content_settings_type)));
303       EXPECT_EQ(*ukm_recorder.GetEntryMetric(entry, "Action"),
304                 static_cast<int64_t>(action.value()));
305
306 #if BUILDFLAG(IS_ANDROID)
307       EXPECT_EQ(
308           *ukm_recorder.GetEntryMetric(entry, "PromptDisposition"),
309           static_cast<int64_t>(PermissionPromptDisposition::MODAL_DIALOG));
310 #else
311       EXPECT_EQ(
312           *ukm_recorder.GetEntryMetric(entry, "PromptDisposition"),
313           static_cast<int64_t>(PermissionPromptDisposition::ANCHORED_BUBBLE));
314 #endif
315     }
316   }
317
318   void DismissMultipleTimesAndExpectBlock(
319       const GURL& url,
320       ContentSettingsType content_settings_type,
321       uint32_t iterations) {
322     base::HistogramTester histograms;
323
324     // Dismiss |iterations| times. The final dismiss should change the decision
325     // from dismiss to block, and hence change the persisted content setting.
326     for (uint32_t i = 0; i < iterations; ++i) {
327       TestPermissionContext permission_context(browser_context(),
328                                                content_settings_type);
329       const PermissionRequestID id(
330           web_contents()->GetPrimaryMainFrame()->GetGlobalId(),
331           PermissionRequestID::RequestLocalId());
332
333       permission_context.SetRespondPermissionCallback(
334           base::BindOnce(&PermissionContextBaseTests::RespondToPermission,
335                          base::Unretained(this), &permission_context, id, url,
336                          CONTENT_SETTING_ASK));
337
338       permission_context.RequestPermission(
339           PermissionRequestData(&permission_context, id,
340                                 /*user_gesture=*/true, url),
341           base::BindOnce(&TestPermissionContext::TrackPermissionDecision,
342                          base::Unretained(&permission_context)));
343       histograms.ExpectTotalCount(
344           "Permissions.Prompt.Dismissed.PriorDismissCount2." +
345               PermissionUtil::GetPermissionString(content_settings_type),
346           i + 1);
347       histograms.ExpectBucketCount(
348           "Permissions.Prompt.Dismissed.PriorDismissCount2." +
349               PermissionUtil::GetPermissionString(content_settings_type),
350           i, 1);
351
352       histograms.ExpectTotalCount("Permissions.AutoBlocker.EmbargoStatus",
353                                   i + 1);
354
355       content::PermissionResult result = permission_context.GetPermissionStatus(
356           nullptr /* render_frame_host */, url, url);
357
358       histograms.ExpectUniqueSample(
359           "Permissions.AutoBlocker.EmbargoPromptSuppression",
360           static_cast<int>(PermissionEmbargoStatus::NOT_EMBARGOED), i + 1);
361       if (i < 2) {
362         EXPECT_EQ(content::PermissionStatusSource::UNSPECIFIED, result.source);
363         EXPECT_EQ(PermissionStatus::ASK, result.status);
364         histograms.ExpectUniqueSample(
365             "Permissions.AutoBlocker.EmbargoStatus",
366             static_cast<int>(PermissionEmbargoStatus::NOT_EMBARGOED), i + 1);
367       } else {
368         EXPECT_EQ(content::PermissionStatusSource::MULTIPLE_DISMISSALS,
369                   result.source);
370         EXPECT_EQ(PermissionStatus::DENIED, result.status);
371         histograms.ExpectBucketCount(
372             "Permissions.AutoBlocker.EmbargoStatus",
373             static_cast<int>(PermissionEmbargoStatus::REPEATED_DISMISSALS), 1);
374       }
375
376       ASSERT_EQ(1u, permission_context.decisions().size());
377       EXPECT_EQ(CONTENT_SETTING_ASK, permission_context.decisions()[0]);
378       EXPECT_TRUE(permission_context.tab_context_updated());
379     }
380
381     TestPermissionContext permission_context(browser_context(),
382                                              content_settings_type);
383     const PermissionRequestID id(
384         web_contents()->GetPrimaryMainFrame()->GetGlobalId(),
385         PermissionRequestID::RequestLocalId());
386
387     permission_context.SetRespondPermissionCallback(
388         base::BindOnce(&PermissionContextBaseTests::RespondToPermission,
389                        base::Unretained(this), &permission_context, id, url,
390                        CONTENT_SETTING_ASK));
391
392     permission_context.RequestPermission(
393         PermissionRequestData(&permission_context, id,
394                               /*user_gesture=*/true, url),
395         base::BindOnce(&TestPermissionContext::TrackPermissionDecision,
396                        base::Unretained(&permission_context)));
397
398     content::PermissionResult result = permission_context.GetPermissionStatus(
399         nullptr /* render_frame_host */, url, url);
400     EXPECT_EQ(PermissionStatus::DENIED, result.status);
401     EXPECT_EQ(content::PermissionStatusSource::MULTIPLE_DISMISSALS,
402               result.source);
403     histograms.ExpectBucketCount(
404         "Permissions.AutoBlocker.EmbargoPromptSuppression",
405         static_cast<int>(PermissionEmbargoStatus::REPEATED_DISMISSALS), 1);
406   }
407
408   void TestBlockOnSeveralDismissals_TestContent() {
409     GURL url("https://www.google.com");
410     SetUpUrl(url);
411     base::HistogramTester histograms;
412
413     {
414       // Ensure that > 3 dismissals behaves correctly when the
415       // BlockPromptsIfDismissedOften feature is off.
416       base::test::ScopedFeatureList feature_list;
417       feature_list.InitAndDisableFeature(
418           features::kBlockPromptsIfDismissedOften);
419
420       for (uint32_t i = 0; i < 4; ++i) {
421         TestPermissionContext permission_context(
422             browser_context(), ContentSettingsType::GEOLOCATION);
423
424         const PermissionRequestID id(
425             web_contents()->GetPrimaryMainFrame()->GetGlobalId(),
426             PermissionRequestID::RequestLocalId(i + 1));
427
428         permission_context.SetRespondPermissionCallback(
429             base::BindOnce(&PermissionContextBaseTests::RespondToPermission,
430                            base::Unretained(this), &permission_context, id, url,
431                            CONTENT_SETTING_ASK));
432         permission_context.RequestPermission(
433             PermissionRequestData(&permission_context, id,
434                                   /*user_gesture=*/true, url),
435             base::BindOnce(&TestPermissionContext::TrackPermissionDecision,
436                            base::Unretained(&permission_context)));
437         histograms.ExpectTotalCount(
438             "Permissions.Prompt.Dismissed.PriorDismissCount2.Geolocation",
439             i + 1);
440         histograms.ExpectBucketCount(
441             "Permissions.Prompt.Dismissed.PriorDismissCount2.Geolocation", i,
442             1);
443         histograms.ExpectUniqueSample(
444             "Permissions.AutoBlocker.EmbargoPromptSuppression",
445             static_cast<int>(PermissionEmbargoStatus::NOT_EMBARGOED), i + 1);
446         histograms.ExpectUniqueSample(
447             "Permissions.AutoBlocker.EmbargoStatus",
448             static_cast<int>(PermissionEmbargoStatus::NOT_EMBARGOED), i + 1);
449
450         ASSERT_EQ(1u, permission_context.decisions().size());
451         EXPECT_EQ(CONTENT_SETTING_ASK, permission_context.decisions()[0]);
452         EXPECT_TRUE(permission_context.tab_context_updated());
453         EXPECT_EQ(CONTENT_SETTING_ASK,
454                   permission_context.GetContentSettingFromMap(url, url));
455       }
456
457       // Flush the dismissal counts.
458       auto* map = PermissionsClient::Get()->GetSettingsMap(browser_context());
459       map->ClearSettingsForOneType(
460           ContentSettingsType::PERMISSION_AUTOBLOCKER_DATA);
461     }
462
463     EXPECT_TRUE(
464         base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften));
465
466     // Sanity check independence per permission type by checking two of them.
467     DismissMultipleTimesAndExpectBlock(url, ContentSettingsType::GEOLOCATION,
468                                        3);
469     DismissMultipleTimesAndExpectBlock(url, ContentSettingsType::NOTIFICATIONS,
470                                        3);
471   }
472
473   void TestVariationBlockOnSeveralDismissals_TestContent() {
474     GURL url("https://www.google.com");
475     SetUpUrl(url);
476     base::HistogramTester histograms;
477
478     std::map<std::string, std::string> params;
479     params
480         [PermissionDecisionAutoBlocker::GetPromptDismissCountKeyForTesting()] =
481             "5";
482     base::test::ScopedFeatureList scoped_feature_list;
483     scoped_feature_list.InitAndEnableFeatureWithParameters(
484         features::kBlockPromptsIfDismissedOften, params);
485
486     std::map<std::string, std::string> actual_params;
487     EXPECT_TRUE(base::GetFieldTrialParamsByFeature(
488         features::kBlockPromptsIfDismissedOften, &actual_params));
489     EXPECT_EQ(params, actual_params);
490
491     EXPECT_TRUE(base::GetFieldTrialParamsByFeature(
492         features::kBlockPromptsIfDismissedOften, &actual_params));
493     EXPECT_EQ(params, actual_params);
494
495     for (uint32_t i = 0; i < 5; ++i) {
496       TestPermissionContext permission_context(browser_context(),
497                                                ContentSettingsType::MIDI_SYSEX);
498
499       const PermissionRequestID id(
500           web_contents()->GetPrimaryMainFrame()->GetGlobalId(),
501           PermissionRequestID::RequestLocalId(i + 1));
502       permission_context.SetRespondPermissionCallback(
503           base::BindOnce(&PermissionContextBaseTests::RespondToPermission,
504                          base::Unretained(this), &permission_context, id, url,
505                          CONTENT_SETTING_ASK));
506       permission_context.RequestPermission(
507           PermissionRequestData(&permission_context, id,
508                                 /*user_gesture=*/true, url),
509           base::BindOnce(&TestPermissionContext::TrackPermissionDecision,
510                          base::Unretained(&permission_context)));
511
512       EXPECT_EQ(1u, permission_context.decisions().size());
513       ASSERT_EQ(CONTENT_SETTING_ASK, permission_context.decisions()[0]);
514       EXPECT_TRUE(permission_context.tab_context_updated());
515       content::PermissionResult result = permission_context.GetPermissionStatus(
516           nullptr /* render_frame_host */, url, url);
517
518       histograms.ExpectTotalCount(
519           "Permissions.Prompt.Dismissed.PriorDismissCount2.MidiSysEx", i + 1);
520       histograms.ExpectBucketCount(
521           "Permissions.Prompt.Dismissed.PriorDismissCount2.MidiSysEx", i, 1);
522       histograms.ExpectUniqueSample(
523           "Permissions.AutoBlocker.EmbargoPromptSuppression",
524           static_cast<int>(PermissionEmbargoStatus::NOT_EMBARGOED), i + 1);
525       histograms.ExpectTotalCount("Permissions.AutoBlocker.EmbargoStatus",
526                                   i + 1);
527       if (i < 4) {
528         EXPECT_EQ(PermissionStatus::ASK, result.status);
529         EXPECT_EQ(content::PermissionStatusSource::UNSPECIFIED, result.source);
530         histograms.ExpectUniqueSample(
531             "Permissions.AutoBlocker.EmbargoStatus",
532             static_cast<int>(PermissionEmbargoStatus::NOT_EMBARGOED), i + 1);
533       } else {
534         EXPECT_EQ(PermissionStatus::DENIED, result.status);
535         EXPECT_EQ(content::PermissionStatusSource::MULTIPLE_DISMISSALS,
536                   result.source);
537         histograms.ExpectBucketCount(
538             "Permissions.AutoBlocker.EmbargoStatus",
539             static_cast<int>(PermissionEmbargoStatus::REPEATED_DISMISSALS), 1);
540       }
541     }
542
543     // Ensure that we finish in the block state.
544     TestPermissionContext permission_context(browser_context(),
545                                              ContentSettingsType::MIDI_SYSEX);
546     content::PermissionResult result = permission_context.GetPermissionStatus(
547         nullptr /* render_frame_host */, url, url);
548     EXPECT_EQ(PermissionStatus::DENIED, result.status);
549     EXPECT_EQ(content::PermissionStatusSource::MULTIPLE_DISMISSALS,
550               result.source);
551   }
552
553   void TestRequestPermissionInvalidUrl(
554       ContentSettingsType content_settings_type) {
555     base::HistogramTester histograms;
556     TestPermissionContext permission_context(browser_context(),
557                                              content_settings_type);
558     GURL url;
559     ASSERT_FALSE(url.is_valid());
560     controller().LoadURL(url, content::Referrer(), ui::PAGE_TRANSITION_TYPED,
561                          std::string());
562
563     const PermissionRequestID id(
564         web_contents()->GetPrimaryMainFrame()->GetGlobalId(),
565         PermissionRequestID::RequestLocalId());
566     permission_context.RequestPermission(
567         PermissionRequestData(&permission_context, id,
568                               /*user_gesture=*/true, url),
569         base::BindOnce(&TestPermissionContext::TrackPermissionDecision,
570                        base::Unretained(&permission_context)));
571
572     ASSERT_EQ(1u, permission_context.decisions().size());
573     EXPECT_EQ(CONTENT_SETTING_BLOCK, permission_context.decisions()[0]);
574     EXPECT_TRUE(permission_context.tab_context_updated());
575     EXPECT_EQ(CONTENT_SETTING_ASK,
576               permission_context.GetContentSettingFromMap(url, url));
577     histograms.ExpectTotalCount(
578         "Permissions.AutoBlocker.EmbargoPromptSuppression", 0);
579   }
580
581   void TestGrantAndRevoke_TestContent(ContentSettingsType content_settings_type,
582                                       ContentSetting expected_default) {
583     TestPermissionContext permission_context(browser_context(),
584                                              content_settings_type);
585     GURL url("https://www.google.com");
586     SetUpUrl(url);
587
588     const PermissionRequestID id(
589         web_contents()->GetPrimaryMainFrame()->GetGlobalId(),
590         PermissionRequestID::RequestLocalId());
591     permission_context.SetRespondPermissionCallback(
592         base::BindOnce(&PermissionContextBaseTests::RespondToPermission,
593                        base::Unretained(this), &permission_context, id, url,
594                        CONTENT_SETTING_ALLOW));
595
596     permission_context.RequestPermission(
597         PermissionRequestData(&permission_context, id,
598                               /*user_gesture=*/true, url),
599         base::BindOnce(&TestPermissionContext::TrackPermissionDecision,
600                        base::Unretained(&permission_context)));
601
602     ASSERT_EQ(1u, permission_context.decisions().size());
603     EXPECT_EQ(CONTENT_SETTING_ALLOW, permission_context.decisions()[0]);
604     EXPECT_TRUE(permission_context.tab_context_updated());
605     EXPECT_EQ(CONTENT_SETTING_ALLOW,
606               permission_context.GetContentSettingFromMap(url, url));
607
608     // Try to reset permission.
609     permission_context.ResetPermission(url.DeprecatedGetOriginAsURL(),
610                                        url.DeprecatedGetOriginAsURL());
611     ContentSetting setting_after_reset =
612         permission_context.GetContentSettingFromMap(url, url);
613     ContentSetting default_setting =
614         PermissionsClient::Get()
615             ->GetSettingsMap(browser_context())
616             ->GetDefaultContentSetting(content_settings_type, nullptr);
617     EXPECT_EQ(default_setting, setting_after_reset);
618   }
619
620   void TestGlobalPermissionsKillSwitch(
621       ContentSettingsType content_settings_type) {
622     TestKillSwitchPermissionContext permission_context(browser_context(),
623                                                        content_settings_type);
624     permission_context.ResetFieldTrialList();
625
626     EXPECT_FALSE(permission_context.IsPermissionKillSwitchOn());
627     std::map<std::string, std::string> params;
628     params[PermissionUtil::GetPermissionString(content_settings_type)] =
629         kPermissionsKillSwitchBlockedValue;
630     base::AssociateFieldTrialParams(kPermissionsKillSwitchFieldStudy,
631                                     kPermissionsKillSwitchTestGroup, params);
632     base::FieldTrialList::CreateFieldTrial(kPermissionsKillSwitchFieldStudy,
633                                            kPermissionsKillSwitchTestGroup);
634     EXPECT_TRUE(permission_context.IsPermissionKillSwitchOn());
635   }
636
637   void TestSecureOriginRestrictedPermissionContextCheck(
638       const std::string& requesting_url_spec,
639       const std::string& embedding_url_spec,
640       bool expect_allowed) {
641     GURL requesting_origin(requesting_url_spec);
642     GURL embedding_origin(embedding_url_spec);
643     TestSecureOriginRestrictedPermissionContext permission_context(
644         browser_context(), ContentSettingsType::GEOLOCATION);
645     bool result = permission_context.IsPermissionAvailableToOrigins(
646         requesting_origin, embedding_origin);
647     EXPECT_EQ(expect_allowed, result)
648         << "test case (requesting, embedding): (" << requesting_url_spec << ", "
649         << embedding_url_spec << ") with secure-origin requirement"
650         << " on";
651
652     // With no secure-origin limitation, this check should always return pass.
653     TestPermissionContext new_context(browser_context(),
654                                       ContentSettingsType::GEOLOCATION);
655     result = new_context.IsPermissionAvailableToOrigins(requesting_origin,
656                                                         embedding_origin);
657     EXPECT_EQ(true, result)
658         << "test case (requesting, embedding): (" << requesting_url_spec << ", "
659         << embedding_url_spec << ") with secure-origin requirement"
660         << " off";
661   }
662
663   // Don't call this more than once in the same test, as it persists data to
664   // HostContentSettingsMap.
665   void TestParallelRequests(ContentSetting response) {
666     TestPermissionContext permission_context(browser_context(),
667                                              ContentSettingsType::GEOLOCATION);
668     GURL url("http://www.google.com");
669     SetUpUrl(url);
670
671     const PermissionRequestID id1(
672         web_contents()->GetPrimaryMainFrame()->GetGlobalId(),
673         PermissionRequestID::RequestLocalId(1));
674     const PermissionRequestID id2(
675         web_contents()->GetPrimaryMainFrame()->GetGlobalId(),
676         PermissionRequestID::RequestLocalId(2));
677
678     // Request a permission without setting the callback to DecidePermission.
679     permission_context.RequestPermission(
680         PermissionRequestData(&permission_context, id1,
681                               /*user_gesture=*/true, url),
682         base::BindOnce(&TestPermissionContext::TrackPermissionDecision,
683                        base::Unretained(&permission_context)));
684
685     EXPECT_EQ(0u, permission_context.decisions().size());
686
687     // Set the callback, and make a second permission request.
688     permission_context.SetRespondPermissionCallback(base::BindOnce(
689         &PermissionContextBaseTests::RespondToPermission,
690         base::Unretained(this), &permission_context, id1, url, response));
691     permission_context.RequestPermission(
692         PermissionRequestData(&permission_context, id2,
693                               /*user_gesture=*/true, url),
694         base::BindOnce(&TestPermissionContext::TrackPermissionDecision,
695                        base::Unretained(&permission_context)));
696
697     ASSERT_EQ(2u, permission_context.decisions().size());
698     EXPECT_EQ(response, permission_context.decisions()[0]);
699     EXPECT_EQ(response, permission_context.decisions()[1]);
700     EXPECT_TRUE(permission_context.tab_context_updated());
701
702     EXPECT_EQ(response, permission_context.GetContentSettingFromMap(url, url));
703   }
704
705   void TestVirtualURL(const GURL& loaded_url,
706                       const GURL& virtual_url,
707                       const ContentSetting want_response,
708                       const content::PermissionStatusSource& want_source) {
709     TestPermissionContext permission_context(browser_context(),
710                                              ContentSettingsType::GEOLOCATION);
711
712     NavigateAndCommit(loaded_url);
713     web_contents()->GetController().GetVisibleEntry()->SetVirtualURL(
714         virtual_url);
715
716     content::PermissionResult result = permission_context.GetPermissionStatus(
717         web_contents()->GetPrimaryMainFrame(), virtual_url, virtual_url);
718     EXPECT_EQ(result.status,
719               PermissionUtil::ContentSettingToPermissionStatus(want_response));
720     EXPECT_EQ(result.source, want_source);
721   }
722
723   void SetUpUrl(const GURL& url) {
724     NavigateAndCommit(url);
725     prompt_factory_->DocumentOnLoadCompletedInPrimaryMainFrame();
726   }
727
728  private:
729   // content::RenderViewHostTestHarness:
730   void SetUp() override {
731     content::RenderViewHostTestHarness::SetUp();
732     PermissionRequestManager::CreateForWebContents(web_contents());
733     PermissionRequestManager* manager =
734         PermissionRequestManager::FromWebContents(web_contents());
735     manager->set_enabled_app_level_notification_permission_for_testing(true);
736     prompt_factory_ = std::make_unique<MockPermissionPromptFactory>(manager);
737   }
738
739   void TearDown() override {
740     prompt_factory_.reset();
741     content::RenderViewHostTestHarness::TearDown();
742   }
743
744   std::unique_ptr<MockPermissionPromptFactory> prompt_factory_;
745   TestPermissionsClientBypassExtensionOriginCheck client_;
746 };
747
748 // Simulates clicking Accept. The permission should be granted and
749 // saved for future use.
750 TEST_F(PermissionContextBaseTests, TestAskAndGrant) {
751   TestAskAndDecide_TestContent(ContentSettingsType::NOTIFICATIONS,
752                                CONTENT_SETTING_ALLOW);
753 }
754
755 // Simulates clicking Block. The permission should be denied and
756 // saved for future use.
757 TEST_F(PermissionContextBaseTests, TestAskAndBlock) {
758   TestAskAndDecide_TestContent(ContentSettingsType::GEOLOCATION,
759                                CONTENT_SETTING_BLOCK);
760 }
761
762 // Simulates clicking Dismiss (X) in the prompt.
763 // The permission should be denied but not saved for future use.
764 TEST_F(PermissionContextBaseTests, TestAskAndDismiss) {
765   TestAskAndDecide_TestContent(ContentSettingsType::MIDI_SYSEX,
766                                CONTENT_SETTING_ASK);
767 }
768
769 // Simulates clicking Dismiss (X) in the prompt with the block on too
770 // many dismissals feature active. The permission should be blocked after
771 // several dismissals.
772 TEST_F(PermissionContextBaseTests, TestDismissUntilBlocked) {
773   TestBlockOnSeveralDismissals_TestContent();
774 }
775
776 // Test setting a custom number of dismissals before block via variations.
777 TEST_F(PermissionContextBaseTests, TestDismissVariations) {
778   TestVariationBlockOnSeveralDismissals_TestContent();
779 }
780
781 // Simulates non-valid requesting URL.
782 // The permission should be denied but not saved for future use.
783 TEST_F(PermissionContextBaseTests, TestNonValidRequestingUrl) {
784   TestRequestPermissionInvalidUrl(ContentSettingsType::GEOLOCATION);
785   TestRequestPermissionInvalidUrl(ContentSettingsType::NOTIFICATIONS);
786   TestRequestPermissionInvalidUrl(ContentSettingsType::MIDI_SYSEX);
787 }
788
789 // Simulates granting and revoking of permissions.
790 TEST_F(PermissionContextBaseTests, TestGrantAndRevoke) {
791   TestGrantAndRevoke_TestContent(ContentSettingsType::GEOLOCATION,
792                                  CONTENT_SETTING_ASK);
793   TestGrantAndRevoke_TestContent(ContentSettingsType::MIDI_SYSEX,
794                                  CONTENT_SETTING_ASK);
795 #if BUILDFLAG(IS_ANDROID)
796   TestGrantAndRevoke_TestContent(
797       ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER, CONTENT_SETTING_ASK);
798   // TODO(timvolodine): currently no test for
799   // ContentSettingsType::NOTIFICATIONS because notification permissions work
800   // differently with infobars as compared to bubbles (crbug.com/453784).
801 #else
802   TestGrantAndRevoke_TestContent(ContentSettingsType::NOTIFICATIONS,
803                                  CONTENT_SETTING_ASK);
804 #endif
805 }
806
807 // Tests the global kill switch by enabling/disabling the Field Trials.
808 TEST_F(PermissionContextBaseTests, TestGlobalKillSwitch) {
809   TestGlobalPermissionsKillSwitch(ContentSettingsType::GEOLOCATION);
810   TestGlobalPermissionsKillSwitch(ContentSettingsType::NOTIFICATIONS);
811   TestGlobalPermissionsKillSwitch(ContentSettingsType::MIDI_SYSEX);
812   TestGlobalPermissionsKillSwitch(ContentSettingsType::DURABLE_STORAGE);
813 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
814   TestGlobalPermissionsKillSwitch(
815       ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER);
816 #endif
817   TestGlobalPermissionsKillSwitch(ContentSettingsType::MEDIASTREAM_MIC);
818   TestGlobalPermissionsKillSwitch(ContentSettingsType::MEDIASTREAM_CAMERA);
819 }
820
821 // Tests that secure origins are examined if switch is on, or ignored if off.
822 TEST_F(PermissionContextBaseTests,
823        TestSecureOriginRestrictedPermissionContextSwitch) {
824   url::ScopedSchemeRegistryForTests scoped_registry;
825   url::AddSecureScheme("chrome-extension");
826   struct {
827     std::string requesting_url_spec;
828     std::string embedding_url_spec;
829     bool expect_permission_allowed;
830   } kTestCases[] = {
831       // Secure-origins that should be allowed.
832       {"https://google.com", "https://foo.com",
833        /*expect_allowed=*/true},
834       {"https://www.bar.com", "https://foo.com",
835        /*expect_allowed=*/true},
836       {"https://localhost", "http://localhost",
837        /*expect_allowed=*/true},
838
839       {"http://localhost", "https://google.com",
840        /*expect_allowed=*/true},
841       {"https://google.com", "http://localhost",
842        /*expect_allowed=*/true},
843       {"https://foo.com", "file://some-file",
844        /*expect_allowed=*/true},
845       {"file://some-file", "https://foo.com",
846        /*expect_allowed=*/true},
847       {"https://foo.com", "about:blank",
848        /*expect_allowed=*/true},
849       {"about:blank", "https://foo.com",
850        /*expect_allowed=*/true},
851
852       // Extensions are exempt from checking the embedder chain.
853       {"chrome-extension://some-extension", "http://not-secure.com",
854        /*expect_allowed=*/true},
855
856       // Insecure-origins that should be blocked.
857       {"http://foo.com", "file://some-file",
858        /*expect_allowed=*/false},
859       {"fake://foo.com", "about:blank",
860        /*expect_allowed=*/false},
861       {"http://localhost", "http://foo.com",
862        /*expect_allowed=*/false},
863       {"http://localhost", "foo.com",
864        /*expect_allowed=*/false},
865       {"http://bar.com", "https://foo.com",
866        /*expect_permission_allowed=*/false},
867       {"https://foo.com", "http://bar.com",
868        /*expect_permission_allowed=*/false},
869       {"http://localhost", "http://foo.com",
870        /*expect_permission_allowed=*/false},
871       {"http://foo.com", "http://localhost",
872        /*expect_permission_allowed=*/false},
873       {"bar.com", "https://foo.com", /*expect_permission_allowed=*/false},
874       {"https://foo.com", "bar.com", /*expect_permission_allowed=*/false}};
875   for (const auto& test_case : kTestCases) {
876     TestSecureOriginRestrictedPermissionContextCheck(
877         test_case.requesting_url_spec, test_case.embedding_url_spec,
878         test_case.expect_permission_allowed);
879   }
880 }
881
882 TEST_F(PermissionContextBaseTests, TestParallelRequestsAllowed) {
883   TestParallelRequests(CONTENT_SETTING_ALLOW);
884 }
885
886 TEST_F(PermissionContextBaseTests, TestParallelRequestsBlocked) {
887   TestParallelRequests(CONTENT_SETTING_BLOCK);
888 }
889
890 TEST_F(PermissionContextBaseTests, TestParallelRequestsDismissed) {
891   TestParallelRequests(CONTENT_SETTING_ASK);
892 }
893
894 TEST_F(PermissionContextBaseTests, TestVirtualURLDifferentOrigin) {
895   TestVirtualURL(GURL("http://www.google.com"), GURL("http://foo.com"),
896                  CONTENT_SETTING_BLOCK,
897                  content::PermissionStatusSource::VIRTUAL_URL_DIFFERENT_ORIGIN);
898 }
899
900 TEST_F(PermissionContextBaseTests, TestVirtualURLNotHTTP) {
901   TestVirtualURL(GURL("chrome://foo"), GURL("chrome://newtab"),
902                  CONTENT_SETTING_ASK,
903                  content::PermissionStatusSource::UNSPECIFIED);
904 }
905
906 TEST_F(PermissionContextBaseTests, TestVirtualURLSameOrigin) {
907   TestVirtualURL(GURL("http://www.google.com"),
908                  GURL("http://www.google.com/foo"), CONTENT_SETTING_ASK,
909                  content::PermissionStatusSource::UNSPECIFIED);
910 }
911
912 #if !BUILDFLAG(IS_ANDROID)
913 TEST_F(PermissionContextBaseTests, ExpirationAllow) {
914   base::test::ScopedFeatureList scoped_feature_list;
915   scoped_feature_list.InitWithFeatures(
916       {features::kRecordPermissionExpirationTimestamps}, {});
917
918   base::Time now = base::Time::Now();
919   TestAskAndDecide_TestContent(ContentSettingsType::GEOLOCATION,
920                                CONTENT_SETTING_ALLOW);
921
922   GURL primary_url("https://www.google.com");
923   GURL secondary_url;
924   auto* hcsm = PermissionsClient::Get()->GetSettingsMap(browser_context());
925   content_settings::SettingInfo info;
926   hcsm->GetWebsiteSetting(primary_url, secondary_url,
927                           ContentSettingsType::GEOLOCATION, &info);
928
929   // The last_visited should lie between today and a week ago.
930   EXPECT_GE(info.metadata.last_visited(), now - base::Days(7));
931   EXPECT_LE(info.metadata.last_visited(), now);
932 }
933
934 TEST_F(PermissionContextBaseTests, ExpirationBlock) {
935   base::test::ScopedFeatureList scoped_feature_list;
936   scoped_feature_list.InitWithFeatures(
937       {features::kRecordPermissionExpirationTimestamps}, {});
938
939   TestAskAndDecide_TestContent(ContentSettingsType::GEOLOCATION,
940                                CONTENT_SETTING_BLOCK);
941
942   GURL primary_url("https://www.google.com");
943   GURL secondary_url;
944   auto* hcsm = PermissionsClient::Get()->GetSettingsMap(browser_context());
945   content_settings::SettingInfo info;
946   hcsm->GetWebsiteSetting(primary_url, secondary_url,
947                           ContentSettingsType::GEOLOCATION, &info);
948
949   // last_visited is not set for BLOCKed permissions.
950   EXPECT_EQ(base::Time(), info.metadata.last_visited());
951 }
952 #endif  // !BUILDFLAG(IS_ANDROID)
953
954 }  // namespace permissions