Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(299)

Side by Side Diff: content/browser/accessibility/browser_accessibility_cocoa.mm

Issue 17261008: Fix crash when system retains an accessibility object. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <execinfo.h> 5 #include <execinfo.h>
6 6
7 #import "content/browser/accessibility/browser_accessibility_cocoa.h" 7 #import "content/browser/accessibility/browser_accessibility_cocoa.h"
8 8
9 #include <map> 9 #include <map>
10 10
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 337
338 - (id)initWithObject:(BrowserAccessibility*)accessibility 338 - (id)initWithObject:(BrowserAccessibility*)accessibility
339 delegate:(id<BrowserAccessibilityDelegateCocoa>)delegate { 339 delegate:(id<BrowserAccessibilityDelegateCocoa>)delegate {
340 if ((self = [super init])) { 340 if ((self = [super init])) {
341 browserAccessibility_ = accessibility; 341 browserAccessibility_ = accessibility;
342 delegate_ = delegate; 342 delegate_ = delegate;
343 } 343 }
344 return self; 344 return self;
345 } 345 }
346 346
347 // Deletes our associated BrowserAccessibilityMac. 347 - (void)detach {
348 - (void)dealloc {
349 if (browserAccessibility_) { 348 if (browserAccessibility_) {
350 NSAccessibilityUnregisterUniqueIdForUIElement(self); 349 NSAccessibilityUnregisterUniqueIdForUIElement(self);
351 delete browserAccessibility_;
352 browserAccessibility_ = NULL; 350 browserAccessibility_ = NULL;
353 } 351 }
354
355 [super dealloc];
356 } 352 }
357 353
358 - (NSString*)accessKey { 354 - (NSString*)accessKey {
359 return NSStringForStringAttribute( 355 return NSStringForStringAttribute(
360 browserAccessibility_->string_attributes(), 356 browserAccessibility_->string_attributes(),
361 AccessibilityNodeData::ATTR_ACCESS_KEY); 357 AccessibilityNodeData::ATTR_ACCESS_KEY);
362 } 358 }
363 359
364 - (NSNumber*)ariaAtomic { 360 - (NSNumber*)ariaAtomic {
365 bool boolValue = false; 361 bool boolValue = false;
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after
990 return [delegate_ window]; 986 return [delegate_ window];
991 } 987 }
992 988
993 - (NSString*)methodNameForAttribute:(NSString*)attribute { 989 - (NSString*)methodNameForAttribute:(NSString*)attribute {
994 return [attributeToMethodNameMap objectForKey:attribute]; 990 return [attributeToMethodNameMap objectForKey:attribute];
995 } 991 }
996 992
997 // Returns the accessibility value for the given attribute. If the value isn't 993 // Returns the accessibility value for the given attribute. If the value isn't
998 // supported this will return nil. 994 // supported this will return nil.
999 - (id)accessibilityAttributeValue:(NSString*)attribute { 995 - (id)accessibilityAttributeValue:(NSString*)attribute {
996 if (!browserAccessibility_)
997 return nil;
998
1000 SEL selector = 999 SEL selector =
1001 NSSelectorFromString([self methodNameForAttribute:attribute]); 1000 NSSelectorFromString([self methodNameForAttribute:attribute]);
1002 if (selector) 1001 if (selector)
1003 return [self performSelector:selector]; 1002 return [self performSelector:selector];
1004 1003
1005 // TODO(dtseng): refactor remaining attributes. 1004 // TODO(dtseng): refactor remaining attributes.
1006 int selStart, selEnd; 1005 int selStart, selEnd;
1007 if (browserAccessibility_->GetIntAttribute( 1006 if (browserAccessibility_->GetIntAttribute(
1008 AccessibilityNodeData::ATTR_TEXT_SEL_START, &selStart) && 1007 AccessibilityNodeData::ATTR_TEXT_SEL_START, &selStart) &&
1009 browserAccessibility_-> 1008 browserAccessibility_->
(...skipping 19 matching lines...) Expand all
1029 return [NSValue valueWithRange:NSMakeRange(selStart, selLength)]; 1028 return [NSValue valueWithRange:NSMakeRange(selStart, selLength)];
1030 } 1029 }
1031 } 1030 }
1032 return nil; 1031 return nil;
1033 } 1032 }
1034 1033
1035 // Returns the accessibility value for the given attribute and parameter. If the 1034 // Returns the accessibility value for the given attribute and parameter. If the
1036 // value isn't supported this will return nil. 1035 // value isn't supported this will return nil.
1037 - (id)accessibilityAttributeValue:(NSString*)attribute 1036 - (id)accessibilityAttributeValue:(NSString*)attribute
1038 forParameter:(id)parameter { 1037 forParameter:(id)parameter {
1038 if (!browserAccessibility_)
1039 return nil;
1040
1039 const std::vector<int32>& line_breaks = browserAccessibility_->line_breaks(); 1041 const std::vector<int32>& line_breaks = browserAccessibility_->line_breaks();
1040 int len = static_cast<int>(browserAccessibility_->value().size()); 1042 int len = static_cast<int>(browserAccessibility_->value().size());
1041 1043
1042 if ([attribute isEqualToString: 1044 if ([attribute isEqualToString:
1043 NSAccessibilityStringForRangeParameterizedAttribute]) { 1045 NSAccessibilityStringForRangeParameterizedAttribute]) {
1044 NSRange range = [(NSValue*)parameter rangeValue]; 1046 NSRange range = [(NSValue*)parameter rangeValue];
1045 return base::SysUTF16ToNSString( 1047 return base::SysUTF16ToNSString(
1046 browserAccessibility_->value().substr(range.location, range.length)); 1048 browserAccessibility_->value().substr(range.location, range.length));
1047 } 1049 }
1048 1050
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1136 [attribute isEqualTo: 1138 [attribute isEqualTo:
1137 NSAccessibilityStyleRangeForIndexParameterizedAttribute]) { 1139 NSAccessibilityStyleRangeForIndexParameterizedAttribute]) {
1138 return nil; 1140 return nil;
1139 } 1141 }
1140 return nil; 1142 return nil;
1141 } 1143 }
1142 1144
1143 // Returns an array of parameterized attributes names that this object will 1145 // Returns an array of parameterized attributes names that this object will
1144 // respond to. 1146 // respond to.
1145 - (NSArray*)accessibilityParameterizedAttributeNames { 1147 - (NSArray*)accessibilityParameterizedAttributeNames {
1148 if (!browserAccessibility_)
1149 return nil;
1150
1146 if ([[self role] isEqualToString:NSAccessibilityTableRole] || 1151 if ([[self role] isEqualToString:NSAccessibilityTableRole] ||
1147 [[self role] isEqualToString:NSAccessibilityGridRole]) { 1152 [[self role] isEqualToString:NSAccessibilityGridRole]) {
1148 return [NSArray arrayWithObjects: 1153 return [NSArray arrayWithObjects:
1149 NSAccessibilityCellForColumnAndRowParameterizedAttribute, 1154 NSAccessibilityCellForColumnAndRowParameterizedAttribute,
1150 nil]; 1155 nil];
1151 } 1156 }
1152 if ([[self role] isEqualToString:NSAccessibilityTextFieldRole] || 1157 if ([[self role] isEqualToString:NSAccessibilityTextFieldRole] ||
1153 [[self role] isEqualToString:NSAccessibilityTextAreaRole]) { 1158 [[self role] isEqualToString:NSAccessibilityTextAreaRole]) {
1154 return [NSArray arrayWithObjects: 1159 return [NSArray arrayWithObjects:
1155 NSAccessibilityLineForIndexParameterizedAttribute, 1160 NSAccessibilityLineForIndexParameterizedAttribute,
1156 NSAccessibilityRangeForLineParameterizedAttribute, 1161 NSAccessibilityRangeForLineParameterizedAttribute,
1157 NSAccessibilityStringForRangeParameterizedAttribute, 1162 NSAccessibilityStringForRangeParameterizedAttribute,
1158 NSAccessibilityRangeForPositionParameterizedAttribute, 1163 NSAccessibilityRangeForPositionParameterizedAttribute,
1159 NSAccessibilityRangeForIndexParameterizedAttribute, 1164 NSAccessibilityRangeForIndexParameterizedAttribute,
1160 NSAccessibilityBoundsForRangeParameterizedAttribute, 1165 NSAccessibilityBoundsForRangeParameterizedAttribute,
1161 NSAccessibilityRTFForRangeParameterizedAttribute, 1166 NSAccessibilityRTFForRangeParameterizedAttribute,
1162 NSAccessibilityAttributedStringForRangeParameterizedAttribute, 1167 NSAccessibilityAttributedStringForRangeParameterizedAttribute,
1163 NSAccessibilityStyleRangeForIndexParameterizedAttribute, 1168 NSAccessibilityStyleRangeForIndexParameterizedAttribute,
1164 nil]; 1169 nil];
1165 } 1170 }
1166 return nil; 1171 return nil;
1167 } 1172 }
1168 1173
1169 // Returns an array of action names that this object will respond to. 1174 // Returns an array of action names that this object will respond to.
1170 - (NSArray*)accessibilityActionNames { 1175 - (NSArray*)accessibilityActionNames {
1176 if (!browserAccessibility_)
1177 return nil;
1178
1171 NSMutableArray* ret = 1179 NSMutableArray* ret =
1172 [NSMutableArray arrayWithObject:NSAccessibilityShowMenuAction]; 1180 [NSMutableArray arrayWithObject:NSAccessibilityShowMenuAction];
1173 NSString* role = [self role]; 1181 NSString* role = [self role];
1174 // TODO(dtseng): this should only get set when there's a default action. 1182 // TODO(dtseng): this should only get set when there's a default action.
1175 if (![role isEqualToString:NSAccessibilityStaticTextRole] && 1183 if (![role isEqualToString:NSAccessibilityStaticTextRole] &&
1176 ![role isEqualToString:NSAccessibilityTextAreaRole] && 1184 ![role isEqualToString:NSAccessibilityTextAreaRole] &&
1177 ![role isEqualToString:NSAccessibilityTextFieldRole]) { 1185 ![role isEqualToString:NSAccessibilityTextFieldRole]) {
1178 [ret addObject:NSAccessibilityPressAction]; 1186 [ret addObject:NSAccessibilityPressAction];
1179 } 1187 }
1180 1188
1181 return ret; 1189 return ret;
1182 } 1190 }
1183 1191
1184 // Returns a sub-array of values for the given attribute value, starting at 1192 // Returns a sub-array of values for the given attribute value, starting at
1185 // index, with up to maxCount items. If the given index is out of bounds, 1193 // index, with up to maxCount items. If the given index is out of bounds,
1186 // or there are no values for the given attribute, it will return nil. 1194 // or there are no values for the given attribute, it will return nil.
1187 // This method is used for querying subsets of values, without having to 1195 // This method is used for querying subsets of values, without having to
1188 // return a large set of data, such as elements with a large number of 1196 // return a large set of data, such as elements with a large number of
1189 // children. 1197 // children.
1190 - (NSArray*)accessibilityArrayAttributeValues:(NSString*)attribute 1198 - (NSArray*)accessibilityArrayAttributeValues:(NSString*)attribute
1191 index:(NSUInteger)index 1199 index:(NSUInteger)index
1192 maxCount:(NSUInteger)maxCount { 1200 maxCount:(NSUInteger)maxCount {
1201 if (!browserAccessibility_)
1202 return nil;
1203
1193 NSArray* fullArray = [self accessibilityAttributeValue:attribute]; 1204 NSArray* fullArray = [self accessibilityAttributeValue:attribute];
1194 if (!fullArray) 1205 if (!fullArray)
1195 return nil; 1206 return nil;
1196 NSUInteger arrayCount = [fullArray count]; 1207 NSUInteger arrayCount = [fullArray count];
1197 if (index >= arrayCount) 1208 if (index >= arrayCount)
1198 return nil; 1209 return nil;
1199 NSRange subRange; 1210 NSRange subRange;
1200 if ((index + maxCount) > arrayCount) { 1211 if ((index + maxCount) > arrayCount) {
1201 subRange = NSMakeRange(index, arrayCount - index); 1212 subRange = NSMakeRange(index, arrayCount - index);
1202 } else { 1213 } else {
1203 subRange = NSMakeRange(index, maxCount); 1214 subRange = NSMakeRange(index, maxCount);
1204 } 1215 }
1205 return [fullArray subarrayWithRange:subRange]; 1216 return [fullArray subarrayWithRange:subRange];
1206 } 1217 }
1207 1218
1208 // Returns the count of the specified accessibility array attribute. 1219 // Returns the count of the specified accessibility array attribute.
1209 - (NSUInteger)accessibilityArrayAttributeCount:(NSString*)attribute { 1220 - (NSUInteger)accessibilityArrayAttributeCount:(NSString*)attribute {
1221 if (!browserAccessibility_)
1222 return nil;
1223
1210 NSArray* fullArray = [self accessibilityAttributeValue:attribute]; 1224 NSArray* fullArray = [self accessibilityAttributeValue:attribute];
1211 return [fullArray count]; 1225 return [fullArray count];
1212 } 1226 }
1213 1227
1214 // Returns the list of accessibility attributes that this object supports. 1228 // Returns the list of accessibility attributes that this object supports.
1215 - (NSArray*)accessibilityAttributeNames { 1229 - (NSArray*)accessibilityAttributeNames {
1230 if (!browserAccessibility_)
1231 return nil;
1232
1216 // General attributes. 1233 // General attributes.
1217 NSMutableArray* ret = [NSMutableArray arrayWithObjects: 1234 NSMutableArray* ret = [NSMutableArray arrayWithObjects:
1218 NSAccessibilityChildrenAttribute, 1235 NSAccessibilityChildrenAttribute,
1219 NSAccessibilityDescriptionAttribute, 1236 NSAccessibilityDescriptionAttribute,
1220 NSAccessibilityEnabledAttribute, 1237 NSAccessibilityEnabledAttribute,
1221 NSAccessibilityFocusedAttribute, 1238 NSAccessibilityFocusedAttribute,
1222 NSAccessibilityHelpAttribute, 1239 NSAccessibilityHelpAttribute,
1223 NSAccessibilityParentAttribute, 1240 NSAccessibilityParentAttribute,
1224 NSAccessibilityPositionAttribute, 1241 NSAccessibilityPositionAttribute,
1225 NSAccessibilityRoleAttribute, 1242 NSAccessibilityRoleAttribute,
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
1341 [ret addObjectsFromArray:[NSArray arrayWithObjects: 1358 [ret addObjectsFromArray:[NSArray arrayWithObjects:
1342 NSAccessibilityTitleUIElementAttribute, 1359 NSAccessibilityTitleUIElementAttribute,
1343 nil]]; 1360 nil]];
1344 } 1361 }
1345 1362
1346 return ret; 1363 return ret;
1347 } 1364 }
1348 1365
1349 // Returns the index of the child in this objects array of children. 1366 // Returns the index of the child in this objects array of children.
1350 - (NSUInteger)accessibilityGetIndexOf:(id)child { 1367 - (NSUInteger)accessibilityGetIndexOf:(id)child {
1368 if (!browserAccessibility_)
1369 return nil;
1370
1351 NSUInteger index = 0; 1371 NSUInteger index = 0;
1352 for (BrowserAccessibilityCocoa* childToCheck in [self children]) { 1372 for (BrowserAccessibilityCocoa* childToCheck in [self children]) {
1353 if ([child isEqual:childToCheck]) 1373 if ([child isEqual:childToCheck])
1354 return index; 1374 return index;
1355 ++index; 1375 ++index;
1356 } 1376 }
1357 return NSNotFound; 1377 return NSNotFound;
1358 } 1378 }
1359 1379
1360 // Returns whether or not the specified attribute can be set by the 1380 // Returns whether or not the specified attribute can be set by the
1361 // accessibility API via |accessibilitySetValue:forAttribute:|. 1381 // accessibility API via |accessibilitySetValue:forAttribute:|.
1362 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute { 1382 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute {
1383 if (!browserAccessibility_)
1384 return nil;
1385
1363 if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) 1386 if ([attribute isEqualToString:NSAccessibilityFocusedAttribute])
1364 return GetState(browserAccessibility_, 1387 return GetState(browserAccessibility_,
1365 AccessibilityNodeData::STATE_FOCUSABLE); 1388 AccessibilityNodeData::STATE_FOCUSABLE);
1366 if ([attribute isEqualToString:NSAccessibilityValueAttribute]) { 1389 if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
1367 bool canSetValue = false; 1390 bool canSetValue = false;
1368 browserAccessibility_->GetBoolAttribute( 1391 browserAccessibility_->GetBoolAttribute(
1369 AccessibilityNodeData::ATTR_CAN_SET_VALUE, &canSetValue); 1392 AccessibilityNodeData::ATTR_CAN_SET_VALUE, &canSetValue);
1370 return canSetValue; 1393 return canSetValue;
1371 } 1394 }
1372 if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute] && 1395 if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute] &&
1373 ([[self role] isEqualToString:NSAccessibilityTextFieldRole] || 1396 ([[self role] isEqualToString:NSAccessibilityTextFieldRole] ||
1374 [[self role] isEqualToString:NSAccessibilityTextAreaRole])) 1397 [[self role] isEqualToString:NSAccessibilityTextAreaRole]))
1375 return YES; 1398 return YES;
1376 1399
1377 return NO; 1400 return NO;
1378 } 1401 }
1379 1402
1380 // Returns whether or not this object should be ignored in the accessibilty 1403 // Returns whether or not this object should be ignored in the accessibilty
1381 // tree. 1404 // tree.
1382 - (BOOL)accessibilityIsIgnored { 1405 - (BOOL)accessibilityIsIgnored {
1406 if (!browserAccessibility_)
1407 return true;
1408
1383 return [self isIgnored]; 1409 return [self isIgnored];
1384 } 1410 }
1385 1411
1386 // Performs the given accessibilty action on the webkit accessibility object 1412 // Performs the given accessibilty action on the webkit accessibility object
1387 // that backs this object. 1413 // that backs this object.
1388 - (void)accessibilityPerformAction:(NSString*)action { 1414 - (void)accessibilityPerformAction:(NSString*)action {
1415 if (!browserAccessibility_)
1416 return;
1417
1389 // TODO(feldstein): Support more actions. 1418 // TODO(feldstein): Support more actions.
1390 if ([action isEqualToString:NSAccessibilityPressAction]) 1419 if ([action isEqualToString:NSAccessibilityPressAction])
1391 [delegate_ doDefaultAction:browserAccessibility_->renderer_id()]; 1420 [delegate_ doDefaultAction:browserAccessibility_->renderer_id()];
1392 else if ([action isEqualToString:NSAccessibilityShowMenuAction]) 1421 else if ([action isEqualToString:NSAccessibilityShowMenuAction])
1393 [delegate_ performShowMenuAction:self]; 1422 [delegate_ performShowMenuAction:self];
1394 } 1423 }
1395 1424
1396 // Returns the description of the given action. 1425 // Returns the description of the given action.
1397 - (NSString*)accessibilityActionDescription:(NSString*)action { 1426 - (NSString*)accessibilityActionDescription:(NSString*)action {
1427 if (!browserAccessibility_)
1428 return nil;
1429
1398 return NSAccessibilityActionDescription(action); 1430 return NSAccessibilityActionDescription(action);
1399 } 1431 }
1400 1432
1401 // Sets an override value for a specific accessibility attribute. 1433 // Sets an override value for a specific accessibility attribute.
1402 // This class does not support this. 1434 // This class does not support this.
1403 - (BOOL)accessibilitySetOverrideValue:(id)value 1435 - (BOOL)accessibilitySetOverrideValue:(id)value
1404 forAttribute:(NSString*)attribute { 1436 forAttribute:(NSString*)attribute {
1405 return NO; 1437 return NO;
1406 } 1438 }
1407 1439
1408 // Sets the value for an accessibility attribute via the accessibility API. 1440 // Sets the value for an accessibility attribute via the accessibility API.
1409 - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute { 1441 - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute {
1442 if (!browserAccessibility_)
1443 return;
1444
1410 if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { 1445 if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
1411 NSNumber* focusedNumber = value; 1446 NSNumber* focusedNumber = value;
1412 BOOL focused = [focusedNumber intValue]; 1447 BOOL focused = [focusedNumber intValue];
1413 [delegate_ setAccessibilityFocus:focused 1448 [delegate_ setAccessibilityFocus:focused
1414 accessibilityId:browserAccessibility_->renderer_id()]; 1449 accessibilityId:browserAccessibility_->renderer_id()];
1415 } 1450 }
1416 if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) { 1451 if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
1417 NSRange range = [(NSValue*)value rangeValue]; 1452 NSRange range = [(NSValue*)value rangeValue];
1418 [delegate_ 1453 [delegate_
1419 accessibilitySetTextSelection:browserAccessibility_->renderer_id() 1454 accessibilitySetTextSelection:browserAccessibility_->renderer_id()
1420 startOffset:range.location 1455 startOffset:range.location
1421 endOffset:range.location + range.length]; 1456 endOffset:range.location + range.length];
1422 } 1457 }
1423 } 1458 }
1424 1459
1425 // Returns the deepest accessibility child that should not be ignored. 1460 // Returns the deepest accessibility child that should not be ignored.
1426 // It is assumed that the hit test has been narrowed down to this object 1461 // It is assumed that the hit test has been narrowed down to this object
1427 // or one of its children, so this will never return nil. 1462 // or one of its children, so this will never return nil unless this
1463 // object is invalid.
1428 - (id)accessibilityHitTest:(NSPoint)point { 1464 - (id)accessibilityHitTest:(NSPoint)point {
1465 if (!browserAccessibility_)
1466 return nil;
1467
1429 BrowserAccessibilityCocoa* hit = self; 1468 BrowserAccessibilityCocoa* hit = self;
1430 for (BrowserAccessibilityCocoa* child in [self children]) { 1469 for (BrowserAccessibilityCocoa* child in [self children]) {
1431 NSPoint origin = [child origin]; 1470 NSPoint origin = [child origin];
1432 NSSize size = [[child size] sizeValue]; 1471 NSSize size = [[child size] sizeValue];
1433 NSRect rect; 1472 NSRect rect;
1434 rect.origin = origin; 1473 rect.origin = origin;
1435 rect.size = size; 1474 rect.size = size;
1436 if (NSPointInRect(point, rect)) { 1475 if (NSPointInRect(point, rect)) {
1437 hit = child; 1476 hit = child;
1438 id childResult = [child accessibilityHitTest:point]; 1477 id childResult = [child accessibilityHitTest:point];
(...skipping 18 matching lines...) Expand all
1457 return [super hash]; 1496 return [super hash];
1458 return browserAccessibility_->renderer_id(); 1497 return browserAccessibility_->renderer_id();
1459 } 1498 }
1460 1499
1461 - (BOOL)accessibilityShouldUseUniqueId { 1500 - (BOOL)accessibilityShouldUseUniqueId {
1462 return YES; 1501 return YES;
1463 } 1502 }
1464 1503
1465 @end 1504 @end
1466 1505
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698