|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include "nsQtNetworkManager.h" |
|
6 |
|
7 #include "nsCOMPtr.h" |
|
8 #include "nsThreadUtils.h" |
|
9 #include "nsINetworkLinkService.h" |
|
10 #include "nsIOService.h" |
|
11 #include "nsIObserverService.h" |
|
12 #include "nsIOService.h" |
|
13 |
|
14 #include <QHostInfo> |
|
15 #include <QHostAddress> |
|
16 #include <QTime> |
|
17 |
|
18 nsQtNetworkManager* nsQtNetworkManager::gQtNetworkManager = nullptr; |
|
19 |
|
20 void nsQtNetworkManager::create() |
|
21 { |
|
22 if (!gQtNetworkManager) { |
|
23 gQtNetworkManager = new nsQtNetworkManager(); |
|
24 connect(gQtNetworkManager, SIGNAL(openConnectionSignal()), |
|
25 gQtNetworkManager, SLOT(openSession()), |
|
26 Qt::BlockingQueuedConnection); |
|
27 connect(&gQtNetworkManager->networkConfigurationManager, |
|
28 SIGNAL(onlineStateChanged(bool)), gQtNetworkManager, |
|
29 SLOT(onlineStateChanged(bool))); |
|
30 } |
|
31 } |
|
32 |
|
33 void nsQtNetworkManager::destroy() |
|
34 { |
|
35 delete gQtNetworkManager; |
|
36 gQtNetworkManager = nullptr; |
|
37 } |
|
38 |
|
39 nsQtNetworkManager::nsQtNetworkManager(QObject* parent) |
|
40 : QObject(parent), networkSession(0) |
|
41 { |
|
42 mOnline = networkConfigurationManager.isOnline(); |
|
43 NS_ASSERTION(NS_IsMainThread(), "nsQtNetworkManager can only initiated in Main Thread"); |
|
44 } |
|
45 |
|
46 nsQtNetworkManager::~nsQtNetworkManager() |
|
47 { |
|
48 closeSession(); |
|
49 networkSession->deleteLater(); |
|
50 } |
|
51 |
|
52 bool |
|
53 nsQtNetworkManager::isOnline() |
|
54 { |
|
55 static bool sForceOnlineUSB = getenv("MOZ_MEEGO_NET_ONLINE") != 0; |
|
56 return sForceOnlineUSB || mOnline; |
|
57 } |
|
58 |
|
59 void |
|
60 nsQtNetworkManager::onlineStateChanged(bool online) |
|
61 { |
|
62 mOnline = online; |
|
63 } |
|
64 |
|
65 /* |
|
66 This function is called from different threads, we need to make sure that |
|
67 the attempt to create a network connection is done in the mainthread |
|
68 |
|
69 In case this function is called by another thread than the mainthread |
|
70 we emit a signal which is connected through "BlockingQueue"-Connection Type. |
|
71 |
|
72 This cause that the current thread is blocked and waiting for the result. |
|
73 |
|
74 Of course, in case this gets called from the mainthread we must not emit the signal, |
|
75 but call the slot directly. |
|
76 */ |
|
77 |
|
78 bool |
|
79 nsQtNetworkManager::openConnection(const QString& host) |
|
80 { |
|
81 // we are already online -> return true. |
|
82 if (isOnline()) { |
|
83 return true; |
|
84 } |
|
85 |
|
86 if (NS_IsMainThread()) { |
|
87 openSession(); |
|
88 } else { |
|
89 // jump to mainthread and do the work there |
|
90 Q_EMIT openConnectionSignal(); |
|
91 } |
|
92 |
|
93 // if its claiming its online -> send one resolve request ahead. |
|
94 // this is important because on mobile the first request can take up to 10 seconds |
|
95 // sending here one will help to avoid trouble and timeouts later |
|
96 if (isOnline()) { |
|
97 QHostInfo::fromName(host); |
|
98 } |
|
99 |
|
100 return isOnline(); |
|
101 } |
|
102 |
|
103 void |
|
104 nsQtNetworkManager::openSession() |
|
105 { |
|
106 if (mBlockTimer.isActive()) { |
|
107 // if openSession is called within 200 ms again, we forget this attempt since |
|
108 // its mostlike an automatic connection attempt which was not successful or canceled 200ms ago. |
|
109 // we reset the timer and start it again. |
|
110 |
|
111 // As example: Go in firefox mobile into AwesomeView, see that the icons are not always cached and |
|
112 // get loaded on the fly. Not having the 200 ms rule here would mean that instantly |
|
113 // after the user dismissed the one connection dialog once another |
|
114 // would get opened. The user will never be able to close / leave the view until each such attempt is gone through. |
|
115 |
|
116 // Basically 200 ms are working fine, its huge enough for automatic attempts to get covered and small enough to |
|
117 // still be able to react on direct user request. |
|
118 |
|
119 mBlockTimer.stop(); |
|
120 mBlockTimer.setSingleShot(true); |
|
121 mBlockTimer.start(200); |
|
122 return; |
|
123 } |
|
124 |
|
125 if (isOnline()) { |
|
126 return; |
|
127 } |
|
128 |
|
129 // this only means we did not shutdown before... |
|
130 // renew Session every time |
|
131 // fix/workaround for prestart bug |
|
132 if (networkSession) { |
|
133 networkSession->close(); |
|
134 networkSession->deleteLater(); |
|
135 } |
|
136 |
|
137 // renew always to react on changed Configurations |
|
138 networkConfigurationManager.updateConfigurations(); |
|
139 // go always with default configuration |
|
140 networkConfiguration = networkConfigurationManager.defaultConfiguration(); |
|
141 networkSession = new QNetworkSession(networkConfiguration); |
|
142 |
|
143 networkSession->open(); |
|
144 QTime current; |
|
145 current.start(); |
|
146 networkSession->waitForOpened(-1); |
|
147 |
|
148 if (current.elapsed() < 1000) { |
|
149 NS_WARNING("Connection Creation was to fast, something is not right."); |
|
150 } |
|
151 |
|
152 mBlockTimer.setSingleShot(true); |
|
153 mBlockTimer.start(200); |
|
154 } |
|
155 |
|
156 void |
|
157 nsQtNetworkManager::closeSession() |
|
158 { |
|
159 if (networkSession) { |
|
160 networkSession->close(); |
|
161 } |
|
162 } |