Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / geolocation / geolocation_permission_context_unittest.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/geolocation/geolocation_permission_context.h"
6
7 #include <set>
8 #include <string>
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/id_map.h"
14 #include "base/memory/scoped_vector.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "base/test/simple_test_clock.h"
17 #include "base/time/clock.h"
18 #include "chrome/browser/chrome_notification_types.h"
19 #include "chrome/browser/content_settings/host_content_settings_map.h"
20 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
21 #include "chrome/browser/geolocation/geolocation_permission_context_factory.h"
22 #include "chrome/browser/infobars/infobar_service.h"
23 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
24 #include "chrome/test/base/testing_profile.h"
25 #include "components/content_settings/core/common/permission_request_id.h"
26 #include "components/infobars/core/confirm_infobar_delegate.h"
27 #include "components/infobars/core/infobar.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/navigation_details.h"
30 #include "content/public/browser/notification_registrar.h"
31 #include "content/public/browser/notification_service.h"
32 #include "content/public/browser/web_contents.h"
33 #include "content/public/test/mock_render_process_host.h"
34 #include "content/public/test/test_renderer_host.h"
35 #include "content/public/test/test_utils.h"
36 #include "content/public/test/web_contents_tester.h"
37 #include "testing/gtest/include/gtest/gtest.h"
38
39 #if defined(OS_ANDROID)
40 #include "base/prefs/pref_service.h"
41 #include "chrome/browser/android/mock_google_location_settings_helper.h"
42 #include "chrome/common/pref_names.h"
43 #endif
44
45 #if defined(ENABLE_EXTENSIONS)
46 #include "extensions/browser/view_type_utils.h"
47 #endif
48
49 using content::MockRenderProcessHost;
50
51
52 // ClosedInfoBarTracker -------------------------------------------------------
53
54 // We need to track which infobars were closed.
55 class ClosedInfoBarTracker : public content::NotificationObserver {
56  public:
57   ClosedInfoBarTracker();
58   virtual ~ClosedInfoBarTracker();
59
60   // content::NotificationObserver:
61   virtual void Observe(int type,
62                        const content::NotificationSource& source,
63                        const content::NotificationDetails& details) OVERRIDE;
64
65   size_t size() const { return removed_infobars_.size(); }
66
67   bool Contains(infobars::InfoBar* infobar) const;
68   void Clear();
69
70  private:
71   FRIEND_TEST_ALL_PREFIXES(GeolocationPermissionContextTests, TabDestroyed);
72   content::NotificationRegistrar registrar_;
73   std::set<infobars::InfoBar*> removed_infobars_;
74 };
75
76 ClosedInfoBarTracker::ClosedInfoBarTracker() {
77   registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
78                  content::NotificationService::AllSources());
79 }
80
81 ClosedInfoBarTracker::~ClosedInfoBarTracker() {
82 }
83
84 void ClosedInfoBarTracker::Observe(
85     int type,
86     const content::NotificationSource& source,
87     const content::NotificationDetails& details) {
88   DCHECK(type == chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED);
89   removed_infobars_.insert(
90       content::Details<infobars::InfoBar::RemovedDetails>(details)->first);
91 }
92
93 bool ClosedInfoBarTracker::Contains(infobars::InfoBar* infobar) const {
94   return removed_infobars_.count(infobar) != 0;
95 }
96
97 void ClosedInfoBarTracker::Clear() {
98   removed_infobars_.clear();
99 }
100
101
102 // GeolocationPermissionContextTests ------------------------------------------
103
104 class GeolocationPermissionContextTests
105     : public ChromeRenderViewHostTestHarness {
106  protected:
107   // ChromeRenderViewHostTestHarness:
108   virtual void SetUp() OVERRIDE;
109   virtual void TearDown() OVERRIDE;
110
111   PermissionRequestID RequestID(int bridge_id);
112   PermissionRequestID RequestIDForTab(int tab, int bridge_id);
113   InfoBarService* infobar_service() {
114     return InfoBarService::FromWebContents(web_contents());
115   }
116   InfoBarService* infobar_service_for_tab(int tab) {
117     return InfoBarService::FromWebContents(extra_tabs_[tab]);
118   }
119
120   void RequestGeolocationPermission(content::WebContents* web_contents,
121                                     const PermissionRequestID& id,
122                                     const GURL& requesting_frame);
123   void RequestGeolocationPermission(content::WebContents* web_contents,
124                                     const PermissionRequestID& id,
125                                     const GURL& requesting_frame,
126                                     base::Closure* cancel_callback);
127   void PermissionResponse(const PermissionRequestID& id,
128                           bool allowed);
129   void CheckPermissionMessageSent(int bridge_id, bool allowed);
130   void CheckPermissionMessageSentForTab(int tab, int bridge_id, bool allowed);
131   void CheckPermissionMessageSentInternal(MockRenderProcessHost* process,
132                                           int bridge_id,
133                                           bool allowed);
134   void AddNewTab(const GURL& url);
135   void CheckTabContentsState(const GURL& requesting_frame,
136                              ContentSetting expected_content_setting);
137
138   scoped_refptr<GeolocationPermissionContext> geolocation_permission_context_;
139   ClosedInfoBarTracker closed_infobar_tracker_;
140   ScopedVector<content::WebContents> extra_tabs_;
141
142   // A map between renderer child id and a pair represending the bridge id and
143   // whether the requested permission was allowed.
144   base::hash_map<int, std::pair<int, bool> > responses_;
145 };
146
147 PermissionRequestID GeolocationPermissionContextTests::RequestID(
148     int bridge_id) {
149   return PermissionRequestID(
150       web_contents()->GetRenderProcessHost()->GetID(),
151       web_contents()->GetRenderViewHost()->GetRoutingID(),
152       bridge_id,
153       GURL());
154 }
155
156 PermissionRequestID GeolocationPermissionContextTests::RequestIDForTab(
157     int tab,
158     int bridge_id) {
159   return PermissionRequestID(
160       extra_tabs_[tab]->GetRenderProcessHost()->GetID(),
161       extra_tabs_[tab]->GetRenderViewHost()->GetRoutingID(),
162       bridge_id,
163       GURL());
164 }
165
166 void GeolocationPermissionContextTests::RequestGeolocationPermission(
167     content::WebContents* web_contents,
168     const PermissionRequestID& id,
169     const GURL& requesting_frame) {
170   RequestGeolocationPermission(web_contents, id, requesting_frame, NULL);
171 }
172
173 void GeolocationPermissionContextTests::RequestGeolocationPermission(
174     content::WebContents* web_contents,
175     const PermissionRequestID& id,
176     const GURL& requesting_frame,
177     base::Closure* cancel_callback) {
178   geolocation_permission_context_->RequestGeolocationPermission(
179       web_contents, id.bridge_id(), requesting_frame, false,
180       base::Bind(&GeolocationPermissionContextTests::PermissionResponse,
181                  base::Unretained(this), id),
182       cancel_callback);
183   content::RunAllBlockingPoolTasksUntilIdle();
184 }
185
186 void GeolocationPermissionContextTests::PermissionResponse(
187     const PermissionRequestID& id,
188     bool allowed) {
189   responses_[id.render_process_id()] = std::make_pair(id.bridge_id(), allowed);
190 }
191
192 void GeolocationPermissionContextTests::CheckPermissionMessageSent(
193     int bridge_id,
194     bool allowed) {
195   CheckPermissionMessageSentInternal(process(), bridge_id, allowed);
196 }
197
198 void GeolocationPermissionContextTests::CheckPermissionMessageSentForTab(
199     int tab,
200     int bridge_id,
201     bool allowed) {
202   CheckPermissionMessageSentInternal(static_cast<MockRenderProcessHost*>(
203       extra_tabs_[tab]->GetRenderProcessHost()),
204       bridge_id, allowed);
205 }
206
207 void GeolocationPermissionContextTests::CheckPermissionMessageSentInternal(
208     MockRenderProcessHost* process,
209     int bridge_id,
210     bool allowed) {
211   ASSERT_EQ(responses_.count(process->GetID()), 1U);
212   EXPECT_EQ(bridge_id, responses_[process->GetID()].first);
213   EXPECT_EQ(allowed, responses_[process->GetID()].second);
214   responses_.erase(process->GetID());
215 }
216
217 void GeolocationPermissionContextTests::AddNewTab(const GURL& url) {
218   content::WebContents* new_tab = content::WebContents::Create(
219       content::WebContents::CreateParams(profile()));
220   new_tab->GetController().LoadURL(
221       url, content::Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
222   content::RenderViewHostTester::For(new_tab->GetRenderViewHost())->
223       SendNavigate(extra_tabs_.size() + 1, url);
224
225   // Set up required helpers, and make this be as "tabby" as the code requires.
226 #if defined(ENABLE_EXTENSIONS)
227   extensions::SetViewType(new_tab, extensions::VIEW_TYPE_TAB_CONTENTS);
228 #endif
229   InfoBarService::CreateForWebContents(new_tab);
230
231   extra_tabs_.push_back(new_tab);
232 }
233
234 void GeolocationPermissionContextTests::CheckTabContentsState(
235     const GURL& requesting_frame,
236     ContentSetting expected_content_setting) {
237   TabSpecificContentSettings* content_settings =
238       TabSpecificContentSettings::FromWebContents(web_contents());
239   const ContentSettingsUsagesState::StateMap& state_map =
240       content_settings->geolocation_usages_state().state_map();
241   EXPECT_EQ(1U, state_map.count(requesting_frame.GetOrigin()));
242   EXPECT_EQ(0U, state_map.count(requesting_frame));
243   ContentSettingsUsagesState::StateMap::const_iterator settings =
244       state_map.find(requesting_frame.GetOrigin());
245   ASSERT_FALSE(settings == state_map.end())
246       << "geolocation state not found " << requesting_frame;
247   EXPECT_EQ(expected_content_setting, settings->second);
248 }
249
250 void GeolocationPermissionContextTests::SetUp() {
251   ChromeRenderViewHostTestHarness::SetUp();
252
253   // Set up required helpers, and make this be as "tabby" as the code requires.
254 #if defined(ENABLE_EXTENSIONS)
255   extensions::SetViewType(web_contents(), extensions::VIEW_TYPE_TAB_CONTENTS);
256 #endif
257   InfoBarService::CreateForWebContents(web_contents());
258   TabSpecificContentSettings::CreateForWebContents(web_contents());
259 #if defined(OS_ANDROID)
260   MockGoogleLocationSettingsHelper::SetLocationStatus(true, true);
261 #endif
262   geolocation_permission_context_ =
263       GeolocationPermissionContextFactory::GetForProfile(profile());
264 }
265
266 void GeolocationPermissionContextTests::TearDown() {
267   extra_tabs_.clear();
268   ChromeRenderViewHostTestHarness::TearDown();
269 }
270
271 // Tests ----------------------------------------------------------------------
272
273 TEST_F(GeolocationPermissionContextTests, SinglePermission) {
274   GURL requesting_frame("http://www.example.com/geolocation");
275   NavigateAndCommit(requesting_frame);
276   EXPECT_EQ(0U, infobar_service()->infobar_count());
277   RequestGeolocationPermission(web_contents(), RequestID(0), requesting_frame);
278   ASSERT_EQ(1U, infobar_service()->infobar_count());
279   infobars::InfoBar* infobar = infobar_service()->infobar_at(0);
280   ConfirmInfoBarDelegate* infobar_delegate =
281       infobar->delegate()->AsConfirmInfoBarDelegate();
282   ASSERT_TRUE(infobar_delegate);
283   infobar_delegate->Cancel();
284   infobar_service()->RemoveInfoBar(infobar);
285   EXPECT_EQ(1U, closed_infobar_tracker_.size());
286   EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar));
287 }
288
289 #if defined(OS_ANDROID)
290 TEST_F(GeolocationPermissionContextTests, GeolocationEnabledDisabled) {
291   GURL requesting_frame("http://www.example.com/geolocation");
292   NavigateAndCommit(requesting_frame);
293   MockGoogleLocationSettingsHelper::SetLocationStatus(true, true);
294   EXPECT_EQ(0U, infobar_service()->infobar_count());
295   RequestGeolocationPermission(web_contents(), RequestID(0), requesting_frame);
296   EXPECT_EQ(1U, infobar_service()->infobar_count());
297   ConfirmInfoBarDelegate* infobar_delegate_0 =
298       infobar_service()->infobar_at(0)->delegate()->AsConfirmInfoBarDelegate();
299   ASSERT_TRUE(infobar_delegate_0);
300   base::string16 text_0 = infobar_delegate_0->GetButtonLabel(
301       ConfirmInfoBarDelegate::BUTTON_OK);
302
303   Reload();
304   MockGoogleLocationSettingsHelper::SetLocationStatus(true, false);
305   EXPECT_EQ(0U, infobar_service()->infobar_count());
306   RequestGeolocationPermission(web_contents(), RequestID(0), requesting_frame);
307   EXPECT_EQ(0U, infobar_service()->infobar_count());
308 }
309
310 TEST_F(GeolocationPermissionContextTests, MasterEnabledGoogleAppsEnabled) {
311   GURL requesting_frame("http://www.example.com/geolocation");
312   NavigateAndCommit(requesting_frame);
313   MockGoogleLocationSettingsHelper::SetLocationStatus(true, true);
314   EXPECT_EQ(0U, infobar_service()->infobar_count());
315   RequestGeolocationPermission(web_contents(), RequestID(0), requesting_frame);
316   EXPECT_EQ(1U, infobar_service()->infobar_count());
317   ConfirmInfoBarDelegate* infobar_delegate =
318       infobar_service()->infobar_at(0)->delegate()->AsConfirmInfoBarDelegate();
319   ASSERT_TRUE(infobar_delegate);
320   infobar_delegate->Accept();
321   CheckTabContentsState(requesting_frame, CONTENT_SETTING_ALLOW);
322   CheckPermissionMessageSent(0, true);
323 }
324
325 TEST_F(GeolocationPermissionContextTests, MasterEnabledGoogleAppsDisabled) {
326   GURL requesting_frame("http://www.example.com/geolocation");
327   NavigateAndCommit(requesting_frame);
328   MockGoogleLocationSettingsHelper::SetLocationStatus(true, false);
329   EXPECT_EQ(0U, infobar_service()->infobar_count());
330   RequestGeolocationPermission(web_contents(), RequestID(0), requesting_frame);
331   EXPECT_EQ(0U, infobar_service()->infobar_count());
332 }
333 #endif
334
335 TEST_F(GeolocationPermissionContextTests, QueuedPermission) {
336   GURL requesting_frame_0("http://www.example.com/geolocation");
337   GURL requesting_frame_1("http://www.example-2.com/geolocation");
338   EXPECT_EQ(CONTENT_SETTING_ASK,
339             profile()->GetHostContentSettingsMap()->GetContentSetting(
340                 requesting_frame_0, requesting_frame_0,
341                 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
342   EXPECT_EQ(CONTENT_SETTING_ASK,
343             profile()->GetHostContentSettingsMap()->GetContentSetting(
344                 requesting_frame_1, requesting_frame_0,
345                 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
346
347   NavigateAndCommit(requesting_frame_0);
348   EXPECT_EQ(0U, infobar_service()->infobar_count());
349   // Request permission for two frames.
350   RequestGeolocationPermission(
351       web_contents(), RequestID(0), requesting_frame_0);
352   RequestGeolocationPermission(
353       web_contents(), RequestID(1), requesting_frame_1);
354   // Ensure only one infobar is created.
355   ASSERT_EQ(1U, infobar_service()->infobar_count());
356   infobars::InfoBar* infobar_0 = infobar_service()->infobar_at(0);
357   ConfirmInfoBarDelegate* infobar_delegate_0 =
358       infobar_0->delegate()->AsConfirmInfoBarDelegate();
359   ASSERT_TRUE(infobar_delegate_0);
360   base::string16 text_0 = infobar_delegate_0->GetMessageText();
361
362   // Accept the first frame.
363   infobar_delegate_0->Accept();
364   CheckTabContentsState(requesting_frame_0, CONTENT_SETTING_ALLOW);
365   CheckPermissionMessageSent(0, true);
366
367   infobar_service()->RemoveInfoBar(infobar_0);
368   EXPECT_EQ(1U, closed_infobar_tracker_.size());
369   EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_0));
370   closed_infobar_tracker_.Clear();
371   // Now we should have a new infobar for the second frame.
372   ASSERT_EQ(1U, infobar_service()->infobar_count());
373
374   infobars::InfoBar* infobar_1 = infobar_service()->infobar_at(0);
375   ConfirmInfoBarDelegate* infobar_delegate_1 =
376       infobar_1->delegate()->AsConfirmInfoBarDelegate();
377   ASSERT_TRUE(infobar_delegate_1);
378   base::string16 text_1 = infobar_delegate_1->GetMessageText();
379   EXPECT_NE(text_0, text_1);
380
381   // Cancel (block) this frame.
382   infobar_delegate_1->Cancel();
383   CheckTabContentsState(requesting_frame_1, CONTENT_SETTING_BLOCK);
384   CheckPermissionMessageSent(1, false);
385   infobar_service()->RemoveInfoBar(infobar_1);
386   EXPECT_EQ(1U, closed_infobar_tracker_.size());
387   EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_1));
388   EXPECT_EQ(0U, infobar_service()->infobar_count());
389   // Ensure the persisted permissions are ok.
390   EXPECT_EQ(CONTENT_SETTING_ALLOW,
391             profile()->GetHostContentSettingsMap()->GetContentSetting(
392                 requesting_frame_0, requesting_frame_0,
393                 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
394
395   EXPECT_EQ(CONTENT_SETTING_BLOCK,
396             profile()->GetHostContentSettingsMap()->GetContentSetting(
397                 requesting_frame_1, requesting_frame_0,
398                 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
399 }
400
401 TEST_F(GeolocationPermissionContextTests, HashIsIgnored) {
402   GURL url_a("http://www.example.com/geolocation#a");
403   GURL url_b("http://www.example.com/geolocation#b");
404
405   // Navigate to the first url and check permission is requested.
406   NavigateAndCommit(url_a);
407   EXPECT_EQ(0U, infobar_service()->infobar_count());
408   RequestGeolocationPermission(web_contents(), RequestID(0), url_a);
409   ASSERT_EQ(1U, infobar_service()->infobar_count());
410   infobars::InfoBar* infobar = infobar_service()->infobar_at(0);
411   ConfirmInfoBarDelegate* infobar_delegate =
412       infobar->delegate()->AsConfirmInfoBarDelegate();
413   ASSERT_TRUE(infobar_delegate);
414
415   // Change the hash, we'll still be on the same page.
416   NavigateAndCommit(url_b);
417
418   // Accept.
419   infobar_delegate->Accept();
420   CheckTabContentsState(url_a, CONTENT_SETTING_ALLOW);
421   CheckTabContentsState(url_b, CONTENT_SETTING_ALLOW);
422   CheckPermissionMessageSent(0, true);
423
424   // Cleanup.
425   infobar_service()->RemoveInfoBar(infobar);
426   EXPECT_EQ(1U, closed_infobar_tracker_.size());
427   EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar));
428 }
429
430 TEST_F(GeolocationPermissionContextTests, PermissionForFileScheme) {
431   GURL requesting_frame("file://example/geolocation.html");
432   NavigateAndCommit(requesting_frame);
433   EXPECT_EQ(0U, infobar_service()->infobar_count());
434   RequestGeolocationPermission(web_contents(), RequestID(0), requesting_frame);
435   EXPECT_EQ(1U, infobar_service()->infobar_count());
436   infobars::InfoBar* infobar = infobar_service()->infobar_at(0);
437   ConfirmInfoBarDelegate* infobar_delegate =
438       infobar->delegate()->AsConfirmInfoBarDelegate();
439   ASSERT_TRUE(infobar_delegate);
440   // Accept the frame.
441   infobar_delegate->Accept();
442   CheckTabContentsState(requesting_frame, CONTENT_SETTING_ALLOW);
443   CheckPermissionMessageSent(0, true);
444   infobar_service()->RemoveInfoBar(infobar);
445
446   // Make sure the setting is not stored.
447   EXPECT_EQ(CONTENT_SETTING_ASK,
448       profile()->GetHostContentSettingsMap()->GetContentSetting(
449           requesting_frame,
450           requesting_frame,
451           CONTENT_SETTINGS_TYPE_GEOLOCATION,
452           std::string()));
453 }
454
455 TEST_F(GeolocationPermissionContextTests, CancelGeolocationPermissionRequest) {
456   GURL requesting_frame_0("http://www.example.com/geolocation");
457   GURL requesting_frame_1("http://www.example-2.com/geolocation");
458   EXPECT_EQ(CONTENT_SETTING_ASK,
459             profile()->GetHostContentSettingsMap()->GetContentSetting(
460                 requesting_frame_0, requesting_frame_0,
461                 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
462
463   EXPECT_EQ(CONTENT_SETTING_ASK,
464             profile()->GetHostContentSettingsMap()->GetContentSetting(
465                 requesting_frame_1, requesting_frame_0,
466                 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
467
468   NavigateAndCommit(requesting_frame_0);
469   EXPECT_EQ(0U, infobar_service()->infobar_count());
470   // Request permission for two frames.
471   base::Closure cancel_callback;
472   RequestGeolocationPermission(
473       web_contents(), RequestID(0), requesting_frame_0, &cancel_callback);
474   RequestGeolocationPermission(
475       web_contents(), RequestID(1), requesting_frame_1);
476   ASSERT_EQ(1U, infobar_service()->infobar_count());
477
478   infobars::InfoBar* infobar_0 = infobar_service()->infobar_at(0);
479   ConfirmInfoBarDelegate* infobar_delegate_0 =
480       infobar_0->delegate()->AsConfirmInfoBarDelegate();
481   ASSERT_TRUE(infobar_delegate_0);
482   base::string16 text_0 = infobar_delegate_0->GetMessageText();
483
484   // Simulate the frame going away, ensure the infobar for this frame
485   // is removed and the next pending infobar is created.
486   cancel_callback.Run();
487   EXPECT_EQ(1U, closed_infobar_tracker_.size());
488   EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_0));
489   closed_infobar_tracker_.Clear();
490   ASSERT_EQ(1U, infobar_service()->infobar_count());
491
492   infobars::InfoBar* infobar_1 = infobar_service()->infobar_at(0);
493   ConfirmInfoBarDelegate* infobar_delegate_1 =
494       infobar_1->delegate()->AsConfirmInfoBarDelegate();
495   ASSERT_TRUE(infobar_delegate_1);
496   base::string16 text_1 = infobar_delegate_1->GetMessageText();
497   EXPECT_NE(text_0, text_1);
498
499   // Allow this frame.
500   infobar_delegate_1->Accept();
501   CheckTabContentsState(requesting_frame_1, CONTENT_SETTING_ALLOW);
502   CheckPermissionMessageSent(1, true);
503   infobar_service()->RemoveInfoBar(infobar_1);
504   EXPECT_EQ(1U, closed_infobar_tracker_.size());
505   EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_1));
506   EXPECT_EQ(0U, infobar_service()->infobar_count());
507   // Ensure the persisted permissions are ok.
508   EXPECT_EQ(CONTENT_SETTING_ASK,
509             profile()->GetHostContentSettingsMap()->GetContentSetting(
510                 requesting_frame_0, requesting_frame_0,
511                 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
512
513   EXPECT_EQ(CONTENT_SETTING_ALLOW,
514             profile()->GetHostContentSettingsMap()->GetContentSetting(
515                 requesting_frame_1, requesting_frame_0,
516                 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
517 }
518
519 TEST_F(GeolocationPermissionContextTests, InvalidURL) {
520   GURL invalid_embedder("about:blank");
521   GURL requesting_frame;
522   NavigateAndCommit(invalid_embedder);
523   EXPECT_EQ(0U, infobar_service()->infobar_count());
524   RequestGeolocationPermission(web_contents(), RequestID(0), requesting_frame);
525   EXPECT_EQ(0U, infobar_service()->infobar_count());
526   CheckPermissionMessageSent(0, false);
527 }
528
529 TEST_F(GeolocationPermissionContextTests, SameOriginMultipleTabs) {
530   GURL url_a("http://www.example.com/geolocation");
531   GURL url_b("http://www.example-2.com/geolocation");
532   NavigateAndCommit(url_a);
533   AddNewTab(url_b);
534   AddNewTab(url_a);
535
536   EXPECT_EQ(0U, infobar_service()->infobar_count());
537   RequestGeolocationPermission(web_contents(), RequestID(0), url_a);
538   ASSERT_EQ(1U, infobar_service()->infobar_count());
539
540   RequestGeolocationPermission(extra_tabs_[0], RequestIDForTab(0, 0), url_b);
541   EXPECT_EQ(1U, infobar_service_for_tab(0)->infobar_count());
542
543   RequestGeolocationPermission(extra_tabs_[1], RequestIDForTab(1, 0), url_a);
544   ASSERT_EQ(1U, infobar_service_for_tab(1)->infobar_count());
545
546   infobars::InfoBar* removed_infobar =
547       infobar_service_for_tab(1)->infobar_at(0);
548
549   // Accept the first tab.
550   infobars::InfoBar* infobar_0 = infobar_service()->infobar_at(0);
551   ConfirmInfoBarDelegate* infobar_delegate_0 =
552       infobar_0->delegate()->AsConfirmInfoBarDelegate();
553   ASSERT_TRUE(infobar_delegate_0);
554   infobar_delegate_0->Accept();
555   CheckPermissionMessageSent(0, true);
556   infobar_service()->RemoveInfoBar(infobar_0);
557   EXPECT_EQ(2U, closed_infobar_tracker_.size());
558   EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_0));
559   // Now the infobar for the tab with the same origin should have gone.
560   EXPECT_EQ(0U, infobar_service_for_tab(1)->infobar_count());
561   CheckPermissionMessageSentForTab(1, 0, true);
562   EXPECT_TRUE(closed_infobar_tracker_.Contains(removed_infobar));
563   closed_infobar_tracker_.Clear();
564
565   // But the other tab should still have the info bar...
566   ASSERT_EQ(1U, infobar_service_for_tab(0)->infobar_count());
567   infobars::InfoBar* infobar_1 = infobar_service_for_tab(0)->infobar_at(0);
568   ConfirmInfoBarDelegate* infobar_delegate_1 =
569       infobar_1->delegate()->AsConfirmInfoBarDelegate();
570   ASSERT_TRUE(infobar_delegate_1);
571   infobar_delegate_1->Cancel();
572   infobar_service_for_tab(0)->RemoveInfoBar(infobar_1);
573   EXPECT_EQ(1U, closed_infobar_tracker_.size());
574   EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_1));
575 }
576
577 TEST_F(GeolocationPermissionContextTests, QueuedOriginMultipleTabs) {
578   GURL url_a("http://www.example.com/geolocation");
579   GURL url_b("http://www.example-2.com/geolocation");
580   NavigateAndCommit(url_a);
581   AddNewTab(url_a);
582
583   EXPECT_EQ(0U, infobar_service()->infobar_count());
584   RequestGeolocationPermission(web_contents(), RequestID(0), url_a);
585   ASSERT_EQ(1U, infobar_service()->infobar_count());
586
587   RequestGeolocationPermission(extra_tabs_[0], RequestIDForTab(0, 0), url_a);
588   EXPECT_EQ(1U, infobar_service_for_tab(0)->infobar_count());
589
590   RequestGeolocationPermission(extra_tabs_[0], RequestIDForTab(0, 1), url_b);
591   ASSERT_EQ(1U, infobar_service_for_tab(0)->infobar_count());
592
593   infobars::InfoBar* removed_infobar = infobar_service()->infobar_at(0);
594
595   // Accept the second tab.
596   infobars::InfoBar* infobar_0 = infobar_service_for_tab(0)->infobar_at(0);
597   ConfirmInfoBarDelegate* infobar_delegate_0 =
598       infobar_0->delegate()->AsConfirmInfoBarDelegate();
599   ASSERT_TRUE(infobar_delegate_0);
600   infobar_delegate_0->Accept();
601   CheckPermissionMessageSentForTab(0, 0, true);
602   infobar_service_for_tab(0)->RemoveInfoBar(infobar_0);
603   EXPECT_EQ(2U, closed_infobar_tracker_.size());
604   EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_0));
605   // Now the infobar for the tab with the same origin should have gone.
606   EXPECT_EQ(0U, infobar_service()->infobar_count());
607   CheckPermissionMessageSent(0, true);
608   EXPECT_TRUE(closed_infobar_tracker_.Contains(removed_infobar));
609   closed_infobar_tracker_.Clear();
610
611   // And we should have the queued infobar displayed now.
612   ASSERT_EQ(1U, infobar_service_for_tab(0)->infobar_count());
613
614   // Accept the second infobar.
615   infobars::InfoBar* infobar_1 = infobar_service_for_tab(0)->infobar_at(0);
616   ConfirmInfoBarDelegate* infobar_delegate_1 =
617       infobar_1->delegate()->AsConfirmInfoBarDelegate();
618   ASSERT_TRUE(infobar_delegate_1);
619   infobar_delegate_1->Accept();
620   CheckPermissionMessageSentForTab(0, 1, true);
621   infobar_service_for_tab(0)->RemoveInfoBar(infobar_1);
622   EXPECT_EQ(1U, closed_infobar_tracker_.size());
623   EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_1));
624 }
625
626 TEST_F(GeolocationPermissionContextTests, TabDestroyed) {
627   GURL requesting_frame_0("http://www.example.com/geolocation");
628   GURL requesting_frame_1("http://www.example-2.com/geolocation");
629   EXPECT_EQ(CONTENT_SETTING_ASK,
630             profile()->GetHostContentSettingsMap()->GetContentSetting(
631                 requesting_frame_0, requesting_frame_0,
632                 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
633
634   EXPECT_EQ(CONTENT_SETTING_ASK,
635             profile()->GetHostContentSettingsMap()->GetContentSetting(
636                 requesting_frame_1, requesting_frame_0,
637                 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
638
639   NavigateAndCommit(requesting_frame_0);
640   EXPECT_EQ(0U, infobar_service()->infobar_count());
641   // Request permission for two frames.
642   RequestGeolocationPermission(
643       web_contents(), RequestID(0), requesting_frame_0);
644   RequestGeolocationPermission(
645       web_contents(), RequestID(1), requesting_frame_1);
646   // Ensure only one infobar is created.
647   ASSERT_EQ(1U, infobar_service()->infobar_count());
648   infobars::InfoBar* infobar = infobar_service()->infobar_at(0);
649
650   // Delete the tab contents.
651   DeleteContents();
652
653   // During contents destruction, the infobar will have been closed, and the
654   // pending request should have been cleared without an infobar being created.
655   ASSERT_EQ(1U, closed_infobar_tracker_.size());
656   ASSERT_TRUE(closed_infobar_tracker_.Contains(infobar));
657 }
658
659 TEST_F(GeolocationPermissionContextTests, InfoBarUsesCommittedEntry) {
660   GURL requesting_frame_0("http://www.example.com/geolocation");
661   GURL requesting_frame_1("http://www.example-2.com/geolocation");
662   NavigateAndCommit(requesting_frame_0);
663   NavigateAndCommit(requesting_frame_1);
664   EXPECT_EQ(0U, infobar_service()->infobar_count());
665   // Go back: navigate to a pending entry before requesting geolocation
666   // permission.
667   web_contents()->GetController().GoBack();
668   // Request permission for the committed frame (not the pending one).
669   RequestGeolocationPermission(
670       web_contents(), RequestID(0), requesting_frame_1);
671   // Ensure the infobar is created.
672   ASSERT_EQ(1U, infobar_service()->infobar_count());
673   infobars::InfoBarDelegate* infobar_delegate =
674       infobar_service()->infobar_at(0)->delegate();
675   ASSERT_TRUE(infobar_delegate);
676   // Ensure the infobar wouldn't expire for a navigation to the committed entry.
677   content::LoadCommittedDetails details;
678   details.entry = web_contents()->GetController().GetLastCommittedEntry();
679   EXPECT_FALSE(infobar_delegate->ShouldExpire(
680       InfoBarService::NavigationDetailsFromLoadCommittedDetails(details)));
681   // Ensure the infobar will expire when we commit the pending navigation.
682   details.entry = web_contents()->GetController().GetActiveEntry();
683   EXPECT_TRUE(infobar_delegate->ShouldExpire(
684       InfoBarService::NavigationDetailsFromLoadCommittedDetails(details)));
685
686   // Delete the tab contents.
687   DeleteContents();
688 }
689
690 TEST_F(GeolocationPermissionContextTests, LastUsageAudited) {
691   GURL requesting_frame("http://www.example.com/geolocation");
692   NavigateAndCommit(requesting_frame);
693
694   base::SimpleTestClock* test_clock = new base::SimpleTestClock;
695   test_clock->SetNow(base::Time::UnixEpoch() +
696                      base::TimeDelta::FromSeconds(10));
697
698   HostContentSettingsMap* map = profile()->GetHostContentSettingsMap();
699   map->SetPrefClockForTesting(scoped_ptr<base::Clock>(test_clock));
700
701   // The permission shouldn't have been used yet.
702   EXPECT_EQ(map->GetLastUsage(requesting_frame.GetOrigin(),
703                               requesting_frame.GetOrigin(),
704                               CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
705             0);
706
707   EXPECT_EQ(0U, infobar_service()->infobar_count());
708   RequestGeolocationPermission(web_contents(), RequestID(0), requesting_frame);
709   ASSERT_EQ(1U, infobar_service()->infobar_count());
710   infobars::InfoBar* infobar = infobar_service()->infobar_at(0);
711   ConfirmInfoBarDelegate* infobar_delegate =
712       infobar->delegate()->AsConfirmInfoBarDelegate();
713   ASSERT_TRUE(infobar_delegate);
714   infobar_delegate->Accept();
715   CheckTabContentsState(requesting_frame, CONTENT_SETTING_ALLOW);
716   CheckPermissionMessageSent(0, true);
717
718   // Permission has been used at the starting time.
719   EXPECT_EQ(map->GetLastUsage(requesting_frame.GetOrigin(),
720                               requesting_frame.GetOrigin(),
721                               CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
722             10);
723
724   test_clock->Advance(base::TimeDelta::FromSeconds(3));
725   RequestGeolocationPermission(web_contents(), RequestID(0), requesting_frame);
726
727   // Permission has been used three seconds later.
728   EXPECT_EQ(map->GetLastUsage(requesting_frame.GetOrigin(),
729                               requesting_frame.GetOrigin(),
730                               CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
731             13);
732 }
733
734 TEST_F(GeolocationPermissionContextTests, LastUsageAuditedMultipleFrames) {
735   base::SimpleTestClock* test_clock = new base::SimpleTestClock;
736   test_clock->SetNow(base::Time::UnixEpoch() +
737                      base::TimeDelta::FromSeconds(10));
738
739   HostContentSettingsMap* map = profile()->GetHostContentSettingsMap();
740   map->SetPrefClockForTesting(scoped_ptr<base::Clock>(test_clock));
741
742   GURL requesting_frame_0("http://www.example.com/geolocation");
743   GURL requesting_frame_1("http://www.example-2.com/geolocation");
744
745   // The permission shouldn't have been used yet.
746   EXPECT_EQ(map->GetLastUsage(requesting_frame_0.GetOrigin(),
747                               requesting_frame_0.GetOrigin(),
748                               CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
749             0);
750   EXPECT_EQ(map->GetLastUsage(requesting_frame_1.GetOrigin(),
751                               requesting_frame_0.GetOrigin(),
752                               CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
753             0);
754
755   NavigateAndCommit(requesting_frame_0);
756   EXPECT_EQ(0U, infobar_service()->infobar_count());
757
758   // Request permission for two frames.
759   RequestGeolocationPermission(
760       web_contents(), RequestID(0), requesting_frame_0);
761   RequestGeolocationPermission(
762       web_contents(), RequestID(1), requesting_frame_1);
763
764   // Ensure only one infobar is created.
765   ASSERT_EQ(1U, infobar_service()->infobar_count());
766   infobars::InfoBar* infobar_0 = infobar_service()->infobar_at(0);
767   ConfirmInfoBarDelegate* infobar_delegate_0 =
768       infobar_0->delegate()->AsConfirmInfoBarDelegate();
769
770   // Accept the first frame.
771   infobar_delegate_0->Accept();
772   CheckTabContentsState(requesting_frame_0, CONTENT_SETTING_ALLOW);
773   CheckPermissionMessageSent(0, true);
774   infobar_service()->RemoveInfoBar(infobar_0);
775
776   // Verify that accepting the first didn't accept because it's embedder
777   // in the other.
778   EXPECT_EQ(map->GetLastUsage(requesting_frame_0.GetOrigin(),
779                               requesting_frame_0.GetOrigin(),
780                               CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
781             10);
782   EXPECT_EQ(map->GetLastUsage(requesting_frame_1.GetOrigin(),
783                               requesting_frame_0.GetOrigin(),
784                               CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
785             0);
786
787   ASSERT_EQ(1U, infobar_service()->infobar_count());
788   infobars::InfoBar* infobar_1 = infobar_service()->infobar_at(0);
789   ConfirmInfoBarDelegate* infobar_delegate_1 =
790       infobar_1->delegate()->AsConfirmInfoBarDelegate();
791
792   test_clock->Advance(base::TimeDelta::FromSeconds(1));
793
794   // Allow the second frame.
795   infobar_delegate_1->Accept();
796   CheckTabContentsState(requesting_frame_1, CONTENT_SETTING_ALLOW);
797   CheckPermissionMessageSent(1, true);
798   infobar_service()->RemoveInfoBar(infobar_1);
799
800   // Verify that the times are different.
801   EXPECT_EQ(map->GetLastUsage(requesting_frame_0.GetOrigin(),
802                               requesting_frame_0.GetOrigin(),
803                               CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
804             10);
805   EXPECT_EQ(map->GetLastUsage(requesting_frame_1.GetOrigin(),
806                               requesting_frame_0.GetOrigin(),
807                               CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
808             11);
809
810   test_clock->Advance(base::TimeDelta::FromSeconds(2));
811   RequestGeolocationPermission(
812       web_contents(), RequestID(0), requesting_frame_0);
813
814   // Verify that requesting permission in one frame doesn't update other where
815   // it is the embedder.
816   EXPECT_EQ(map->GetLastUsage(requesting_frame_0.GetOrigin(),
817                               requesting_frame_0.GetOrigin(),
818                               CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
819             13);
820   EXPECT_EQ(map->GetLastUsage(requesting_frame_1.GetOrigin(),
821                               requesting_frame_0.GetOrigin(),
822                               CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
823             11);
824 }