Fix emulator build error
[platform/framework/web/chromium-efl.git] / components / permissions / permission_manager_unittest.cc
1 // Copyright 2015 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_manager.h"
6
7 #include <memory>
8
9 #include "base/functional/bind.h"
10 #include "base/memory/raw_ptr.h"
11 #include "base/metrics/field_trial.h"
12 #include "base/metrics/field_trial_params.h"
13 #include "build/build_config.h"
14 #include "build/chromeos_buildflags.h"
15 #include "components/content_settings/core/browser/host_content_settings_map.h"
16 #include "components/permissions/features.h"
17 #include "components/permissions/permission_context_base.h"
18 #include "components/permissions/permission_request_manager.h"
19 #include "components/permissions/permission_util.h"
20 #include "components/permissions/test/mock_permission_prompt_factory.h"
21 #include "components/permissions/test/permission_test_util.h"
22 #include "components/permissions/test/test_permissions_client.h"
23 #include "content/public/browser/content_browser_client.h"
24 #include "content/public/browser/permission_request_description.h"
25 #include "content/public/browser/permission_result.h"
26 #include "content/public/common/content_client.h"
27 #include "content/public/test/browser_task_environment.h"
28 #include "content/public/test/mock_render_process_host.h"
29 #include "content/public/test/navigation_simulator.h"
30 #include "content/public/test/test_browser_context.h"
31 #include "content/public/test/test_renderer_host.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33 #include "third_party/blink/public/common/permissions/permission_utils.h"
34 #include "third_party/blink/public/common/permissions_policy/origin_with_possible_wildcards.h"
35 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom.h"
36 #include "url/origin.h"
37
38 using blink::PermissionType;
39 using blink::mojom::PermissionsPolicyFeature;
40
41 namespace permissions {
42 namespace {
43
44 class ScopedPartitionedOriginBrowserClient
45     : public content::ContentBrowserClient {
46  public:
47   explicit ScopedPartitionedOriginBrowserClient(const GURL& app_origin)
48       : app_origin_(url::Origin::Create(app_origin)) {
49     old_client_ = content::SetBrowserClientForTesting(this);
50   }
51
52   ~ScopedPartitionedOriginBrowserClient() override {
53     content::SetBrowserClientForTesting(old_client_);
54   }
55
56   content::StoragePartitionConfig GetStoragePartitionConfigForSite(
57       content::BrowserContext* browser_context,
58       const GURL& site) override {
59     if (url::Origin::Create(site) == app_origin_) {
60       return content::StoragePartitionConfig::Create(
61           browser_context, "test_partition", /*partition_name=*/std::string(),
62           /*in_memory=*/false);
63     }
64     return content::StoragePartitionConfig::CreateDefault(browser_context);
65   }
66
67  private:
68   url::Origin app_origin_;
69   raw_ptr<content::ContentBrowserClient> old_client_;
70 };
71
72 }  // namespace
73
74 class PermissionManagerTest : public content::RenderViewHostTestHarness {
75  public:
76   void OnPermissionChange(PermissionStatus permission) {
77     if (!quit_closure_.is_null())
78       std::move(quit_closure_).Run();
79     callback_called_ = true;
80     callback_count_++;
81     callback_result_ = permission;
82   }
83
84  protected:
85   PermissionManagerTest()
86       : url_("https://example.com"), other_url_("https://foo.com") {}
87
88   PermissionManager* GetPermissionManager() {
89     return static_cast<PermissionManager*>(
90         browser_context_->GetPermissionControllerDelegate());
91   }
92
93   HostContentSettingsMap* GetHostContentSettingsMap() {
94     return PermissionsClient::Get()->GetSettingsMap(browser_context_.get());
95   }
96
97   void CheckPermissionStatus(PermissionType type, PermissionStatus expected) {
98     EXPECT_EQ(expected, GetPermissionManager()
99                             ->GetPermissionResultForOriginWithoutContext(
100                                 type, url::Origin::Create(url_),
101                                 url::Origin::Create(url_))
102                             .status);
103   }
104
105   void CheckPermissionResult(
106       PermissionType type,
107       PermissionStatus expected_status,
108       content::PermissionStatusSource expected_status_source) {
109     content::PermissionResult result =
110         GetPermissionManager()->GetPermissionResultForOriginWithoutContext(
111             type, url::Origin::Create(url_), url::Origin::Create(url_));
112     EXPECT_EQ(expected_status, result.status);
113     EXPECT_EQ(expected_status_source, result.source);
114   }
115
116   void SetPermission(PermissionType type, PermissionStatus value) {
117     SetPermission(url_, url_, type, value);
118   }
119
120   void SetPermission(const GURL& origin,
121                      PermissionType type,
122                      PermissionStatus value) {
123     SetPermission(origin, origin, type, value);
124   }
125
126   void SetPermission(const GURL& requesting_origin,
127                      const GURL& embedding_origin,
128                      PermissionType type,
129                      PermissionStatus value) {
130     GetHostContentSettingsMap()->SetContentSettingDefaultScope(
131         requesting_origin, embedding_origin,
132         permissions::PermissionUtil::PermissionTypeToContentSettingType(type),
133         permissions::PermissionUtil::PermissionStatusToContentSetting(value));
134   }
135
136   void RequestPermissionFromCurrentDocument(PermissionType type,
137                                             content::RenderFrameHost* rfh) {
138     base::RunLoop loop;
139     quit_closure_ = loop.QuitClosure();
140     GetPermissionManager()->RequestPermissionsFromCurrentDocument(
141         rfh,
142         std::move(content::PermissionRequestDescription(
143             std::vector(1, type),
144             /*user_gesture=*/true, rfh->GetLastCommittedOrigin().GetURL())),
145         base::BindOnce(
146             [](base::OnceCallback<void(PermissionStatus)> callback,
147                const std::vector<PermissionStatus>& state) {
148               DCHECK_EQ(state.size(), 1U);
149               std::move(callback).Run(state[0]);
150             },
151             base::BindOnce(&PermissionManagerTest::OnPermissionChange,
152                            base::Unretained(this))));
153     loop.Run();
154   }
155
156   void RequestPermissionFromCurrentDocumentNonBlocking(
157       PermissionType type,
158       content::RenderFrameHost* rfh) {
159     GetPermissionManager()->RequestPermissionsFromCurrentDocument(
160         rfh,
161         content::PermissionRequestDescription(
162             type, /*user_gesture=*/true,
163             rfh->GetLastCommittedOrigin().GetURL()),
164         base::BindOnce(
165             [](base::OnceCallback<void(PermissionStatus)> callback,
166                const std::vector<PermissionStatus>& state) {
167               DCHECK_EQ(state.size(), 1U);
168               std::move(callback).Run(state[0]);
169             },
170             base::BindOnce(&PermissionManagerTest::OnPermissionChange,
171                            base::Unretained(this))));
172   }
173
174   PermissionStatus GetPermissionStatusForCurrentDocument(
175       PermissionType permission,
176       content::RenderFrameHost* render_frame_host) {
177     return GetPermissionManager()->GetPermissionStatusForCurrentDocument(
178         permission, render_frame_host);
179   }
180
181   content::PermissionResult GetPermissionResultForCurrentDocument(
182       PermissionType permission,
183       content::RenderFrameHost* render_frame_host) {
184     return GetPermissionManager()->GetPermissionResultForCurrentDocument(
185         permission, render_frame_host);
186   }
187
188   PermissionStatus GetPermissionStatusForWorker(
189       PermissionType permission,
190       content::RenderProcessHost* render_process_host,
191       const GURL& worker_origin) {
192     return GetPermissionManager()->GetPermissionStatusForWorker(
193         permission, render_process_host, worker_origin);
194   }
195
196   content::PermissionControllerDelegate::SubscriptionId
197   SubscribePermissionStatusChange(
198       PermissionType permission,
199       content::RenderProcessHost* render_process_host,
200       content::RenderFrameHost* render_frame_host,
201       const GURL& requesting_origin,
202       base::RepeatingCallback<void(PermissionStatus)> callback) {
203     return GetPermissionManager()->SubscribePermissionStatusChange(
204         permission, render_process_host, render_frame_host, requesting_origin,
205         std::move(callback));
206   }
207
208   void UnsubscribePermissionStatusChange(
209       content::PermissionControllerDelegate::SubscriptionId subscription_id) {
210     GetPermissionManager()->UnsubscribePermissionStatusChange(subscription_id);
211   }
212
213   bool IsPermissionOverridable(PermissionType permission,
214                                const absl::optional<url::Origin>& origin) {
215     return GetPermissionManager()->IsPermissionOverridable(permission, origin);
216   }
217
218   void ResetPermission(PermissionType permission,
219                        const GURL& requesting_origin,
220                        const GURL& embedding_origin) {
221     GetPermissionManager()->ResetPermission(permission, requesting_origin,
222                                             embedding_origin);
223   }
224
225   const GURL& url() const { return url_; }
226
227   const GURL& other_url() const { return other_url_; }
228
229   bool callback_called() const { return callback_called_; }
230
231   int callback_count() const { return callback_count_; }
232
233   PermissionStatus callback_result() const { return callback_result_; }
234
235   content::TestBrowserContext* browser_context() const {
236     return browser_context_.get();
237   }
238
239   void Reset() {
240     callback_called_ = false;
241     callback_count_ = 0;
242     callback_result_ = PermissionStatus::ASK;
243   }
244
245   bool PendingRequestsEmpty() {
246     return GetPermissionManager()->pending_requests_.IsEmpty();
247   }
248
249   // The header policy should only be set once on page load, so we refresh the
250   // page to simulate that.
251   void RefreshPageAndSetHeaderPolicy(content::RenderFrameHost** rfh,
252                                      PermissionsPolicyFeature feature,
253                                      const std::vector<std::string>& origins) {
254     content::RenderFrameHost* current = *rfh;
255     auto navigation = content::NavigationSimulator::CreateRendererInitiated(
256         current->GetLastCommittedURL(), current);
257     std::vector<blink::OriginWithPossibleWildcards> parsed_origins;
258     for (const std::string& origin : origins)
259       parsed_origins.emplace_back(
260           *blink::OriginWithPossibleWildcards::FromOrigin(
261               url::Origin::Create(GURL(origin))));
262     navigation->SetPermissionsPolicyHeader(
263         {{feature, parsed_origins, /*self_if_matches=*/absl::nullopt,
264           /*matches_all_origins=*/false,
265           /*matches_opaque_src=*/false}});
266     navigation->Commit();
267     *rfh = navigation->GetFinalRenderFrameHost();
268   }
269
270   content::RenderFrameHost* AddChildRFH(
271       content::RenderFrameHost* parent,
272       const GURL& origin,
273       PermissionsPolicyFeature feature = PermissionsPolicyFeature::kNotFound) {
274     blink::ParsedPermissionsPolicy frame_policy = {};
275     if (feature != PermissionsPolicyFeature::kNotFound) {
276       frame_policy.emplace_back(
277           feature,
278           std::vector{*blink::OriginWithPossibleWildcards::FromOrigin(
279               url::Origin::Create(origin))},
280           /*self_if_matches=*/absl::nullopt,
281           /*matches_all_origins=*/false,
282           /*matches_opaque_src=*/false);
283     }
284     content::RenderFrameHost* result =
285         content::RenderFrameHostTester::For(parent)->AppendChildWithPolicy(
286             "", frame_policy);
287     content::RenderFrameHostTester::For(result)
288         ->InitializeRenderFrameIfNeeded();
289     SimulateNavigation(&result, origin);
290     return result;
291   }
292
293   TestPermissionsClient& permissions_client() { return client_; }
294
295  private:
296   void SetUp() override {
297     RenderViewHostTestHarness::SetUp();
298     browser_context_ = std::make_unique<content::TestBrowserContext>();
299     browser_context_->SetPermissionControllerDelegate(
300         permissions::GetPermissionControllerDelegate(browser_context_.get()));
301     NavigateAndCommit(url());
302   }
303
304   void TearDown() override {
305     GetPermissionManager()->Shutdown();
306     browser_context_ = nullptr;
307     RenderViewHostTestHarness::TearDown();
308   }
309
310   void SimulateNavigation(content::RenderFrameHost** rfh, const GURL& url) {
311     auto navigation_simulator =
312         content::NavigationSimulator::CreateRendererInitiated(url, *rfh);
313     navigation_simulator->Commit();
314     *rfh = navigation_simulator->GetFinalRenderFrameHost();
315   }
316
317   const GURL url_;
318   const GURL other_url_;
319   bool callback_called_ = false;
320   int callback_count_ = 0;
321   PermissionStatus callback_result_ = PermissionStatus::ASK;
322   base::OnceClosure quit_closure_;
323   std::unique_ptr<content::TestBrowserContext> browser_context_;
324   TestPermissionsClient client_;
325 };
326
327 TEST_F(PermissionManagerTest, GetPermissionStatusDefault) {
328   CheckPermissionStatus(PermissionType::MIDI_SYSEX, PermissionStatus::ASK);
329   CheckPermissionStatus(PermissionType::NOTIFICATIONS, PermissionStatus::ASK);
330   CheckPermissionStatus(PermissionType::GEOLOCATION, PermissionStatus::ASK);
331 #if BUILDFLAG(IS_ANDROID)
332   CheckPermissionStatus(PermissionType::PROTECTED_MEDIA_IDENTIFIER,
333                         PermissionStatus::GRANTED);
334   CheckPermissionStatus(PermissionType::WINDOW_MANAGEMENT,
335                         PermissionStatus::DENIED);
336 #else
337   CheckPermissionStatus(PermissionType::WINDOW_MANAGEMENT,
338                         PermissionStatus::ASK);
339 #endif
340 }
341
342 TEST_F(PermissionManagerTest, GetPermissionStatusAfterSet) {
343   SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
344   CheckPermissionStatus(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
345
346   SetPermission(PermissionType::NOTIFICATIONS, PermissionStatus::GRANTED);
347   CheckPermissionStatus(PermissionType::NOTIFICATIONS,
348                         PermissionStatus::GRANTED);
349
350   SetPermission(PermissionType::MIDI_SYSEX, PermissionStatus::GRANTED);
351   CheckPermissionStatus(PermissionType::MIDI_SYSEX, PermissionStatus::GRANTED);
352
353 #if BUILDFLAG(IS_ANDROID)
354   SetPermission(PermissionType::PROTECTED_MEDIA_IDENTIFIER,
355                 PermissionStatus::GRANTED);
356   CheckPermissionStatus(PermissionType::PROTECTED_MEDIA_IDENTIFIER,
357                         PermissionStatus::GRANTED);
358
359   SetPermission(PermissionType::WINDOW_MANAGEMENT, PermissionStatus::GRANTED);
360   CheckPermissionStatus(PermissionType::WINDOW_MANAGEMENT,
361                         PermissionStatus::DENIED);
362 #else
363   SetPermission(PermissionType::WINDOW_MANAGEMENT, PermissionStatus::GRANTED);
364   CheckPermissionStatus(PermissionType::WINDOW_MANAGEMENT,
365                         PermissionStatus::GRANTED);
366 #endif
367 }
368
369 TEST_F(PermissionManagerTest, CheckPermissionResultDefault) {
370   CheckPermissionResult(PermissionType::MIDI_SYSEX, PermissionStatus::ASK,
371                         content::PermissionStatusSource::UNSPECIFIED);
372   CheckPermissionResult(PermissionType::NOTIFICATIONS, PermissionStatus::ASK,
373                         content::PermissionStatusSource::UNSPECIFIED);
374   CheckPermissionResult(PermissionType::GEOLOCATION, PermissionStatus::ASK,
375                         content::PermissionStatusSource::UNSPECIFIED);
376 #if BUILDFLAG(IS_ANDROID)
377   CheckPermissionResult(PermissionType::PROTECTED_MEDIA_IDENTIFIER,
378                         PermissionStatus::GRANTED,
379                         content::PermissionStatusSource::UNSPECIFIED);
380 #endif
381 }
382
383 TEST_F(PermissionManagerTest, CheckPermissionResultAfterSet) {
384   SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
385   CheckPermissionResult(PermissionType::GEOLOCATION, PermissionStatus::GRANTED,
386                         content::PermissionStatusSource::UNSPECIFIED);
387
388   SetPermission(PermissionType::NOTIFICATIONS, PermissionStatus::GRANTED);
389   CheckPermissionResult(PermissionType::NOTIFICATIONS,
390                         PermissionStatus::GRANTED,
391                         content::PermissionStatusSource::UNSPECIFIED);
392
393   SetPermission(PermissionType::MIDI_SYSEX, PermissionStatus::GRANTED);
394   CheckPermissionResult(PermissionType::MIDI_SYSEX, PermissionStatus::GRANTED,
395                         content::PermissionStatusSource::UNSPECIFIED);
396
397 #if BUILDFLAG(IS_ANDROID)
398   SetPermission(PermissionType::PROTECTED_MEDIA_IDENTIFIER,
399                 PermissionStatus::GRANTED);
400   CheckPermissionResult(PermissionType::PROTECTED_MEDIA_IDENTIFIER,
401                         PermissionStatus::GRANTED,
402                         content::PermissionStatusSource::UNSPECIFIED);
403 #endif
404 }
405
406 TEST_F(PermissionManagerTest, SubscriptionDestroyedCleanlyWithoutUnsubscribe) {
407   // Test that the PermissionManager shuts down cleanly with subscriptions that
408   // haven't been removed, crbug.com/720071.
409   SubscribePermissionStatusChange(
410       PermissionType::GEOLOCATION, /*render_process_host=*/nullptr, main_rfh(),
411       url(),
412       base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
413                           base::Unretained(this)));
414 }
415
416 TEST_F(PermissionManagerTest, SubscribeUnsubscribeAfterShutdown) {
417   content::PermissionControllerDelegate::SubscriptionId subscription_id =
418       SubscribePermissionStatusChange(
419           PermissionType::GEOLOCATION, /*render_process_host=*/nullptr,
420           main_rfh(), url(),
421           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
422                               base::Unretained(this)));
423
424   // Simulate Keyed Services shutdown pass. Note: Shutdown will be called second
425   // time during browser_context destruction. This is ok for now: Shutdown is
426   // reenterant.
427   GetPermissionManager()->Shutdown();
428
429   UnsubscribePermissionStatusChange(subscription_id);
430
431   // Check that subscribe/unsubscribe after shutdown don't crash.
432   content::PermissionControllerDelegate::SubscriptionId subscription2_id =
433       SubscribePermissionStatusChange(
434           PermissionType::GEOLOCATION, /*render_process_host=*/nullptr,
435           main_rfh(), url(),
436           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
437                               base::Unretained(this)));
438
439   UnsubscribePermissionStatusChange(subscription2_id);
440 }
441
442 TEST_F(PermissionManagerTest, SameTypeChangeNotifies) {
443   content::PermissionControllerDelegate::SubscriptionId subscription_id =
444       SubscribePermissionStatusChange(
445           PermissionType::GEOLOCATION, /*render_process_host=*/nullptr,
446           main_rfh(), url(),
447           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
448                               base::Unretained(this)));
449
450   SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
451
452   EXPECT_TRUE(callback_called());
453   EXPECT_EQ(PermissionStatus::GRANTED, callback_result());
454
455   UnsubscribePermissionStatusChange(subscription_id);
456 }
457
458 TEST_F(PermissionManagerTest, DifferentTypeChangeDoesNotNotify) {
459   content::PermissionControllerDelegate::SubscriptionId subscription_id =
460       SubscribePermissionStatusChange(
461           PermissionType::GEOLOCATION, /*render_process_host=*/nullptr,
462           main_rfh(), url(),
463           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
464                               base::Unretained(this)));
465
466   SetPermission(url(), GURL(), PermissionType::NOTIFICATIONS,
467                 PermissionStatus::GRANTED);
468
469   EXPECT_FALSE(callback_called());
470
471   UnsubscribePermissionStatusChange(subscription_id);
472 }
473
474 TEST_F(PermissionManagerTest, ChangeAfterUnsubscribeDoesNotNotify) {
475   content::PermissionControllerDelegate::SubscriptionId subscription_id =
476       SubscribePermissionStatusChange(
477           PermissionType::GEOLOCATION, /*render_process_host=*/nullptr,
478           main_rfh(), url(),
479           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
480                               base::Unretained(this)));
481
482   UnsubscribePermissionStatusChange(subscription_id);
483
484   SetPermission(url(), url(), PermissionType::GEOLOCATION,
485                 PermissionStatus::GRANTED);
486
487   EXPECT_FALSE(callback_called());
488 }
489
490 TEST_F(PermissionManagerTest,
491        ChangeAfterUnsubscribeOnlyNotifiesActiveSubscribers) {
492   content::PermissionControllerDelegate::SubscriptionId subscription_id =
493       SubscribePermissionStatusChange(
494           PermissionType::GEOLOCATION, /*render_process_host=*/nullptr,
495           main_rfh(), url(),
496           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
497                               base::Unretained(this)));
498
499   SubscribePermissionStatusChange(
500       PermissionType::GEOLOCATION, /*render_process_host=*/nullptr, main_rfh(),
501       url(),
502       base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
503                           base::Unretained(this)));
504
505   UnsubscribePermissionStatusChange(subscription_id);
506
507   SetPermission(url(), url(), PermissionType::GEOLOCATION,
508                 PermissionStatus::GRANTED);
509
510   EXPECT_EQ(callback_count(), 1);
511 }
512
513 TEST_F(PermissionManagerTest, DifferentPrimaryUrlDoesNotNotify) {
514   content::PermissionControllerDelegate::SubscriptionId subscription_id =
515       SubscribePermissionStatusChange(
516           PermissionType::GEOLOCATION, /*render_process_host=*/nullptr,
517           main_rfh(), url(),
518           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
519                               base::Unretained(this)));
520
521   SetPermission(other_url(), url(), PermissionType::GEOLOCATION,
522                 PermissionStatus::GRANTED);
523
524   EXPECT_FALSE(callback_called());
525
526   UnsubscribePermissionStatusChange(subscription_id);
527 }
528
529 TEST_F(PermissionManagerTest, DifferentSecondaryUrlDoesNotNotify) {
530   content::PermissionControllerDelegate::SubscriptionId subscription_id =
531       SubscribePermissionStatusChange(
532           PermissionType::STORAGE_ACCESS_GRANT, /*render_process_host=*/nullptr,
533           main_rfh(), url(),
534           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
535                               base::Unretained(this)));
536
537   SetPermission(url(), other_url(), PermissionType::STORAGE_ACCESS_GRANT,
538                 PermissionStatus::GRANTED);
539
540   EXPECT_FALSE(callback_called());
541
542   UnsubscribePermissionStatusChange(subscription_id);
543 }
544
545 TEST_F(PermissionManagerTest, WildCardPatternNotifies) {
546   content::PermissionControllerDelegate::SubscriptionId subscription_id =
547       SubscribePermissionStatusChange(
548           PermissionType::GEOLOCATION, /*render_process_host=*/nullptr,
549           main_rfh(), url(),
550           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
551                               base::Unretained(this)));
552
553   GetHostContentSettingsMap()->SetDefaultContentSetting(
554       ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW);
555
556   EXPECT_TRUE(callback_called());
557   EXPECT_EQ(PermissionStatus::GRANTED, callback_result());
558
559   UnsubscribePermissionStatusChange(subscription_id);
560 }
561
562 TEST_F(PermissionManagerTest, ClearSettingsNotifies) {
563   SetPermission(url(), url(), PermissionType::GEOLOCATION,
564                 PermissionStatus::GRANTED);
565
566   content::PermissionControllerDelegate::SubscriptionId subscription_id =
567       SubscribePermissionStatusChange(
568           PermissionType::GEOLOCATION, /*render_process_host=*/nullptr,
569           main_rfh(), url(),
570           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
571                               base::Unretained(this)));
572
573   GetHostContentSettingsMap()->ClearSettingsForOneType(
574       ContentSettingsType::GEOLOCATION);
575
576   EXPECT_TRUE(callback_called());
577   EXPECT_EQ(PermissionStatus::ASK, callback_result());
578
579   UnsubscribePermissionStatusChange(subscription_id);
580 }
581
582 TEST_F(PermissionManagerTest, NewValueCorrectlyPassed) {
583   content::PermissionControllerDelegate::SubscriptionId subscription_id =
584       SubscribePermissionStatusChange(
585           PermissionType::GEOLOCATION, /*render_process_host=*/nullptr,
586           main_rfh(), url(),
587           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
588                               base::Unretained(this)));
589
590   SetPermission(PermissionType::GEOLOCATION, PermissionStatus::DENIED);
591
592   EXPECT_TRUE(callback_called());
593   EXPECT_EQ(PermissionStatus::DENIED, callback_result());
594
595   UnsubscribePermissionStatusChange(subscription_id);
596 }
597
598 TEST_F(PermissionManagerTest, ChangeWithoutPermissionChangeDoesNotNotify) {
599   SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
600
601   content::PermissionControllerDelegate::SubscriptionId subscription_id =
602       SubscribePermissionStatusChange(
603           PermissionType::GEOLOCATION, /*render_process_host=*/nullptr,
604           main_rfh(), url(),
605           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
606                               base::Unretained(this)));
607
608   SetPermission(url(), url(), PermissionType::GEOLOCATION,
609                 PermissionStatus::GRANTED);
610
611   EXPECT_FALSE(callback_called());
612
613   UnsubscribePermissionStatusChange(subscription_id);
614 }
615
616 TEST_F(PermissionManagerTest, ChangesBackAndForth) {
617   SetPermission(url(), url(), PermissionType::GEOLOCATION,
618                 PermissionStatus::ASK);
619
620   content::PermissionControllerDelegate::SubscriptionId subscription_id =
621       SubscribePermissionStatusChange(
622           PermissionType::GEOLOCATION, /*render_process_host=*/nullptr,
623           main_rfh(), url(),
624           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
625                               base::Unretained(this)));
626
627   SetPermission(url(), url(), PermissionType::GEOLOCATION,
628                 PermissionStatus::GRANTED);
629
630   EXPECT_TRUE(callback_called());
631   EXPECT_EQ(PermissionStatus::GRANTED, callback_result());
632
633   Reset();
634
635   SetPermission(PermissionType::GEOLOCATION, PermissionStatus::ASK);
636
637   EXPECT_TRUE(callback_called());
638   EXPECT_EQ(PermissionStatus::ASK, callback_result());
639
640   UnsubscribePermissionStatusChange(subscription_id);
641 }
642
643 TEST_F(PermissionManagerTest, ChangesBackAndForthWorker) {
644   SetPermission(PermissionType::GEOLOCATION, PermissionStatus::ASK);
645
646   content::PermissionControllerDelegate::SubscriptionId subscription_id =
647       SubscribePermissionStatusChange(
648           PermissionType::GEOLOCATION, process(), /*render_frame_host=*/nullptr,
649           url(),
650           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
651                               base::Unretained(this)));
652
653   SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
654
655   EXPECT_TRUE(callback_called());
656   EXPECT_EQ(PermissionStatus::GRANTED, callback_result());
657
658   Reset();
659
660   SetPermission(PermissionType::GEOLOCATION, PermissionStatus::ASK);
661
662   EXPECT_TRUE(callback_called());
663   EXPECT_EQ(PermissionStatus::ASK, callback_result());
664
665   UnsubscribePermissionStatusChange(subscription_id);
666 }
667
668 TEST_F(PermissionManagerTest, SubscribeMIDIPermission) {
669   content::PermissionControllerDelegate::SubscriptionId subscription_id =
670       SubscribePermissionStatusChange(
671           PermissionType::MIDI, /*render_process_host=*/nullptr, main_rfh(),
672           url(),
673           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
674                               base::Unretained(this)));
675
676   CheckPermissionStatus(PermissionType::GEOLOCATION, PermissionStatus::ASK);
677   SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
678   CheckPermissionStatus(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
679
680   EXPECT_FALSE(callback_called());
681
682   UnsubscribePermissionStatusChange(subscription_id);
683 }
684
685 TEST_F(PermissionManagerTest, PermissionIgnoredCleanup) {
686   content::WebContents* contents = web_contents();
687   PermissionRequestManager::CreateForWebContents(contents);
688   PermissionRequestManager* manager =
689       PermissionRequestManager::FromWebContents(contents);
690   auto prompt_factory = std::make_unique<MockPermissionPromptFactory>(manager);
691
692   NavigateAndCommit(url());
693
694   RequestPermissionFromCurrentDocumentNonBlocking(PermissionType::GEOLOCATION,
695                                                   main_rfh());
696
697   EXPECT_FALSE(PendingRequestsEmpty());
698
699   NavigateAndCommit(GURL("https://foobar.com"));
700
701   EXPECT_TRUE(callback_called());
702   EXPECT_TRUE(PendingRequestsEmpty());
703 }
704
705 // Check PermissionResult shows requests denied due to insecure
706 // origins.
707 TEST_F(PermissionManagerTest, InsecureOrigin) {
708   GURL insecure_frame("http://www.example.com/geolocation");
709   NavigateAndCommit(insecure_frame);
710
711   content::PermissionResult result = GetPermissionResultForCurrentDocument(
712       PermissionType::GEOLOCATION, web_contents()->GetPrimaryMainFrame());
713
714   EXPECT_EQ(PermissionStatus::DENIED, result.status);
715   EXPECT_EQ(content::PermissionStatusSource::INSECURE_ORIGIN, result.source);
716
717   GURL secure_frame("https://www.example.com/geolocation");
718   NavigateAndCommit(secure_frame);
719
720   result = GetPermissionResultForCurrentDocument(
721       PermissionType::GEOLOCATION, web_contents()->GetPrimaryMainFrame());
722
723   EXPECT_EQ(PermissionStatus::ASK, result.status);
724   EXPECT_EQ(content::PermissionStatusSource::UNSPECIFIED, result.source);
725 }
726
727 TEST_F(PermissionManagerTest, InsecureOriginIsNotOverridable) {
728   const url::Origin kInsecureOrigin =
729       url::Origin::Create(GURL("http://example.com/geolocation"));
730   const url::Origin kSecureOrigin =
731       url::Origin::Create(GURL("https://example.com/geolocation"));
732   EXPECT_FALSE(
733       IsPermissionOverridable(PermissionType::GEOLOCATION, kInsecureOrigin));
734   EXPECT_TRUE(
735       IsPermissionOverridable(PermissionType::GEOLOCATION, kSecureOrigin));
736 }
737
738 TEST_F(PermissionManagerTest, MissingContextIsNotOverridable) {
739   // Permissions that are not implemented should be denied overridability.
740 #if !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_ANDROID)
741   EXPECT_FALSE(
742       IsPermissionOverridable(PermissionType::PROTECTED_MEDIA_IDENTIFIER,
743                               url::Origin::Create(GURL("http://localhost"))));
744 #endif
745   EXPECT_TRUE(
746       IsPermissionOverridable(PermissionType::MIDI_SYSEX,
747                               url::Origin::Create(GURL("http://localhost"))));
748 }
749
750 TEST_F(PermissionManagerTest, KillSwitchOnIsNotOverridable) {
751   const url::Origin kLocalHost = url::Origin::Create(GURL("http://localhost"));
752   EXPECT_TRUE(IsPermissionOverridable(PermissionType::GEOLOCATION, kLocalHost));
753
754   // Turn on kill switch for GEOLOCATION.
755   std::map<std::string, std::string> params;
756   params[PermissionUtil::GetPermissionString(
757       ContentSettingsType::GEOLOCATION)] =
758       PermissionContextBase::kPermissionsKillSwitchBlockedValue;
759   base::AssociateFieldTrialParams(
760       PermissionContextBase::kPermissionsKillSwitchFieldStudy, "TestGroup",
761       params);
762   base::FieldTrialList::CreateFieldTrial(
763       PermissionContextBase::kPermissionsKillSwitchFieldStudy, "TestGroup");
764
765   EXPECT_FALSE(
766       IsPermissionOverridable(PermissionType::GEOLOCATION, kLocalHost));
767 }
768
769 TEST_F(PermissionManagerTest, ResetPermission) {
770 #if BUILDFLAG(IS_ANDROID)
771   CheckPermissionStatus(PermissionType::NOTIFICATIONS, PermissionStatus::ASK);
772   SetPermission(PermissionType::NOTIFICATIONS, PermissionStatus::GRANTED);
773   CheckPermissionStatus(PermissionType::NOTIFICATIONS,
774                         PermissionStatus::GRANTED);
775
776   ResetPermission(PermissionType::NOTIFICATIONS, url(), url());
777
778   CheckPermissionStatus(PermissionType::NOTIFICATIONS, PermissionStatus::ASK);
779 #else
780   const char* kOrigin1 = "https://example.com";
781
782   NavigateAndCommit(GURL(kOrigin1));
783   content::RenderFrameHost* rfh = main_rfh();
784
785   EXPECT_EQ(PermissionStatus::ASK, GetPermissionStatusForCurrentDocument(
786                                        PermissionType::NOTIFICATIONS, rfh));
787
788   PermissionRequestManager::CreateForWebContents(web_contents());
789   PermissionRequestManager* manager =
790       PermissionRequestManager::FromWebContents(web_contents());
791   auto prompt_factory = std::make_unique<MockPermissionPromptFactory>(manager);
792   prompt_factory->set_response_type(PermissionRequestManager::ACCEPT_ALL);
793   prompt_factory->DocumentOnLoadCompletedInPrimaryMainFrame();
794
795   RequestPermissionFromCurrentDocument(PermissionType::NOTIFICATIONS, rfh);
796
797   EXPECT_EQ(PermissionStatus::GRANTED, GetPermissionStatusForCurrentDocument(
798                                            PermissionType::NOTIFICATIONS, rfh));
799
800   ResetPermission(PermissionType::NOTIFICATIONS, GURL(kOrigin1),
801                   GURL(kOrigin1));
802
803   EXPECT_EQ(PermissionStatus::ASK, GetPermissionStatusForCurrentDocument(
804                                        PermissionType::NOTIFICATIONS, rfh));
805 #endif
806 }
807
808 TEST_F(PermissionManagerTest, GetPermissionStatusDelegation) {
809   const char* kOrigin1 = "https://example.com";
810   const char* kOrigin2 = "https://google.com";
811
812   NavigateAndCommit(GURL(kOrigin1));
813   content::RenderFrameHost* parent = main_rfh();
814
815   content::RenderFrameHost* child = AddChildRFH(parent, GURL(kOrigin2));
816
817   // By default the parent should be able to request access, but not the child.
818   EXPECT_EQ(PermissionStatus::ASK, GetPermissionStatusForCurrentDocument(
819                                        PermissionType::GEOLOCATION, parent));
820   EXPECT_EQ(PermissionStatus::DENIED, GetPermissionStatusForCurrentDocument(
821                                           PermissionType::GEOLOCATION, child));
822
823   // Enabling geolocation by FP should allow the child to request access also.
824   child = AddChildRFH(parent, GURL(kOrigin2),
825                       PermissionsPolicyFeature::kGeolocation);
826
827   EXPECT_EQ(PermissionStatus::ASK, GetPermissionStatusForCurrentDocument(
828                                        PermissionType::GEOLOCATION, child));
829
830   // When the child requests location a prompt should be displayed for the
831   // parent.
832   PermissionRequestManager::CreateForWebContents(web_contents());
833   PermissionRequestManager* manager =
834       PermissionRequestManager::FromWebContents(web_contents());
835   auto prompt_factory = std::make_unique<MockPermissionPromptFactory>(manager);
836   prompt_factory->set_response_type(PermissionRequestManager::ACCEPT_ALL);
837   prompt_factory->DocumentOnLoadCompletedInPrimaryMainFrame();
838
839   RequestPermissionFromCurrentDocument(PermissionType::GEOLOCATION, child);
840
841   EXPECT_TRUE(prompt_factory->RequestOriginSeen(GURL(kOrigin1)));
842
843   // Now the child frame should have location, as well as the parent frame.
844   EXPECT_EQ(PermissionStatus::GRANTED,
845             GetPermissionStatusForCurrentDocument(PermissionType::GEOLOCATION,
846                                                   parent));
847   EXPECT_EQ(PermissionStatus::GRANTED, GetPermissionStatusForCurrentDocument(
848                                            PermissionType::GEOLOCATION, child));
849
850   // Revoking access from the parent should cause the child not to have access
851   // either.
852   ResetPermission(PermissionType::GEOLOCATION, GURL(kOrigin1), GURL(kOrigin1));
853   EXPECT_EQ(PermissionStatus::ASK, GetPermissionStatusForCurrentDocument(
854                                        PermissionType::GEOLOCATION, parent));
855   EXPECT_EQ(PermissionStatus::ASK, GetPermissionStatusForCurrentDocument(
856                                        PermissionType::GEOLOCATION, child));
857
858   // If the parent changes its policy, the child should be blocked.
859   RefreshPageAndSetHeaderPolicy(&parent, PermissionsPolicyFeature::kGeolocation,
860                                 {kOrigin1});
861   child = AddChildRFH(parent, GURL(kOrigin2));
862
863   EXPECT_EQ(PermissionStatus::ASK, GetPermissionStatusForCurrentDocument(
864                                        PermissionType::GEOLOCATION, parent));
865   EXPECT_EQ(PermissionStatus::DENIED, GetPermissionStatusForCurrentDocument(
866                                           PermissionType::GEOLOCATION, child));
867
868   prompt_factory.reset();
869 }
870
871 TEST_F(PermissionManagerTest, SubscribeWithPermissionDelegation) {
872   const char* kOrigin1 = "https://example.com";
873   const char* kOrigin2 = "https://google.com";
874
875   NavigateAndCommit(GURL(kOrigin1));
876   content::RenderFrameHost* parent = main_rfh();
877   content::RenderFrameHost* child = AddChildRFH(parent, GURL(kOrigin2));
878
879   content::PermissionControllerDelegate::SubscriptionId subscription_id =
880       SubscribePermissionStatusChange(
881           PermissionType::GEOLOCATION, /*render_process_host=*/nullptr, child,
882           GURL(kOrigin2),
883           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
884                               base::Unretained(this)));
885   EXPECT_FALSE(callback_called());
886
887   // Location should be blocked for the child because it's not delegated.
888   EXPECT_EQ(PermissionStatus::DENIED, GetPermissionStatusForCurrentDocument(
889                                           PermissionType::GEOLOCATION, child));
890
891   // Allow access for the top level origin.
892   SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
893
894   // The child's permission should still be block and no callback should be run.
895   EXPECT_EQ(PermissionStatus::DENIED, GetPermissionStatusForCurrentDocument(
896                                           PermissionType::GEOLOCATION, child));
897
898   EXPECT_FALSE(callback_called());
899
900   // Enabling geolocation by FP should allow the child to request access also.
901   child = AddChildRFH(parent, GURL(kOrigin2),
902                       PermissionsPolicyFeature::kGeolocation);
903
904   EXPECT_EQ(PermissionStatus::GRANTED, GetPermissionStatusForCurrentDocument(
905                                            PermissionType::GEOLOCATION, child));
906
907   subscription_id = SubscribePermissionStatusChange(
908       PermissionType::GEOLOCATION, /*render_process_host=*/nullptr, child,
909       GURL(kOrigin2),
910       base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
911                           base::Unretained(this)));
912   EXPECT_FALSE(callback_called());
913
914   // Blocking access to the parent should trigger the callback to be run for the
915   // child also.
916   SetPermission(PermissionType::GEOLOCATION, PermissionStatus::DENIED);
917
918   EXPECT_TRUE(callback_called());
919   EXPECT_EQ(PermissionStatus::DENIED, callback_result());
920
921   EXPECT_EQ(PermissionStatus::DENIED, GetPermissionStatusForCurrentDocument(
922                                           PermissionType::GEOLOCATION, child));
923
924   UnsubscribePermissionStatusChange(subscription_id);
925 }
926
927 TEST_F(PermissionManagerTest, SubscribeUnsubscribeAndResubscribe) {
928   const char* kOrigin1 = "https://example.com";
929   NavigateAndCommit(GURL(kOrigin1));
930
931   content::PermissionControllerDelegate::SubscriptionId subscription_id =
932       SubscribePermissionStatusChange(
933           PermissionType::GEOLOCATION, /*render_process_host=*/nullptr,
934           main_rfh(), GURL(kOrigin1),
935           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
936                               base::Unretained(this)));
937   EXPECT_EQ(callback_count(), 0);
938
939   SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
940
941   EXPECT_EQ(callback_count(), 1);
942   EXPECT_EQ(PermissionStatus::GRANTED, callback_result());
943
944   UnsubscribePermissionStatusChange(subscription_id);
945
946   // ensure no callbacks are received when unsubscribed.
947   SetPermission(PermissionType::GEOLOCATION, PermissionStatus::DENIED);
948   SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
949
950   EXPECT_EQ(callback_count(), 1);
951
952   content::PermissionControllerDelegate::SubscriptionId subscription_id_2 =
953       SubscribePermissionStatusChange(
954           PermissionType::GEOLOCATION, /*render_process_host=*/nullptr,
955           main_rfh(), GURL(kOrigin1),
956           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
957                               base::Unretained(this)));
958   EXPECT_EQ(callback_count(), 1);
959
960   SetPermission(PermissionType::GEOLOCATION, PermissionStatus::DENIED);
961
962   EXPECT_EQ(callback_count(), 2);
963   EXPECT_EQ(PermissionStatus::DENIED, callback_result());
964
965   UnsubscribePermissionStatusChange(subscription_id_2);
966 }
967
968 TEST_F(PermissionManagerTest, GetCanonicalOrigin) {
969   GURL requesting("https://requesting.example.com");
970   GURL embedding("https://embedding.example.com");
971
972   EXPECT_EQ(embedding,
973             permissions::PermissionUtil::GetCanonicalOrigin(
974                 ContentSettingsType::COOKIES, requesting, embedding));
975   EXPECT_EQ(requesting,
976             permissions::PermissionUtil::GetCanonicalOrigin(
977                 ContentSettingsType::NOTIFICATIONS, requesting, embedding));
978   EXPECT_EQ(requesting,
979             permissions::PermissionUtil::GetCanonicalOrigin(
980                 ContentSettingsType::STORAGE_ACCESS, requesting, embedding));
981 }
982
983 TEST_F(PermissionManagerTest, RequestPermissionInDifferentStoragePartition) {
984   const GURL kOrigin("https://example.com");
985   const GURL kOrigin2("https://example2.com");
986   const GURL kPartitionedOrigin("https://partitioned.com");
987   ScopedPartitionedOriginBrowserClient browser_client(kPartitionedOrigin);
988
989   SetPermission(kOrigin, PermissionType::GEOLOCATION,
990                 PermissionStatus::GRANTED);
991
992   SetPermission(kOrigin2, PermissionType::GEOLOCATION,
993                 PermissionStatus::DENIED);
994   SetPermission(kOrigin2, PermissionType::NOTIFICATIONS,
995                 PermissionStatus::GRANTED);
996
997   SetPermission(kPartitionedOrigin, PermissionType::GEOLOCATION,
998                 PermissionStatus::DENIED);
999   SetPermission(kPartitionedOrigin, PermissionType::NOTIFICATIONS,
1000                 PermissionStatus::GRANTED);
1001
1002   NavigateAndCommit(kOrigin);
1003   content::RenderFrameHost* parent = main_rfh();
1004
1005   content::RenderFrameHost* child =
1006       AddChildRFH(parent, kOrigin2, PermissionsPolicyFeature::kGeolocation);
1007   content::RenderFrameHost* partitioned_child = AddChildRFH(
1008       parent, kPartitionedOrigin, PermissionsPolicyFeature::kGeolocation);
1009
1010   // The parent should have geolocation access which is delegated to child and
1011   // partitioned_child.
1012   EXPECT_EQ(PermissionStatus::GRANTED,
1013             GetPermissionStatusForCurrentDocument(PermissionType::GEOLOCATION,
1014                                                   parent));
1015   EXPECT_EQ(PermissionStatus::GRANTED, GetPermissionStatusForCurrentDocument(
1016                                            PermissionType::GEOLOCATION, child));
1017   EXPECT_EQ(PermissionStatus::GRANTED,
1018             GetPermissionStatusForCurrentDocument(PermissionType::GEOLOCATION,
1019                                                   partitioned_child));
1020
1021   // The parent should not have notification permission.
1022   EXPECT_EQ(PermissionStatus::ASK, GetPermissionStatusForCurrentDocument(
1023                                        PermissionType::NOTIFICATIONS, parent));
1024   EXPECT_EQ(PermissionStatus::ASK,
1025             GetPermissionStatusForWorker(
1026                 PermissionType::NOTIFICATIONS, parent->GetProcess(),
1027                 parent->GetLastCommittedOrigin().GetURL()));
1028
1029   // The non-partitioned child should have notification permission.
1030   EXPECT_EQ(PermissionStatus::GRANTED,
1031             GetPermissionStatusForCurrentDocument(PermissionType::NOTIFICATIONS,
1032                                                   child));
1033   EXPECT_EQ(PermissionStatus::GRANTED,
1034             GetPermissionStatusForWorker(
1035                 PermissionType::NOTIFICATIONS, child->GetProcess(),
1036                 child->GetLastCommittedOrigin().GetURL()));
1037
1038   // The partitioned child should not have notification permission because it
1039   // belongs to a different StoragePartition, even though its origin would have
1040   // permission if loaded in a main frame.
1041   EXPECT_EQ(PermissionStatus::DENIED,
1042             GetPermissionStatusForCurrentDocument(PermissionType::NOTIFICATIONS,
1043                                                   partitioned_child));
1044   EXPECT_EQ(PermissionStatus::DENIED,
1045             GetPermissionStatusForWorker(
1046                 PermissionType::NOTIFICATIONS, partitioned_child->GetProcess(),
1047                 partitioned_child->GetLastCommittedOrigin().GetURL()));
1048 }
1049
1050 TEST_F(PermissionManagerTest, SubscribersAreNotifedOfEmbargoEvents) {
1051   const char* kOrigin1 = "https://example.com";
1052   NavigateAndCommit(GURL(kOrigin1));
1053
1054   content::PermissionControllerDelegate::SubscriptionId subscription_id =
1055       SubscribePermissionStatusChange(
1056           PermissionType::GEOLOCATION, /*render_process_host=*/nullptr,
1057           main_rfh(), GURL(kOrigin1),
1058           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
1059                               base::Unretained(this)));
1060   EXPECT_EQ(callback_count(), 0);
1061
1062   auto* autoblocker =
1063       permissions::PermissionsClient::Get()->GetPermissionDecisionAutoBlocker(
1064           browser_context());
1065
1066   // 3 dismisses will trigger embargo, which should call the subscription
1067   // callback.
1068   autoblocker->RecordDismissAndEmbargo(GURL(kOrigin1),
1069                                        ContentSettingsType::GEOLOCATION,
1070                                        false /* dismissed_prompt_was_quiet */);
1071   EXPECT_EQ(callback_count(), 0);
1072   autoblocker->RecordDismissAndEmbargo(GURL(kOrigin1),
1073                                        ContentSettingsType::GEOLOCATION,
1074                                        false /* dismissed_prompt_was_quiet */);
1075   EXPECT_EQ(callback_count(), 0);
1076   autoblocker->RecordDismissAndEmbargo(GURL(kOrigin1),
1077                                        ContentSettingsType::GEOLOCATION,
1078                                        false /* dismissed_prompt_was_quiet */);
1079   EXPECT_EQ(callback_count(), 1);
1080
1081   UnsubscribePermissionStatusChange(subscription_id);
1082 }
1083
1084 TEST_F(PermissionManagerTest, UpdatePermissionStatusWithDeviceStatus) {
1085   struct {
1086     blink::mojom::PermissionStatus initial_status;
1087     bool has_device_permission;
1088     bool can_request_device_permission;
1089     blink::mojom::PermissionStatus expected_status =
1090         initial_status;  // For most of these test cases the expected status is
1091                          // the same as the initial status
1092   } kTests[] = {
1093       {blink::mojom::PermissionStatus::GRANTED, false, false,
1094        blink::mojom::PermissionStatus::DENIED},
1095       {blink::mojom::PermissionStatus::GRANTED, false, true,
1096        blink::mojom::PermissionStatus::ASK},
1097       {blink::mojom::PermissionStatus::GRANTED, true, false},
1098       {blink::mojom::PermissionStatus::GRANTED, true, true},
1099
1100       {blink::mojom::PermissionStatus::ASK, false, false},
1101       {blink::mojom::PermissionStatus::ASK, false, true},
1102       {blink::mojom::PermissionStatus::ASK, true, false},
1103       {blink::mojom::PermissionStatus::ASK, true, true},
1104
1105       {blink::mojom::PermissionStatus::DENIED, false, false},
1106       {blink::mojom::PermissionStatus::DENIED, false, true},
1107       {blink::mojom::PermissionStatus::DENIED, true, false},
1108       {blink::mojom::PermissionStatus::DENIED, true, true},
1109   };
1110
1111   GURL url("http://google.com");
1112
1113   for (const auto& test : kTests) {
1114     SCOPED_TRACE(::testing::Message()
1115                  << "initial_status:" << test.initial_status
1116                  << ", expected_status: " << test.expected_status
1117                  << ", has_device_permission: " << test.has_device_permission
1118                  << ", can_request_device_permission: "
1119                  << test.can_request_device_permission);
1120
1121     SetPermission(blink::PermissionType::NOTIFICATIONS, test.initial_status);
1122     permissions_client().SetHasDevicePermission(test.has_device_permission);
1123     permissions_client().SetCanRequestDevicePermission(
1124         test.can_request_device_permission);
1125
1126     CheckPermissionStatus(blink::PermissionType::NOTIFICATIONS,
1127                           test.expected_status);
1128   }
1129 }
1130
1131 TEST_F(PermissionManagerTest,
1132        RequestableDevicePermissionChangesLazilyNotifiesObservers) {
1133   SetPermission(url(), url(), PermissionType::GEOLOCATION,
1134                 PermissionStatus::GRANTED);
1135   permissions_client().SetHasDevicePermission(true);
1136   permissions_client().SetCanRequestDevicePermission(true);
1137
1138   content::PermissionControllerDelegate::SubscriptionId subscription_id =
1139       SubscribePermissionStatusChange(
1140           PermissionType::GEOLOCATION, /*render_process_host=*/nullptr,
1141           main_rfh(), url(),
1142           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
1143                               base::Unretained(this)));
1144
1145   permissions_client().SetHasDevicePermission(false);
1146
1147   // At this point we have not yet retrieved the permission status so the device
1148   // permission change has not been detected.
1149   EXPECT_FALSE(callback_called());
1150
1151   // This call will trigger an update of the device permission status and
1152   // observers will be notified if needed.
1153   GetPermissionResultForCurrentDocument(PermissionType::GEOLOCATION,
1154                                         web_contents()->GetPrimaryMainFrame());
1155
1156   EXPECT_TRUE(callback_called());
1157   EXPECT_EQ(PermissionStatus::ASK, callback_result());
1158   Reset();
1159
1160   // This does not change the overall permission status so no callback should be
1161   // called.
1162   SetPermission(url(), url(), PermissionType::GEOLOCATION,
1163                 PermissionStatus::ASK);
1164   EXPECT_FALSE(callback_called());
1165
1166   // This does change the overall permission status from ask to blocked.
1167   SetPermission(url(), url(), PermissionType::GEOLOCATION,
1168                 PermissionStatus::DENIED);
1169   EXPECT_TRUE(callback_called());
1170   EXPECT_EQ(PermissionStatus::DENIED, callback_result());
1171   Reset();
1172
1173   // We now reset to a granted state, which should move the overall permission
1174   // status to ask (origin status "granted", but Chrome does not have the device
1175   // permission).
1176   SetPermission(url(), url(), PermissionType::GEOLOCATION,
1177                 PermissionStatus::GRANTED);
1178   EXPECT_TRUE(callback_called());
1179   EXPECT_EQ(PermissionStatus::ASK, callback_result());
1180   Reset();
1181
1182   // Now we reset the device permission status back to granted, which moves the
1183   // overall permission status to granted.
1184   permissions_client().SetHasDevicePermission(true);
1185
1186   // At this point we have not yet refreshed the permission status.
1187   EXPECT_FALSE(callback_called());
1188
1189   // This call will make us retrieve the device permission status and observers
1190   // will be notified if needed.
1191   GetPermissionResultForCurrentDocument(PermissionType::GEOLOCATION,
1192                                         web_contents()->GetPrimaryMainFrame());
1193
1194   EXPECT_TRUE(callback_called());
1195   EXPECT_EQ(PermissionStatus::GRANTED, callback_result());
1196
1197   UnsubscribePermissionStatusChange(subscription_id);
1198 }
1199
1200 TEST_F(PermissionManagerTest,
1201        NonrequestableDevicePermissionChangesLazilyNotifiesObservers) {
1202   SetPermission(url(), url(), PermissionType::GEOLOCATION,
1203                 PermissionStatus::GRANTED);
1204   permissions_client().SetHasDevicePermission(true);
1205   permissions_client().SetCanRequestDevicePermission(false);
1206
1207   content::PermissionControllerDelegate::SubscriptionId subscription_id =
1208       SubscribePermissionStatusChange(
1209           PermissionType::GEOLOCATION, /*render_process_host=*/nullptr,
1210           main_rfh(), url(),
1211           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
1212                               base::Unretained(this)));
1213
1214   EXPECT_EQ(
1215       GetPermissionResultForCurrentDocument(
1216           PermissionType::GEOLOCATION, web_contents()->GetPrimaryMainFrame())
1217           .status,
1218       blink::mojom::PermissionStatus::GRANTED);
1219
1220   permissions_client().SetHasDevicePermission(false);
1221
1222   // At this point the device permission has not been queried yet.
1223   EXPECT_FALSE(callback_called());
1224
1225   // Get permission status to also trigger the device permission being queried
1226   // which would result in observers being notified.
1227   GetPermissionResultForCurrentDocument(PermissionType::GEOLOCATION,
1228                                         web_contents()->GetPrimaryMainFrame());
1229
1230   EXPECT_TRUE(callback_called());
1231   EXPECT_EQ(PermissionStatus::DENIED, callback_result());
1232   Reset();
1233
1234   // Overall these 2 changes don't change the permission status, since the
1235   // status moves back to "denied". While there is a brief moment when both
1236   // device and origin-level permissions are granted, the device permission
1237   // status is not queried in the mean time so observers won't be notified.
1238   permissions_client().SetHasDevicePermission(true);
1239   SetPermission(url(), url(), PermissionType::GEOLOCATION,
1240                 PermissionStatus::DENIED);
1241
1242   EXPECT_FALSE(callback_called());
1243
1244   SetPermission(url(), url(), PermissionType::GEOLOCATION,
1245                 PermissionStatus::GRANTED);
1246   EXPECT_TRUE(callback_called());
1247   EXPECT_EQ(PermissionStatus::GRANTED, callback_result());
1248   Reset();
1249
1250   UnsubscribePermissionStatusChange(subscription_id);
1251 }
1252
1253 }  // namespace permissions