1 // Copyright 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.
5 #include "ios/net/request_tracker.h"
7 #include "base/logging.h"
8 #import "ios/net/clients/crn_forwarding_network_client.h"
9 #import "ios/net/clients/crn_forwarding_network_client_factory.h"
15 // Reference to the single instance of the RequestTrackerFactory.
16 RequestTracker::RequestTrackerFactory* g_request_tracker_factory = nullptr;
18 // Array of network client factories that should be added to any new request
20 class GlobalNetworkClientFactories {
22 static GlobalNetworkClientFactories* GetInstance() {
23 if (!g_global_network_client_factories)
24 g_global_network_client_factories = new GlobalNetworkClientFactories;
25 return g_global_network_client_factories;
28 // Gets the factories.
29 NSArray* GetFactories() {
30 DCHECK(thread_checker_.CalledOnValidThread());
31 return factories_.get();
35 void AddFactory(CRNForwardingNetworkClientFactory* factory) {
36 DCHECK(thread_checker_.CalledOnValidThread());
37 // TODO(justincohen): Cast indexOfObject to work around Xcode beta bugs.
38 // Revisit in future betas where hopefully these types match again.
41 static_cast<NSInteger>([factories_ indexOfObject:factory]));
42 DCHECK(!IsSelectorOverriden(factory, @selector(clientHandlingRequest:)));
43 DCHECK(!IsSelectorOverriden(factory,
44 @selector(clientHandlingResponse:request:)));
45 DCHECK(!IsSelectorOverriden(
46 factory, @selector(clientHandlingRedirect:url:response:)));
47 [factories_ addObject:factory];
50 // Returns true if |factory| re-implements |selector|.
51 // Only used for debugging.
52 bool IsSelectorOverriden(CRNForwardingNetworkClientFactory* factory,
55 [factory methodForSelector:selector] !=
56 [CRNForwardingNetworkClientFactory instanceMethodForSelector:selector];
60 GlobalNetworkClientFactories() : factories_([[NSMutableArray alloc] init]) {}
62 base::scoped_nsobject<NSMutableArray> factories_;
63 base::ThreadChecker thread_checker_;
65 static GlobalNetworkClientFactories* g_global_network_client_factories;
68 GlobalNetworkClientFactories*
69 GlobalNetworkClientFactories::g_global_network_client_factories = nullptr;
73 RequestTracker::RequestTrackerFactory::~RequestTrackerFactory() {
77 void RequestTracker::SetRequestTrackerFactory(RequestTrackerFactory* factory) {
78 g_request_tracker_factory = factory;
82 bool RequestTracker::GetRequestTracker(NSURLRequest* request,
83 base::WeakPtr<RequestTracker>* tracker) {
86 DCHECK(!tracker->get());
87 if (!g_request_tracker_factory) {
90 return g_request_tracker_factory->GetRequestTracker(request, tracker);
93 void RequestTracker::AddNetworkClientFactory(
94 CRNForwardingNetworkClientFactory* factory) {
95 DCHECK(thread_checker_.CalledOnValidThread());
96 DCHECK([[factory clientClass]
97 isSubclassOfClass:[CRNForwardingNetworkClient class]]);
98 // Sanity check: We don't already have a factory of the type being added.
99 DCHECK([client_factories_ indexOfObjectPassingTest:^BOOL(id obj,
102 return [obj clientClass] == [factory clientClass];
104 [client_factories_ addObject:factory];
105 if ([factory requiresOrdering]) {
106 [client_factories_ sortUsingSelector:@selector(orderRelativeTo:)];
111 void RequestTracker::AddGlobalNetworkClientFactory(
112 CRNForwardingNetworkClientFactory* factory) {
113 GlobalNetworkClientFactories::GetInstance()->AddFactory(factory);
116 RequestTracker::RequestTracker()
117 : client_factories_([[NSMutableArray alloc] init]),
119 cache_mode_(CACHE_NORMAL),
120 weak_ptr_factory_(this) {
121 // RequestTracker can be created from the main thread and used from another
123 thread_checker_.DetachFromThread();
126 RequestTracker::~RequestTracker() {
129 base::WeakPtr<RequestTracker> RequestTracker::GetWeakPtr() {
130 return weak_ptr_factory_.GetWeakPtr();
133 void RequestTracker::InvalidateWeakPtrs() {
134 weak_ptr_factory_.InvalidateWeakPtrs();
137 void RequestTracker::Init() {
138 DCHECK(thread_checker_.CalledOnValidThread());
139 DCHECK(!initialized_);
141 for (CRNForwardingNetworkClientFactory* factory in
142 GlobalNetworkClientFactories::GetInstance()->GetFactories()) {
143 AddNetworkClientFactory(factory);
148 NSArray* RequestTracker::GlobalClientsHandlingAnyRequest() {
149 NSMutableArray* applicable_clients = [NSMutableArray array];
150 for (CRNForwardingNetworkClientFactory* factory in
151 GlobalNetworkClientFactories::GetInstance()->GetFactories()) {
152 CRNForwardingNetworkClient* client = [factory clientHandlingAnyRequest];
154 [applicable_clients addObject:client];
156 return applicable_clients;
159 NSArray* RequestTracker::ClientsHandlingAnyRequest() {
160 DCHECK(thread_checker_.CalledOnValidThread());
161 DCHECK(initialized_);
162 NSMutableArray* applicable_clients = [NSMutableArray array];
163 for (CRNForwardingNetworkClientFactory* factory in client_factories_.get()) {
164 CRNForwardingNetworkClient* client = [factory clientHandlingAnyRequest];
166 [applicable_clients addObject:client];
168 return applicable_clients;
171 NSArray* RequestTracker::ClientsHandlingRequest(const URLRequest& request) {
172 DCHECK(thread_checker_.CalledOnValidThread());
173 DCHECK(initialized_);
174 NSMutableArray* applicable_clients = [NSMutableArray array];
175 for (CRNForwardingNetworkClientFactory* factory in client_factories_.get()) {
176 CRNForwardingNetworkClient* client =
177 [factory clientHandlingRequest:request];
179 [applicable_clients addObject:client];
181 return applicable_clients;
184 NSArray* RequestTracker::ClientsHandlingRequestAndResponse(
185 const URLRequest& request,
186 NSURLResponse* response) {
187 DCHECK(thread_checker_.CalledOnValidThread());
188 DCHECK(initialized_);
189 NSMutableArray* applicable_clients = [NSMutableArray array];
190 for (CRNForwardingNetworkClientFactory* factory in client_factories_.get()) {
191 CRNForwardingNetworkClient* client =
192 [factory clientHandlingResponse:response request:request];
194 [applicable_clients addObject:client];
196 return applicable_clients;
199 NSArray* RequestTracker::ClientsHandlingRedirect(
200 const URLRequest& request,
202 NSURLResponse* redirect_response) {
203 DCHECK(thread_checker_.CalledOnValidThread());
204 DCHECK(initialized_);
205 NSMutableArray* applicable_clients = [NSMutableArray array];
206 for (CRNForwardingNetworkClientFactory* factory in client_factories_.get()) {
207 CRNForwardingNetworkClient* client =
208 [factory clientHandlingRedirect:request
210 response:redirect_response];
212 [applicable_clients addObject:client];
214 return applicable_clients;
217 RequestTracker::CacheMode RequestTracker::GetCacheMode() const {
218 DCHECK(thread_checker_.CalledOnValidThread());
222 void RequestTracker::SetCacheMode(RequestTracker::CacheMode mode) {
223 DCHECK(thread_checker_.CalledOnValidThread());