MockUiProvider.java revision 27e85f244604c8de53b76b135e0dd6f2bf3cad96
1/** 2 * Copyright (c) 2011, Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.mail.providers.protos.mock; 18 19import android.content.ContentProvider; 20import android.content.ContentValues; 21import android.database.Cursor; 22import android.database.MatrixCursor; 23import android.net.Uri; 24import android.os.Parcel; 25import android.provider.BaseColumns; 26import android.text.Html; 27 28import com.android.mail.providers.AccountCacheProvider; 29import com.android.mail.providers.Account; 30import com.android.mail.providers.UIProvider.AccountCapabilities; 31import com.android.mail.providers.UIProvider.AccountColumns; 32import com.android.mail.providers.UIProvider.AttachmentColumns; 33import com.android.mail.providers.UIProvider.ConversationColumns; 34import com.android.mail.providers.UIProvider.FolderCapabilities; 35import com.android.mail.providers.UIProvider.FolderColumns; 36import com.android.mail.providers.UIProvider.MessageColumns; 37import com.android.mail.providers.UIProvider.SettingsColumns; 38 39import com.google.common.annotations.VisibleForTesting; 40import com.google.common.collect.ImmutableList; 41import com.google.common.collect.ImmutableMap; 42import com.google.common.collect.Lists; 43import com.google.common.collect.Maps; 44 45import java.util.Date; 46import java.util.List; 47import java.util.Map; 48import java.util.Set; 49 50public final class MockUiProvider extends ContentProvider { 51 52 public static final String AUTHORITY = "com.android.mail.mockprovider"; 53 54 55 static final String BASE_URI_STRING = "content://" + AUTHORITY; 56 57 public static final int NUM_MOCK_ACCOUNTS = 2; 58 59 // A map of query result for uris 60 // TODO(pwestbro) read this map from an external 61 private static Map<String, List<Map<String, Object>>> MOCK_QUERY_RESULTS = Maps.newHashMap(); 62 63 64 public static void initializeMockProvider() { 65 ImmutableMap.Builder<String, List<Map<String, Object>>> builder = ImmutableMap.builder(); 66 67 // Add results for account list 68 final List<Map<String, Object>> accountList = Lists.newArrayList(); 69 Map<String, Object> accountDetailsMap0; 70 71 // Account 1 72 accountDetailsMap0 = createAccountDetailsMap(0, true); 73 74 accountList.add(accountDetailsMap0); 75 Uri accountUri1 = (Uri) accountDetailsMap0.get(AccountColumns.URI); 76 builder.put(accountUri1.toString(), ImmutableList.of(accountDetailsMap0)); 77 78 // Account 2 79 Map<String, Object> accountDetailsMap1 = createAccountDetailsMap(1, true); 80 accountList.add(accountDetailsMap1); 81 82 Uri accountUri2 = (Uri) accountDetailsMap1.get(AccountColumns.URI); 83 builder.put(accountUri2.toString(), ImmutableList.of(accountDetailsMap1)); 84 85 // Add the account list to the builder 86 builder.put(getAccountsUri().toString(), accountList); 87 88 Map<String, Object> folderDetailsMap0 = createFolderDetailsMap(0, "zero", true, 0, 2); 89 builder.put(folderDetailsMap0.get(FolderColumns.URI).toString(), 90 ImmutableList.of(folderDetailsMap0)); 91 builder.put( 92 folderDetailsMap0.get(FolderColumns.CHILD_FOLDERS_LIST_URI).toString(), 93 ImmutableList.of(createFolderDetailsMap(10, "zeroChild0", 0, 0), 94 createFolderDetailsMap(11, "zeroChild1", 0, 0))); 95 96 Map<String, Object> conv0 = createConversationDetailsMap("zeroConv0".hashCode(), 97 "zeroConv0", 1); 98 builder.put(conv0.get(ConversationColumns.URI).toString(), 99 ImmutableList.of(conv0)); 100 Map<String, Object> conv1 = createConversationDetailsMap("zeroConv1".hashCode(), 101 "zeroConv1", 1); 102 builder.put(conv1.get(ConversationColumns.URI).toString(), 103 ImmutableList.of(conv1)); 104 builder.put(folderDetailsMap0.get(FolderColumns.CONVERSATION_LIST_URI).toString(), 105 ImmutableList.of(conv0, conv1)); 106 107 Map<String, Object> message0 = createMessageDetailsMap("zeroConv0".hashCode(), "zeroConv0", 108 1, false); 109 builder.put(message0.get(MessageColumns.URI).toString(), ImmutableList.of(message0)); 110 builder.put(conv0.get(ConversationColumns.MESSAGE_LIST_URI).toString(), 111 ImmutableList.of(message0)); 112 builder.put(message0.get(MessageColumns.ATTACHMENT_LIST_URI).toString(), 113 ImmutableList.of(createAttachmentDetailsMap(0, "zero"))); 114 Map<String, Object> message1 = createMessageDetailsMap("zeroConv1".hashCode(), "zeroConv1", 115 1, false); 116 builder.put(message1.get(MessageColumns.URI).toString(), ImmutableList.of(message1)); 117 Map<String, Object> message1a = createMessageDetailsMap("zeroConv1a".hashCode(), "zeroConv1a", 118 2, false); 119 builder.put(message1a.get(MessageColumns.URI).toString(), ImmutableList.of(message1a)); 120 builder.put(conv1.get(ConversationColumns.MESSAGE_LIST_URI).toString(), 121 ImmutableList.of(message1, message1a)); 122 builder.put(message1.get(MessageColumns.ATTACHMENT_LIST_URI).toString(), 123 ImmutableList.of(createAttachmentDetailsMap(1, "one"))); 124 125 Map<String, Object> folderDetailsMap1 = createFolderDetailsMap(1, "one", 0, 0); 126 builder.put(folderDetailsMap1.get(FolderColumns.URI).toString(), 127 ImmutableList.of(folderDetailsMap1)); 128 builder.put(accountDetailsMap0.get(AccountColumns.FOLDER_LIST_URI).toString(), 129 ImmutableList.of(folderDetailsMap0, folderDetailsMap1)); 130 Map<String, Object> settings0 = createSettingsDetailsMap(folderDetailsMap0.get( 131 FolderColumns.URI).toString()); 132 builder.put(accountDetailsMap0.get(AccountColumns.SETTINGS_QUERY_URI).toString(), 133 ImmutableList.of(settings0)); 134 135 Map<String, Object> folderDetailsMap2 = createFolderDetailsMap(2, "two", 2, 2); 136 builder.put(folderDetailsMap2.get(FolderColumns.URI).toString(), 137 ImmutableList.of(folderDetailsMap2)); 138 Map<String, Object> folderDetailsMap3 = createFolderDetailsMap(3, "three", 0, 0); 139 builder.put(folderDetailsMap3.get(FolderColumns.URI).toString(), 140 ImmutableList.of(folderDetailsMap3)); 141 builder.put(accountDetailsMap1.get(AccountColumns.FOLDER_LIST_URI).toString(), 142 ImmutableList.of(folderDetailsMap2, folderDetailsMap3)); 143 Map<String, Object> settings1 = createSettingsDetailsMap(folderDetailsMap2.get( 144 FolderColumns.URI).toString()); 145 builder.put(accountDetailsMap1.get(AccountColumns.SETTINGS_QUERY_URI).toString(), 146 ImmutableList.of(settings1)); 147 148 Map<String, Object> conv2 = createConversationDetailsMap("zeroConv2".hashCode(), 149 "zeroConv2", 0); 150 builder.put(conv2.get(ConversationColumns.URI).toString(), 151 ImmutableList.of(conv2)); 152 Map<String, Object> conv3 = createConversationDetailsMap("zeroConv3".hashCode(), 153 "zeroConv3", 0); 154 builder.put(conv3.get(ConversationColumns.URI).toString(), 155 ImmutableList.of(conv3)); 156 builder.put(folderDetailsMap2.get(FolderColumns.CONVERSATION_LIST_URI).toString(), 157 ImmutableList.of(conv2, conv3)); 158 159 Map<String, Object> message2 = createMessageDetailsMap("zeroConv2".hashCode(), "zeroConv2", 160 0, true); 161 builder.put(message2.get(MessageColumns.URI).toString(), ImmutableList.of(message2)); 162 builder.put(conv2.get(ConversationColumns.MESSAGE_LIST_URI).toString(), 163 ImmutableList.of(message2)); 164 Map<String, Object> message3 = createMessageDetailsMap("zeroConv3".hashCode(), "zeroConv3", 165 0, true); 166 builder.put(message3.get(MessageColumns.URI).toString(), ImmutableList.of(message3)); 167 builder.put(conv3.get(ConversationColumns.MESSAGE_LIST_URI).toString(), 168 ImmutableList.of(message3)); 169 170 MOCK_QUERY_RESULTS = builder.build(); 171 } 172 173 private static Map<String, Object> createSettingsDetailsMap(String uri) { 174 Map<String, Object> settingsMap = Maps.newHashMap(); 175 settingsMap.put(SettingsColumns.DEFAULT_INBOX, uri); 176 return settingsMap; 177 } 178 179 private static Map<String, Object> createConversationDetailsMap(int conversationId, 180 String subject, int hasAttachments) { 181 final String conversationUri = "content://" + AUTHORITY + "/conversation/" + conversationId; 182 Map<String, Object> conversationMap = Maps.newHashMap(); 183 conversationMap.put(BaseColumns._ID, Long.valueOf(conversationId)); 184 conversationMap.put(ConversationColumns.URI, conversationUri); 185 conversationMap.put(ConversationColumns.MESSAGE_LIST_URI, conversationUri + "/getMessages"); 186 conversationMap.put(ConversationColumns.SUBJECT, "Conversation " + subject); 187 conversationMap.put(ConversationColumns.SNIPPET, "snippet"); 188 conversationMap.put(ConversationColumns.SENDER_INFO, 189 "account1@mock.com, account2@mock.com"); 190 conversationMap.put(ConversationColumns.DATE_RECEIVED_MS, new Date().getTime()); 191 conversationMap.put(ConversationColumns.HAS_ATTACHMENTS, hasAttachments); 192 conversationMap.put(ConversationColumns.NUM_MESSAGES, 1); 193 conversationMap.put(ConversationColumns.NUM_DRAFTS, 1); 194 conversationMap.put(ConversationColumns.SENDING_STATE, 1); 195 conversationMap.put(ConversationColumns.READ, 0); 196 conversationMap.put(ConversationColumns.STARRED, 0); 197 return conversationMap; 198 } 199 200 private static Map<String, Object> createMessageDetailsMap(int messageId, String subject, 201 int hasAttachments, boolean addReplyTo) { 202 final String messageUri = "content://" + AUTHORITY + "/message/" + messageId; 203 Map<String, Object> messageMap = Maps.newHashMap(); 204 messageMap.put(BaseColumns._ID, Long.valueOf(messageId)); 205 messageMap.put(MessageColumns.URI, messageUri); 206 messageMap.put(MessageColumns.SUBJECT, "Message " + subject); 207 messageMap.put(MessageColumns.SNIPPET, "SNIPPET"); 208 String html = "<html><body><b><i>This is some html!!!</i></b></body></html>"; 209 messageMap.put(MessageColumns.BODY_HTML, html); 210 messageMap.put(MessageColumns.BODY_TEXT, Html.fromHtml(html)); 211 messageMap.put(MessageColumns.HAS_ATTACHMENTS, hasAttachments); 212 messageMap.put(MessageColumns.DATE_RECEIVED_MS, new Date().getTime()); 213 messageMap.put(MessageColumns.ATTACHMENT_LIST_URI, messageUri + "/getAttachments"); 214 messageMap.put(MessageColumns.TO, "account1@mock.com, account2@mock.com"); 215 messageMap.put(MessageColumns.FROM, "fromaccount1@mock.com"); 216 if (addReplyTo) { 217 messageMap.put(MessageColumns.REPLY_TO, "replytofromaccount1@mock.com"); 218 } 219 return messageMap; 220 } 221 222 private static Map<String, Object> createAttachmentDetailsMap(int attachmentId, String name) { 223 Map<String, Object> attachmentMap = Maps.newHashMap(); 224 attachmentMap.put(BaseColumns._ID, Long.valueOf(attachmentId)); 225 attachmentMap.put(AttachmentColumns.NAME, "Attachment " + name); 226 attachmentMap.put(AttachmentColumns.URI, 227 "attachmentUri/" + attachmentMap.get(AttachmentColumns.NAME)); 228 return attachmentMap; 229 } 230 231 private static Map<String, Object> createFolderDetailsMap(int folderId, String name, 232 int unread, int total) { 233 return createFolderDetailsMap(folderId, name, false, unread, total); 234 } 235 236 private static Map<String, Object> createFolderDetailsMap(int folderId, String name, 237 boolean hasChildren, int unread, int total) { 238 final String folderUri = "content://" + AUTHORITY + "/folder/" + folderId; 239 Map<String, Object> folderMap = Maps.newHashMap(); 240 folderMap.put(BaseColumns._ID, Long.valueOf(folderId)); 241 folderMap.put(FolderColumns.URI, folderUri); 242 folderMap.put(FolderColumns.NAME, "Folder " + name); 243 folderMap.put(FolderColumns.HAS_CHILDREN, new Integer(hasChildren ? 1 : 0)); 244 folderMap.put(FolderColumns.CONVERSATION_LIST_URI, folderUri + "/getConversations"); 245 folderMap.put(FolderColumns.CHILD_FOLDERS_LIST_URI, folderUri + "/getChildFolders"); 246 folderMap.put(FolderColumns.CAPABILITIES, 247 Long.valueOf( 248 FolderCapabilities.SYNCABLE | 249 FolderCapabilities.PARENT | 250 FolderCapabilities.CAN_HOLD_MAIL | 251 FolderCapabilities.CAN_ACCEPT_MOVED_MESSAGES)); 252 folderMap.put(FolderColumns.UNREAD_COUNT, unread); 253 folderMap.put(FolderColumns.TOTAL_COUNT, total); 254 folderMap.put(FolderColumns.SYNC_STATUS, 0); 255 folderMap.put(FolderColumns.LAST_SYNC_RESULT, 0); 256 return folderMap; 257 } 258 259 // Temporarily made this public to allow the Gmail accounts to use the mock ui provider uris 260 public static Map<String, Object> createAccountDetailsMap(int accountId, boolean cacheMap) { 261 final String accountUri = getMockAccountUri(accountId); 262 Map<String, Object> accountMap = Maps.newHashMap(); 263 accountMap.put(BaseColumns._ID, Long.valueOf(accountId)); 264 accountMap.put(AccountColumns.NAME, "account" + accountId + "@mockuiprovider.com"); 265 accountMap.put(AccountColumns.PROVIDER_VERSION, Long.valueOf(1)); 266 accountMap.put(AccountColumns.URI, Uri.parse(accountUri)); 267 accountMap.put(AccountColumns.CAPABILITIES, 268 Integer.valueOf( 269 AccountCapabilities.SYNCABLE_FOLDERS | 270 AccountCapabilities.REPORT_SPAM | 271 AccountCapabilities.ARCHIVE | 272 AccountCapabilities.MUTE | 273 AccountCapabilities.SERVER_SEARCH | 274 AccountCapabilities.FOLDER_SERVER_SEARCH | 275 AccountCapabilities.SANITIZED_HTML | 276 AccountCapabilities.DRAFT_SYNCHRONIZATION | 277 AccountCapabilities.MULTIPLE_FROM_ADDRESSES | 278 AccountCapabilities.SMART_REPLY | 279 AccountCapabilities.LOCAL_SEARCH | 280 AccountCapabilities.THREADED_CONVERSATIONS | 281 AccountCapabilities.MULTIPLE_FOLDERS_PER_CONV)); 282 accountMap.put(AccountColumns.FOLDER_LIST_URI, Uri.parse(accountUri + "/folders")); 283 accountMap.put(AccountColumns.SEARCH_URI, Uri.parse(accountUri + "/search")); 284 accountMap.put(AccountColumns.ACCOUNT_FROM_ADDRESSES_URI, 285 Uri.parse(accountUri + "/fromAddresses")); 286 accountMap.put(AccountColumns.SAVE_DRAFT_URI, Uri.parse(accountUri + "/saveDraft")); 287 accountMap.put(AccountColumns.SEND_MAIL_URI, Uri.parse(accountUri + "/sendMail")); 288 accountMap.put(AccountColumns.EXPUNGE_MESSAGE_URI, 289 Uri.parse(accountUri + "/expungeMessage")); 290 accountMap.put(AccountColumns.UNDO_URI, Uri.parse(accountUri + "/undo")); 291 accountMap.put(AccountColumns.SETTINGS_INTENT_URI, Uri.parse("http://www.google.com")); 292 accountMap.put(AccountColumns.SETTINGS_QUERY_URI, Uri.parse(accountUri + "/settings")); 293 accountMap.put(AccountColumns.HELP_INTENT_URI, Uri.parse("http://www.google.com")); 294 accountMap.put(AccountColumns.SYNC_STATUS, 0); 295 accountMap.put(AccountColumns.COMPOSE_URI, Uri.parse(accountUri + "/compose")); 296 accountMap.put(AccountColumns.RECENT_FOLDER_LIST_URI, 297 Uri.parse(accountUri + "/recentFolderListUri")); 298 if (cacheMap) { 299 addAccountInfoToAccountCache(accountMap); 300 } 301 return accountMap; 302 } 303 304 public static String getMockAccountUri(int accountId) { 305 return "content://" + AUTHORITY + "/account/" + accountId; 306 } 307 308 @Override 309 public boolean onCreate() { 310 return true; 311 } 312 313 @Override 314 public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs, 315 String sortOrder) { 316 317 // TODO (pwestbro): respect the projection that is specified by the caller 318 319 final List<Map<String, Object>> queryResults = 320 MOCK_QUERY_RESULTS.get(url.toString()); 321 322 if (queryResults != null && queryResults.size() > 0) { 323 // Get the projection. If there are rows in the result set, pick the first item to 324 // generate the projection 325 // TODO (pwestbro): handle the case where we want to return an empty result.\ 326 if (projection == null) { 327 Set<String> keys = queryResults.get(0).keySet(); 328 projection = keys.toArray(new String[keys.size()]); 329 } 330 MatrixCursor matrixCursor = new MatrixCursor(projection, queryResults.size()); 331 332 for (Map<String, Object> queryResult : queryResults) { 333 MatrixCursor.RowBuilder rowBuilder = matrixCursor.newRow(); 334 335 for (String key : projection) { 336 rowBuilder.add(queryResult.get(key)); 337 } 338 } 339 return matrixCursor; 340 } 341 342 return null; 343 } 344 345 @Override 346 public Uri insert(Uri url, ContentValues values) { 347 return url; 348 } 349 350 @Override 351 public int update(Uri url, ContentValues values, String selection, 352 String[] selectionArgs) { 353 return 0; 354 } 355 356 @Override 357 public int delete(Uri url, String selection, String[] selectionArgs) { 358 return 0; 359 } 360 361 @Override 362 public String getType(Uri uri) { 363 return null; 364 } 365 366 @VisibleForTesting 367 static Uri getAccountsUri() { 368 // TODO: this should probably return a different specific to the mock account list 369 return Uri.parse(BASE_URI_STRING + "/"); 370 } 371 372 private static void addAccountInfoToAccountCache(Map<String, Object> accountInfo) { 373 final Parcel dest = Parcel.obtain(); 374 375 dest.writeString((String) accountInfo.get(AccountColumns.NAME)); 376 dest.writeString("mock"); 377 dest.writeInt(0); 378 dest.writeParcelable((Uri) accountInfo.get(AccountColumns.URI), 0); 379 dest.writeInt((Integer) accountInfo.get(AccountColumns.CAPABILITIES)); 380 dest.writeParcelable((Uri) accountInfo.get(AccountColumns.FOLDER_LIST_URI), 0); 381 dest.writeParcelable((Uri) accountInfo.get(AccountColumns.SEARCH_URI), 0); 382 dest.writeParcelable((Uri) accountInfo.get(AccountColumns.ACCOUNT_FROM_ADDRESSES_URI), 0); 383 dest.writeParcelable((Uri) accountInfo.get(AccountColumns.SAVE_DRAFT_URI), 0); 384 dest.writeParcelable((Uri) accountInfo.get(AccountColumns.SEND_MAIL_URI), 0); 385 dest.writeParcelable((Uri) accountInfo.get(AccountColumns.EXPUNGE_MESSAGE_URI), 0); 386 dest.writeParcelable((Uri) accountInfo.get(AccountColumns.UNDO_URI), 0); 387 dest.writeParcelable((Uri) accountInfo.get(AccountColumns.SETTINGS_INTENT_URI), 0); 388 dest.writeParcelable((Uri)accountInfo.get(AccountColumns.SETTINGS_QUERY_URI), 0); 389 dest.writeParcelable((Uri) accountInfo.get(AccountColumns.HELP_INTENT_URI), 0); 390 dest.writeInt((Integer) accountInfo.get(AccountColumns.SYNC_STATUS)); 391 dest.writeParcelable((Uri) accountInfo.get(AccountColumns.COMPOSE_URI), 0); 392 dest.writeString((String) accountInfo.get(AccountColumns.MIME_TYPE)); 393 dest.writeParcelable((Uri) accountInfo.get(AccountColumns.RECENT_FOLDER_LIST_URI), 0); 394 dest.setDataPosition(0); 395 final Account account = new Account(dest); 396 AccountCacheProvider.addAccount(account); 397 } 398} 399 400