Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | /* |
michael@0 | 7 | * This implementation has support only for http requests. It is because the |
michael@0 | 8 | * spec has defined event streams only for http. HTTP is required because |
michael@0 | 9 | * this implementation uses some http headers: "Last-Event-ID", "Cache-Control" |
michael@0 | 10 | * and "Accept". |
michael@0 | 11 | */ |
michael@0 | 12 | |
michael@0 | 13 | #ifndef mozilla_dom_EventSource_h |
michael@0 | 14 | #define mozilla_dom_EventSource_h |
michael@0 | 15 | |
michael@0 | 16 | #include "mozilla/Attributes.h" |
michael@0 | 17 | #include "mozilla/DOMEventTargetHelper.h" |
michael@0 | 18 | #include "nsIObserver.h" |
michael@0 | 19 | #include "nsIStreamListener.h" |
michael@0 | 20 | #include "nsIChannelEventSink.h" |
michael@0 | 21 | #include "nsIInterfaceRequestor.h" |
michael@0 | 22 | #include "nsITimer.h" |
michael@0 | 23 | #include "nsIHttpChannel.h" |
michael@0 | 24 | #include "nsWeakReference.h" |
michael@0 | 25 | #include "nsDeque.h" |
michael@0 | 26 | #include "nsIUnicodeDecoder.h" |
michael@0 | 27 | |
michael@0 | 28 | class nsPIDOMWindow; |
michael@0 | 29 | |
michael@0 | 30 | namespace mozilla { |
michael@0 | 31 | |
michael@0 | 32 | class ErrorResult; |
michael@0 | 33 | |
michael@0 | 34 | namespace dom { |
michael@0 | 35 | |
michael@0 | 36 | class AsyncVerifyRedirectCallbackFwr; |
michael@0 | 37 | struct EventSourceInit; |
michael@0 | 38 | |
michael@0 | 39 | class EventSource : public DOMEventTargetHelper |
michael@0 | 40 | , public nsIObserver |
michael@0 | 41 | , public nsIStreamListener |
michael@0 | 42 | , public nsIChannelEventSink |
michael@0 | 43 | , public nsIInterfaceRequestor |
michael@0 | 44 | , public nsSupportsWeakReference |
michael@0 | 45 | { |
michael@0 | 46 | friend class AsyncVerifyRedirectCallbackFwr; |
michael@0 | 47 | |
michael@0 | 48 | public: |
michael@0 | 49 | EventSource(nsPIDOMWindow* aOwnerWindow); |
michael@0 | 50 | virtual ~EventSource(); |
michael@0 | 51 | NS_DECL_ISUPPORTS_INHERITED |
michael@0 | 52 | NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED( |
michael@0 | 53 | EventSource, DOMEventTargetHelper) |
michael@0 | 54 | |
michael@0 | 55 | NS_DECL_NSIOBSERVER |
michael@0 | 56 | NS_DECL_NSISTREAMLISTENER |
michael@0 | 57 | NS_DECL_NSIREQUESTOBSERVER |
michael@0 | 58 | NS_DECL_NSICHANNELEVENTSINK |
michael@0 | 59 | NS_DECL_NSIINTERFACEREQUESTOR |
michael@0 | 60 | |
michael@0 | 61 | // nsWrapperCache |
michael@0 | 62 | virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; |
michael@0 | 63 | |
michael@0 | 64 | // WebIDL |
michael@0 | 65 | nsPIDOMWindow* |
michael@0 | 66 | GetParentObject() const |
michael@0 | 67 | { |
michael@0 | 68 | return GetOwner(); |
michael@0 | 69 | } |
michael@0 | 70 | static already_AddRefed<EventSource> |
michael@0 | 71 | Constructor(const GlobalObject& aGlobal, const nsAString& aURL, |
michael@0 | 72 | const EventSourceInit& aEventSourceInitDict, |
michael@0 | 73 | ErrorResult& aRv); |
michael@0 | 74 | |
michael@0 | 75 | void GetUrl(nsAString& aURL) const |
michael@0 | 76 | { |
michael@0 | 77 | aURL = mOriginalURL; |
michael@0 | 78 | } |
michael@0 | 79 | bool WithCredentials() const |
michael@0 | 80 | { |
michael@0 | 81 | return mWithCredentials; |
michael@0 | 82 | } |
michael@0 | 83 | |
michael@0 | 84 | enum { |
michael@0 | 85 | CONNECTING = 0U, |
michael@0 | 86 | OPEN = 1U, |
michael@0 | 87 | CLOSED = 2U |
michael@0 | 88 | }; |
michael@0 | 89 | uint16_t ReadyState() const |
michael@0 | 90 | { |
michael@0 | 91 | return mReadyState; |
michael@0 | 92 | } |
michael@0 | 93 | |
michael@0 | 94 | IMPL_EVENT_HANDLER(open) |
michael@0 | 95 | IMPL_EVENT_HANDLER(message) |
michael@0 | 96 | IMPL_EVENT_HANDLER(error) |
michael@0 | 97 | void Close(); |
michael@0 | 98 | |
michael@0 | 99 | // Determine if preferences allow EventSource |
michael@0 | 100 | static bool PrefEnabled(JSContext* aCx = nullptr, JSObject* aGlobal = nullptr); |
michael@0 | 101 | |
michael@0 | 102 | virtual void DisconnectFromOwner() MOZ_OVERRIDE; |
michael@0 | 103 | |
michael@0 | 104 | protected: |
michael@0 | 105 | nsresult Init(nsISupports* aOwner, |
michael@0 | 106 | const nsAString& aURL, |
michael@0 | 107 | bool aWithCredentials); |
michael@0 | 108 | |
michael@0 | 109 | nsresult GetBaseURI(nsIURI **aBaseURI); |
michael@0 | 110 | |
michael@0 | 111 | nsresult SetupHttpChannel(); |
michael@0 | 112 | nsresult InitChannelAndRequestEventSource(); |
michael@0 | 113 | nsresult ResetConnection(); |
michael@0 | 114 | nsresult DispatchFailConnection(); |
michael@0 | 115 | nsresult SetReconnectionTimeout(); |
michael@0 | 116 | |
michael@0 | 117 | void AnnounceConnection(); |
michael@0 | 118 | void DispatchAllMessageEvents(); |
michael@0 | 119 | void ReestablishConnection(); |
michael@0 | 120 | void FailConnection(); |
michael@0 | 121 | |
michael@0 | 122 | nsresult Thaw(); |
michael@0 | 123 | nsresult Freeze(); |
michael@0 | 124 | |
michael@0 | 125 | static void TimerCallback(nsITimer *aTimer, void *aClosure); |
michael@0 | 126 | |
michael@0 | 127 | nsresult PrintErrorOnConsole(const char *aBundleURI, |
michael@0 | 128 | const char16_t *aError, |
michael@0 | 129 | const char16_t **aFormatStrings, |
michael@0 | 130 | uint32_t aFormatStringsLen); |
michael@0 | 131 | nsresult ConsoleError(); |
michael@0 | 132 | |
michael@0 | 133 | static NS_METHOD StreamReaderFunc(nsIInputStream *aInputStream, |
michael@0 | 134 | void *aClosure, |
michael@0 | 135 | const char *aFromRawSegment, |
michael@0 | 136 | uint32_t aToOffset, |
michael@0 | 137 | uint32_t aCount, |
michael@0 | 138 | uint32_t *aWriteCount); |
michael@0 | 139 | nsresult SetFieldAndClear(); |
michael@0 | 140 | nsresult ClearFields(); |
michael@0 | 141 | nsresult ResetEvent(); |
michael@0 | 142 | nsresult DispatchCurrentMessageEvent(); |
michael@0 | 143 | nsresult ParseCharacter(char16_t aChr); |
michael@0 | 144 | bool CheckCanRequestSrc(nsIURI* aSrc = nullptr); // if null, it tests mSrc |
michael@0 | 145 | nsresult CheckHealthOfRequestCallback(nsIRequest *aRequestCallback); |
michael@0 | 146 | nsresult OnRedirectVerifyCallback(nsresult result); |
michael@0 | 147 | |
michael@0 | 148 | nsCOMPtr<nsIURI> mSrc; |
michael@0 | 149 | |
michael@0 | 150 | nsString mLastEventID; |
michael@0 | 151 | uint32_t mReconnectionTime; // in ms |
michael@0 | 152 | |
michael@0 | 153 | struct Message { |
michael@0 | 154 | nsString mEventName; |
michael@0 | 155 | nsString mLastEventID; |
michael@0 | 156 | nsString mData; |
michael@0 | 157 | }; |
michael@0 | 158 | nsDeque mMessagesToDispatch; |
michael@0 | 159 | Message mCurrentMessage; |
michael@0 | 160 | |
michael@0 | 161 | /** |
michael@0 | 162 | * A simple state machine used to manage the event-source's line buffer |
michael@0 | 163 | * |
michael@0 | 164 | * PARSE_STATE_OFF -> PARSE_STATE_BEGIN_OF_STREAM |
michael@0 | 165 | * |
michael@0 | 166 | * PARSE_STATE_BEGIN_OF_STREAM -> PARSE_STATE_BOM_WAS_READ | |
michael@0 | 167 | * PARSE_STATE_CR_CHAR | |
michael@0 | 168 | * PARSE_STATE_BEGIN_OF_LINE | |
michael@0 | 169 | * PARSE_STATE_COMMENT | |
michael@0 | 170 | * PARSE_STATE_FIELD_NAME |
michael@0 | 171 | * |
michael@0 | 172 | * PARSE_STATE_BOM_WAS_READ -> PARSE_STATE_CR_CHAR | |
michael@0 | 173 | * PARSE_STATE_BEGIN_OF_LINE | |
michael@0 | 174 | * PARSE_STATE_COMMENT | |
michael@0 | 175 | * PARSE_STATE_FIELD_NAME |
michael@0 | 176 | * |
michael@0 | 177 | * PARSE_STATE_CR_CHAR -> PARSE_STATE_CR_CHAR | |
michael@0 | 178 | * PARSE_STATE_COMMENT | |
michael@0 | 179 | * PARSE_STATE_FIELD_NAME | |
michael@0 | 180 | * PARSE_STATE_BEGIN_OF_LINE |
michael@0 | 181 | * |
michael@0 | 182 | * PARSE_STATE_COMMENT -> PARSE_STATE_CR_CHAR | |
michael@0 | 183 | * PARSE_STATE_BEGIN_OF_LINE |
michael@0 | 184 | * |
michael@0 | 185 | * PARSE_STATE_FIELD_NAME -> PARSE_STATE_CR_CHAR | |
michael@0 | 186 | * PARSE_STATE_BEGIN_OF_LINE | |
michael@0 | 187 | * PARSE_STATE_FIRST_CHAR_OF_FIELD_VALUE |
michael@0 | 188 | * |
michael@0 | 189 | * PARSE_STATE_FIRST_CHAR_OF_FIELD_VALUE -> PARSE_STATE_FIELD_VALUE | |
michael@0 | 190 | * PARSE_STATE_CR_CHAR | |
michael@0 | 191 | * PARSE_STATE_BEGIN_OF_LINE |
michael@0 | 192 | * |
michael@0 | 193 | * PARSE_STATE_FIELD_VALUE -> PARSE_STATE_CR_CHAR | |
michael@0 | 194 | * PARSE_STATE_BEGIN_OF_LINE |
michael@0 | 195 | * |
michael@0 | 196 | * PARSE_STATE_BEGIN_OF_LINE -> PARSE_STATE_CR_CHAR | |
michael@0 | 197 | * PARSE_STATE_COMMENT | |
michael@0 | 198 | * PARSE_STATE_FIELD_NAME | |
michael@0 | 199 | * PARSE_STATE_BEGIN_OF_LINE |
michael@0 | 200 | * |
michael@0 | 201 | * Whenever the parser find an empty line or the end-of-file |
michael@0 | 202 | * it dispatches the stacked event. |
michael@0 | 203 | * |
michael@0 | 204 | */ |
michael@0 | 205 | enum ParserStatus { |
michael@0 | 206 | PARSE_STATE_OFF, |
michael@0 | 207 | PARSE_STATE_BEGIN_OF_STREAM, |
michael@0 | 208 | PARSE_STATE_BOM_WAS_READ, |
michael@0 | 209 | PARSE_STATE_CR_CHAR, |
michael@0 | 210 | PARSE_STATE_COMMENT, |
michael@0 | 211 | PARSE_STATE_FIELD_NAME, |
michael@0 | 212 | PARSE_STATE_FIRST_CHAR_OF_FIELD_VALUE, |
michael@0 | 213 | PARSE_STATE_FIELD_VALUE, |
michael@0 | 214 | PARSE_STATE_BEGIN_OF_LINE |
michael@0 | 215 | }; |
michael@0 | 216 | ParserStatus mStatus; |
michael@0 | 217 | |
michael@0 | 218 | bool mFrozen; |
michael@0 | 219 | bool mErrorLoadOnRedirect; |
michael@0 | 220 | bool mGoingToDispatchAllMessages; |
michael@0 | 221 | bool mWithCredentials; |
michael@0 | 222 | bool mWaitingForOnStopRequest; |
michael@0 | 223 | bool mInterrupted; |
michael@0 | 224 | |
michael@0 | 225 | // used while reading the input streams |
michael@0 | 226 | nsCOMPtr<nsIUnicodeDecoder> mUnicodeDecoder; |
michael@0 | 227 | nsresult mLastConvertionResult; |
michael@0 | 228 | nsString mLastFieldName; |
michael@0 | 229 | nsString mLastFieldValue; |
michael@0 | 230 | |
michael@0 | 231 | nsCOMPtr<nsILoadGroup> mLoadGroup; |
michael@0 | 232 | |
michael@0 | 233 | /** |
michael@0 | 234 | * The notification callbacks the channel had initially. |
michael@0 | 235 | * We want to forward things here as needed. |
michael@0 | 236 | */ |
michael@0 | 237 | nsCOMPtr<nsIInterfaceRequestor> mNotificationCallbacks; |
michael@0 | 238 | nsCOMPtr<nsIChannelEventSink> mChannelEventSink; |
michael@0 | 239 | |
michael@0 | 240 | nsCOMPtr<nsIHttpChannel> mHttpChannel; |
michael@0 | 241 | |
michael@0 | 242 | nsCOMPtr<nsITimer> mTimer; |
michael@0 | 243 | |
michael@0 | 244 | uint16_t mReadyState; |
michael@0 | 245 | nsString mOriginalURL; |
michael@0 | 246 | |
michael@0 | 247 | nsCOMPtr<nsIPrincipal> mPrincipal; |
michael@0 | 248 | nsString mOrigin; |
michael@0 | 249 | |
michael@0 | 250 | uint32_t mRedirectFlags; |
michael@0 | 251 | nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback; |
michael@0 | 252 | nsCOMPtr<nsIChannel> mNewRedirectChannel; |
michael@0 | 253 | |
michael@0 | 254 | // Event Source owner information: |
michael@0 | 255 | // - the script file name |
michael@0 | 256 | // - source code line number where the Event Source object was constructed. |
michael@0 | 257 | // - the ID of the inner window where the script lives. Note that this may not |
michael@0 | 258 | // be the same as the Event Source owner window. |
michael@0 | 259 | // These attributes are used for error reporting. |
michael@0 | 260 | nsString mScriptFile; |
michael@0 | 261 | uint32_t mScriptLine; |
michael@0 | 262 | uint64_t mInnerWindowID; |
michael@0 | 263 | |
michael@0 | 264 | private: |
michael@0 | 265 | EventSource(const EventSource& x); // prevent bad usage |
michael@0 | 266 | EventSource& operator=(const EventSource& x); |
michael@0 | 267 | }; |
michael@0 | 268 | |
michael@0 | 269 | } // namespace dom |
michael@0 | 270 | } // namespace mozilla |
michael@0 | 271 | |
michael@0 | 272 | #endif // mozilla_dom_EventSource_h |