15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/command_line.h" 8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/metrics/user_metrics_action.h" 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/ui/website_settings/permission_bubble_request.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/public/browser/browser_thread.h" 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/navigation_details.h" 13010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/public/browser/user_metrics.h" 14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace { 16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 17010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)class CancelledRequest : public PermissionBubbleRequest { 18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) public: 19010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) explicit CancelledRequest(PermissionBubbleRequest* cancelled) 20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) : icon_(cancelled->GetIconID()), 21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) message_text_(cancelled->GetMessageText()), 22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) message_fragment_(cancelled->GetMessageTextFragment()), 23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) user_gesture_(cancelled->HasUserGesture()), 24010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) hostname_(cancelled->GetRequestingHostname()) {} 25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) virtual ~CancelledRequest() {} 26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) virtual int GetIconID() const OVERRIDE { 28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return icon_; 29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) virtual base::string16 GetMessageText() const OVERRIDE { 31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return message_text_; 32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) virtual base::string16 GetMessageTextFragment() const OVERRIDE { 34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return message_fragment_; 35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) virtual bool HasUserGesture() const OVERRIDE { 37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return user_gesture_; 38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) virtual GURL GetRequestingHostname() const OVERRIDE { 40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return hostname_; 41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // These are all no-ops since the placeholder is non-forwarding. 44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) virtual void PermissionGranted() OVERRIDE {} 45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) virtual void PermissionDenied() OVERRIDE {} 46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) virtual void Cancelled() OVERRIDE {} 47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) virtual void RequestFinished() OVERRIDE { 49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) delete this; 50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) private: 53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int icon_; 54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::string16 message_text_; 55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::string16 message_fragment_; 56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool user_gesture_; 57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) GURL hostname_; 58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}; 59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} // namespace 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)DEFINE_WEB_CONTENTS_USER_DATA_KEY(PermissionBubbleManager); 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool PermissionBubbleManager::Enabled() { 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (CommandLine::ForCurrentProcess()->HasSwitch( 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switches::kEnablePermissionsBubbles)) 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (CommandLine::ForCurrentProcess()->HasSwitch( 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switches::kDisablePermissionsBubbles)) 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)PermissionBubbleManager::PermissionBubbleManager( 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) content::WebContents* web_contents) 79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : content::WebContentsObserver(web_contents), 80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bubble_showing_(false), 81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) view_(NULL), 825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu request_url_has_loaded_(false), 835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu customization_mode_(false), 845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu weak_factory_(this) {} 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)PermissionBubbleManager::~PermissionBubbleManager() { 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (view_ != NULL) 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) view_->SetDelegate(NULL); 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<PermissionBubbleRequest*>::iterator requests_iter; 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (requests_iter = requests_.begin(); 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) requests_iter != requests_.end(); 93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) requests_iter++) { 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (*requests_iter)->RequestFinished(); 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (requests_iter = queued_requests_.begin(); 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) requests_iter != queued_requests_.end(); 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) requests_iter++) { 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (*requests_iter)->RequestFinished(); 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::AddRequest(PermissionBubbleRequest* request) { 104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) content::RecordAction(base::UserMetricsAction("PermissionBubbleRequest")); 1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // TODO(gbillock): is there a race between an early request on a 1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // newly-navigated page and the to-be-cleaned-up requests on the previous 1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // page? We should maybe listen to DidStartNavigationToPendingEntry (and 1080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // any other renderer-side nav initiations?). Double-check this for 1090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // correct behavior on interstitials -- we probably want to basically queue 1100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // any request for which GetVisibleURL != GetLastCommittedURL. 1110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch request_url_ = web_contents()->GetLastCommittedURL(); 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool is_main_frame = 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) request->GetRequestingHostname().GetOrigin() == request_url_.GetOrigin(); 1140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Don't re-add an existing request or one with a duplicate text request. 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool same_object = false; 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (ExistingRequest(request, requests_, &same_object) || 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExistingRequest(request, queued_requests_, &same_object) || 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExistingRequest(request, queued_frame_requests_, &same_object)) { 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!same_object) 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request->RequestFinished(); 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (bubble_showing_) { 126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (is_main_frame) { 127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) content::RecordAction( 128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::UserMetricsAction("PermissionBubbleRequestQueued")); 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) queued_requests_.push_back(request); 130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else { 131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) content::RecordAction( 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::UserMetricsAction("PermissionBubbleIFrameRequestQueued")); 133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) queued_frame_requests_.push_back(request); 134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (is_main_frame) { 139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) requests_.push_back(request); 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(gbillock): do we need to make default state a request property? 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) accept_states_.push_back(true); 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) content::RecordAction( 144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::UserMetricsAction("PermissionBubbleIFrameRequestQueued")); 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) queued_frame_requests_.push_back(request); 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (request->HasUserGesture()) 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ScheduleShowBubble(); 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void PermissionBubbleManager::CancelRequest(PermissionBubbleRequest* request) { 153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // First look in the queued requests, where we can simply delete the request 154010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // and go on. 155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) std::vector<PermissionBubbleRequest*>::iterator requests_iter; 156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (requests_iter = queued_requests_.begin(); 157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) requests_iter != queued_requests_.end(); 158010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) requests_iter++) { 159010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (*requests_iter == request) { 160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) (*requests_iter)->RequestFinished(); 161010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) queued_requests_.erase(requests_iter); 162010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 164010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) std::vector<bool>::iterator accepts_iter = accept_states_.begin(); 167010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (requests_iter = requests_.begin(), accepts_iter = accept_states_.begin(); 168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) requests_iter != requests_.end(); 169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) requests_iter++, accepts_iter++) { 170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (*requests_iter != request) 171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) continue; 172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // We can simply erase the current entry in the request table if we aren't 174010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // showing the dialog, or if we are showing it and it can accept the update. 175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool can_erase = !bubble_showing_ || 176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) !view_ || view_->CanAcceptRequestUpdate(); 177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (can_erase) { 178010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) (*requests_iter)->RequestFinished(); 179010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) requests_.erase(requests_iter); 180010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) accept_states_.erase(accepts_iter); 181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TriggerShowBubble(); // Will redraw the bubble if it is being shown. 182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 185010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Cancel the existing request and replace it with a dummy. 186010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) PermissionBubbleRequest* cancelled_request = 187010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) new CancelledRequest(*requests_iter); 188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) (*requests_iter)->RequestFinished(); 189010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) *requests_iter = cancelled_request; 190010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 191010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 192010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) NOTREACHED(); // Callers should not cancel requests that are not pending. 194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::SetView(PermissionBubbleView* view) { 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (view == view_) 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 200010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Disengage from the existing view if there is one. 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (view_ != NULL) { 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) view_->SetDelegate(NULL); 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) view_->Hide(); 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bubble_showing_ = false; 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) view_ = view; 208010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!view) 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 211010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) view->SetDelegate(this); 212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TriggerShowBubble(); 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 215010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void PermissionBubbleManager::DocumentOnLoadCompletedInMainFrame() { 2165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu request_url_has_loaded_ = true; 2175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // This is scheduled because while all calls to the browser have been 2185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // issued at DOMContentLoaded, they may be bouncing around in scheduled 2195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // callbacks finding the UI thread still. This makes sure we allow those 2205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // scheduled calls to AddRequest to complete before we show the page-load 2215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // permissions bubble. 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ScheduleShowBubble(); 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PermissionBubbleManager::DocumentLoadedInFrame( 226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch content::RenderFrameHost* render_frame_host) { 227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (request_url_has_loaded_) 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ScheduleShowBubble(); 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid PermissionBubbleManager::NavigationEntryCommitted( 2320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const content::LoadCommittedDetails& details) { 233010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // No permissions requests pending. 234010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (request_url_.is_empty()) 235010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 236010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // If we have navigated to a new url or reloaded the page... 238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // GetAsReferrer strips fragment and username/password, meaning 239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // the navigation is really to the same page. 240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if ((request_url_.GetAsReferrer() != 241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch web_contents()->GetLastCommittedURL().GetAsReferrer()) || 242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) details.type == content::NAVIGATION_TYPE_EXISTING_PAGE) { 2430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Kill off existing bubble and cancel any pending requests. 244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CancelPendingQueues(); 2450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FinalizeBubble(); 2460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 2480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 249010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void PermissionBubbleManager::WebContentsDestroyed() { 250010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // If the web contents has been destroyed, treat the bubble as cancelled. 251116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CancelPendingQueues(); 252c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch FinalizeBubble(); 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The WebContents is going away; be aggressively paranoid and delete 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // ourselves lest other parts of the system attempt to add permission bubbles 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // or use us otherwise during the destruction. 257010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) web_contents()->RemoveUserData(UserDataKey()); 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // That was the equivalent of "delete this". This object is now destroyed; 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // returning from this function is the only safe thing to do. 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::ToggleAccept(int request_index, bool new_value) { 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(request_index < static_cast<int>(accept_states_.size())); 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) accept_states_[request_index] = new_value; 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::SetCustomizationMode() { 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) customization_mode_ = true; 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (view_) 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) view_->Show(requests_, accept_states_, customization_mode_); 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::Accept() { 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<PermissionBubbleRequest*>::iterator requests_iter; 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<bool>::iterator accepts_iter = accept_states_.begin(); 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (requests_iter = requests_.begin(), accepts_iter = accept_states_.begin(); 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) requests_iter != requests_.end(); 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) requests_iter++, accepts_iter++) { 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (*accepts_iter) 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*requests_iter)->PermissionGranted(); 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*requests_iter)->PermissionDenied(); 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FinalizeBubble(); 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::Deny() { 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<PermissionBubbleRequest*>::iterator requests_iter; 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (requests_iter = requests_.begin(); 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) requests_iter != requests_.end(); 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) requests_iter++) { 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*requests_iter)->PermissionDenied(); 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FinalizeBubble(); 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::Closing() { 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<PermissionBubbleRequest*>::iterator requests_iter; 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (requests_iter = requests_.begin(); 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) requests_iter != requests_.end(); 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) requests_iter++) { 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*requests_iter)->Cancelled(); 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FinalizeBubble(); 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PermissionBubbleManager::ScheduleShowBubble() { 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::BrowserThread::PostTask( 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::BrowserThread::UI, 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&PermissionBubbleManager::TriggerShowBubble, 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) weak_factory_.GetWeakPtr())); 313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PermissionBubbleManager::TriggerShowBubble() { 316010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!view_) 317010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 318010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (bubble_showing_) 319010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 320010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!request_url_has_loaded_) 321010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (requests_.empty() && queued_requests_.empty() && 323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch queued_frame_requests_.empty()) { 324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 325116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (requests_.empty()) { 328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Queues containing a user-gesture-generated request have priority. 329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (HasUserGestureRequest(queued_requests_)) 330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) requests_.swap(queued_requests_); 331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else if (HasUserGestureRequest(queued_frame_requests_)) 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) requests_.swap(queued_frame_requests_); 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else if (queued_requests_.size()) 334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) requests_.swap(queued_requests_); 335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else 336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) requests_.swap(queued_frame_requests_); 337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Sets the default value for each request to be 'accept'. 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(leng): Currently all requests default to true. If that changes: 340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // a) Add additional accept_state queues to store default values. 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // b) Change the request API to provide the default value. 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) accept_states_.resize(requests_.size(), true); 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 344010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 345010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Note: this should appear above Show() for testing, since in that 346010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // case we may do in-line calling of finalization. 347010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bubble_showing_ = true; 348010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) view_->Show(requests_, accept_states_, customization_mode_); 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionBubbleManager::FinalizeBubble() { 352a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (view_) 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) view_->Hide(); 354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bubble_showing_ = false; 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<PermissionBubbleRequest*>::iterator requests_iter; 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (requests_iter = requests_.begin(); 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) requests_iter != requests_.end(); 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) requests_iter++) { 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*requests_iter)->RequestFinished(); 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) requests_.clear(); 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) accept_states_.clear(); 364116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (queued_requests_.size() || queued_frame_requests_.size()) 365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TriggerShowBubble(); 366116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch else 3670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch request_url_ = GURL(); 3680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 3690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 370116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid PermissionBubbleManager::CancelPendingQueues() { 3710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<PermissionBubbleRequest*>::iterator requests_iter; 3720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (requests_iter = queued_requests_.begin(); 3730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch requests_iter != queued_requests_.end(); 3740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch requests_iter++) { 3750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (*requests_iter)->RequestFinished(); 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 377116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (requests_iter = queued_frame_requests_.begin(); 378116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch requests_iter != queued_frame_requests_.end(); 379116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch requests_iter++) { 380116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch (*requests_iter)->RequestFinished(); 381116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 382116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch queued_requests_.clear(); 383116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch queued_frame_requests_.clear(); 3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool PermissionBubbleManager::ExistingRequest( 387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PermissionBubbleRequest* request, 388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::vector<PermissionBubbleRequest*>& queue, 389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool* same_object) { 390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CHECK(same_object); 391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *same_object = false; 392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::vector<PermissionBubbleRequest*>::const_iterator iter; 393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (iter = queue.begin(); iter != queue.end(); iter++) { 394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (*iter == request) { 395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *same_object = true; 396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if ((*iter)->GetMessageTextFragment() == 399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) request->GetMessageTextFragment() && 400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (*iter)->GetRequestingHostname() == request->GetRequestingHostname()) { 401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool PermissionBubbleManager::HasUserGestureRequest( 408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::vector<PermissionBubbleRequest*>& queue) { 409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::vector<PermissionBubbleRequest*>::const_iterator iter; 410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (iter = queue.begin(); iter != queue.end(); iter++) { 411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if ((*iter)->HasUserGesture()) 412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 416116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 417