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 // This file implements a mock location provider and the factory functions for 6 // various ways of creating it. 7 8 #include "content/browser/geolocation/mock_location_provider.h" 9 10 #include "base/bind.h" 11 #include "base/bind_helpers.h" 12 #include "base/compiler_specific.h" 13 #include "base/logging.h" 14 #include "base/memory/weak_ptr.h" 15 #include "base/message_loop/message_loop.h" 16 #include "base/message_loop/message_loop_proxy.h" 17 18 namespace content { 19 MockLocationProvider* MockLocationProvider::instance_ = NULL; 20 21 MockLocationProvider::MockLocationProvider(MockLocationProvider** self_ref) 22 : state_(STOPPED), 23 is_permission_granted_(false), 24 self_ref_(self_ref), 25 provider_loop_(base::MessageLoopProxy::current()) { 26 CHECK(self_ref_); 27 CHECK(*self_ref_ == NULL); 28 *self_ref_ = this; 29 } 30 31 MockLocationProvider::~MockLocationProvider() { 32 CHECK(*self_ref_ == this); 33 *self_ref_ = NULL; 34 } 35 36 void MockLocationProvider::HandlePositionChanged(const Geoposition& position) { 37 if (provider_loop_->BelongsToCurrentThread()) { 38 // The location arbitrator unit tests rely on this method running 39 // synchronously. 40 position_ = position; 41 NotifyCallback(position_); 42 } else { 43 provider_loop_->PostTask( 44 FROM_HERE, 45 base::Bind(&MockLocationProvider::HandlePositionChanged, 46 base::Unretained(this), position)); 47 } 48 } 49 50 bool MockLocationProvider::StartProvider(bool high_accuracy) { 51 state_ = high_accuracy ? HIGH_ACCURACY : LOW_ACCURACY; 52 return true; 53 } 54 55 void MockLocationProvider::StopProvider() { 56 state_ = STOPPED; 57 } 58 59 void MockLocationProvider::GetPosition(Geoposition* position) { 60 *position = position_; 61 } 62 63 void MockLocationProvider::OnPermissionGranted() { 64 is_permission_granted_ = true; 65 } 66 67 // Mock location provider that automatically calls back its client at most 68 // once, when StartProvider or OnPermissionGranted is called. Use 69 // |requires_permission_to_start| to select which event triggers the callback. 70 class AutoMockLocationProvider : public MockLocationProvider { 71 public: 72 AutoMockLocationProvider(bool has_valid_location, 73 bool requires_permission_to_start) 74 : MockLocationProvider(&instance_), 75 weak_factory_(this), 76 requires_permission_to_start_(requires_permission_to_start), 77 listeners_updated_(false) { 78 if (has_valid_location) { 79 position_.accuracy = 3; 80 position_.latitude = 4.3; 81 position_.longitude = -7.8; 82 // Webkit compares the timestamp to wall clock time, so we need it to be 83 // contemporary. 84 position_.timestamp = base::Time::Now(); 85 } else { 86 position_.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; 87 } 88 } 89 virtual bool StartProvider(bool high_accuracy) OVERRIDE { 90 MockLocationProvider::StartProvider(high_accuracy); 91 if (!requires_permission_to_start_) { 92 UpdateListenersIfNeeded(); 93 } 94 return true; 95 } 96 97 virtual void OnPermissionGranted() OVERRIDE { 98 MockLocationProvider::OnPermissionGranted(); 99 if (requires_permission_to_start_) { 100 UpdateListenersIfNeeded(); 101 } 102 } 103 104 void UpdateListenersIfNeeded() { 105 if (!listeners_updated_) { 106 listeners_updated_ = true; 107 base::MessageLoop::current()->PostTask( 108 FROM_HERE, 109 base::Bind(&MockLocationProvider::HandlePositionChanged, 110 weak_factory_.GetWeakPtr(), 111 position_)); 112 } 113 } 114 115 base::WeakPtrFactory<MockLocationProvider> weak_factory_; 116 const bool requires_permission_to_start_; 117 bool listeners_updated_; 118 }; 119 120 LocationProvider* NewMockLocationProvider() { 121 return new MockLocationProvider(&MockLocationProvider::instance_); 122 } 123 124 LocationProvider* NewAutoSuccessMockLocationProvider() { 125 return new AutoMockLocationProvider(true, false); 126 } 127 128 LocationProvider* NewAutoFailMockLocationProvider() { 129 return new AutoMockLocationProvider(false, false); 130 } 131 132 LocationProvider* NewAutoSuccessMockNetworkLocationProvider() { 133 return new AutoMockLocationProvider(true, true); 134 } 135 136 } // namespace content 137