Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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 file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #ifndef mozilla_system_volumecommand_h__
6 #define mozilla_system_volumecommand_h__
8 #include "nsString.h"
9 #include "nsISupportsImpl.h"
10 #include "mozilla/RefPtr.h"
11 #include <algorithm>
12 #include <vold/ResponseCode.h>
14 namespace mozilla {
15 namespace system {
17 class Volume;
18 class VolumeCommand;
20 /***************************************************************************
21 *
22 * The VolumeResponseCallback class is an abstract base class. The ResponseReceived
23 * method will be called for each response received.
24 *
25 * Depending on the command, there may be multiple responses for the
26 * command. Done() will return true if this is the last response.
27 *
28 * The responses from vold are all of the form:
29 *
30 * <ResponseCode> <String>
31 *
32 * Valid Response codes can be found in the vold/ResponseCode.h header.
33 *
34 ***************************************************************************/
36 class VolumeResponseCallback
37 {
38 protected:
39 virtual ~VolumeResponseCallback() {}
41 public:
42 NS_INLINE_DECL_REFCOUNTING(VolumeResponseCallback)
43 VolumeResponseCallback()
44 : mResponseCode(0), mPending(false) {}
46 bool Done() const
47 {
48 // Response codes from the 200, 400, and 500 series all indicated that
49 // the command has completed.
51 return (mResponseCode >= ResponseCode::CommandOkay)
52 && (mResponseCode < ResponseCode::UnsolicitedInformational);
53 }
55 bool WasSuccessful() const
56 {
57 return mResponseCode == ResponseCode::CommandOkay;
58 }
60 bool IsPending() const { return mPending; }
61 int ResponseCode() const { return mResponseCode; }
62 const nsCString &ResponseStr() const { return mResponseStr; }
64 protected:
65 virtual void ResponseReceived(const VolumeCommand* aCommand) = 0;
67 private:
68 friend class VolumeCommand; // Calls HandleResponse and SetPending
70 void HandleResponse(const VolumeCommand* aCommand,
71 int aResponseCode,
72 nsACString& aResponseStr)
73 {
74 mResponseCode = aResponseCode;
75 #if ANDROID_VERSION >= 17
76 // There's a sequence number here that we don't care about
77 // We expect it to be 0. See VolumeCommand::SetCmd
78 mResponseStr = Substring(aResponseStr, 2);
79 #else
80 mResponseStr = aResponseStr;
81 #endif
82 if (mResponseCode >= ResponseCode::CommandOkay) {
83 // This is a final response.
84 mPending = false;
85 }
86 ResponseReceived(aCommand);
87 }
89 void SetPending(bool aPending) { mPending = aPending; }
91 int mResponseCode; // The response code parsed from vold
92 nsCString mResponseStr; // The rest of the line.
93 bool mPending; // Waiting for response?
94 };
96 /***************************************************************************
97 *
98 * The VolumeCommand class is an abstract base class used to encapsulate
99 * volume commands send to vold.
100 *
101 * See VolumeManager.h for a list of the volume commands.
102 *
103 * Commands sent to vold need an explicit null character so we add one
104 * to the command to ensure that it's included in the length.
105 *
106 * All of these commands are asynchronous in nature, and the
107 * ResponseReceived callback will be called when a response is available.
108 *
109 ***************************************************************************/
111 class VolumeCommand
112 {
113 protected:
114 virtual ~VolumeCommand() {}
116 public:
117 NS_INLINE_DECL_REFCOUNTING(VolumeCommand)
119 VolumeCommand(VolumeResponseCallback* aCallback)
120 : mBytesConsumed(0),
121 mCallback(aCallback)
122 {
123 SetCmd(NS_LITERAL_CSTRING(""));
124 }
126 VolumeCommand(const nsACString& aCommand, VolumeResponseCallback* aCallback)
127 : mBytesConsumed(0),
128 mCallback(aCallback)
129 {
130 SetCmd(aCommand);
131 }
133 void SetCmd(const nsACString& aCommand)
134 {
135 mCmd.Truncate();
136 #if ANDROID_VERSION >= 17
137 // JB requires a sequence number at the beginning of messages.
138 // It doesn't matter what we use, so we use 0.
139 mCmd = "0 ";
140 #endif
141 mCmd.Append(aCommand);
142 // Add a null character. We want this to be included in the length since
143 // vold uses it to determine the end of the command.
144 mCmd.Append('\0');
145 }
147 const char* CmdStr() const { return mCmd.get(); }
148 const char* Data() const { return mCmd.Data() + mBytesConsumed; }
149 size_t BytesConsumed() const { return mBytesConsumed; }
151 size_t BytesRemaining() const
152 {
153 return mCmd.Length() - std::min(mCmd.Length(), mBytesConsumed);
154 }
156 void ConsumeBytes(size_t aNumBytes)
157 {
158 mBytesConsumed += std::min(BytesRemaining(), aNumBytes);
159 }
161 private:
162 friend class VolumeManager; // Calls SetPending & HandleResponse
164 void SetPending(bool aPending)
165 {
166 if (mCallback) {
167 mCallback->SetPending(aPending);
168 }
169 }
171 void HandleResponse(int aResponseCode, nsACString& aResponseStr)
172 {
173 if (mCallback) {
174 mCallback->HandleResponse(this, aResponseCode, aResponseStr);
175 }
176 }
178 nsCString mCmd; // Command being sent
179 size_t mBytesConsumed; // How many bytes have been sent
181 // Called when a response to the command is received.
182 RefPtr<VolumeResponseCallback> mCallback;
183 };
185 class VolumeActionCommand : public VolumeCommand
186 {
187 public:
188 VolumeActionCommand(Volume* aVolume, const char* aAction,
189 const char* aExtraArgs, VolumeResponseCallback* aCallback);
191 private:
192 RefPtr<Volume> mVolume;
193 };
195 class VolumeListCommand : public VolumeCommand
196 {
197 public:
198 VolumeListCommand(VolumeResponseCallback* aCallback);
199 };
201 } // system
202 } // mozilla
204 #endif // mozilla_system_volumecommand_h__