FBElementCache.m 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /**
  2. * Copyright (c) 2015-present, Facebook, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. */
  9. #import "FBElementCache.h"
  10. #import "LRUCache.h"
  11. #import "FBAlert.h"
  12. #import "FBExceptions.h"
  13. #import "FBXCodeCompatibility.h"
  14. #import "XCTestPrivateSymbols.h"
  15. #import "XCUIElement.h"
  16. #import "XCUIElement+FBCaching.h"
  17. #import "XCUIElement+FBUtilities.h"
  18. #import "XCUIElement+FBWebDriverAttributes.h"
  19. #import "XCUIElement+FBUID.h"
  20. #import "XCUIElement+FBResolve.h"
  21. #import "XCUIElementQuery.h"
  22. const int ELEMENT_CACHE_SIZE = 1024;
  23. @interface FBElementCache ()
  24. @property (nonatomic, strong) LRUCache *elementCache;
  25. @end
  26. @implementation FBElementCache
  27. - (instancetype)init
  28. {
  29. self = [super init];
  30. if (!self) {
  31. return nil;
  32. }
  33. _elementCache = [[LRUCache alloc] initWithCapacity:ELEMENT_CACHE_SIZE];
  34. return self;
  35. }
  36. - (NSString *)storeElement:(XCUIElement *)element
  37. {
  38. NSString *uuid = element.fb_cacheId;
  39. if (nil == uuid) {
  40. return nil;
  41. }
  42. @synchronized (self.elementCache) {
  43. [self.elementCache setObject:element forKey:uuid];
  44. }
  45. return uuid;
  46. }
  47. - (XCUIElement *)elementForUUID:(NSString *)uuid
  48. {
  49. return [self elementForUUID:uuid checkStaleness:NO];
  50. }
  51. - (XCUIElement *)elementForUUID:(NSString *)uuid checkStaleness:(BOOL)checkStaleness
  52. {
  53. if (!uuid) {
  54. NSString *reason = [NSString stringWithFormat:@"Cannot extract cached element for UUID: %@", uuid];
  55. @throw [NSException exceptionWithName:FBInvalidArgumentException reason:reason userInfo:@{}];
  56. }
  57. XCUIElement *element;
  58. @synchronized (self.elementCache) {
  59. element = [self.elementCache objectForKey:uuid];
  60. }
  61. if (nil == element) {
  62. NSString *reason = [NSString stringWithFormat:@"The element identified by \"%@\" is either not present or it has expired from the internal cache. Try to find it again", uuid];
  63. @throw [NSException exceptionWithName:FBStaleElementException reason:reason userInfo:@{}];
  64. }
  65. if (checkStaleness) {
  66. @try {
  67. [element fb_standardSnapshot];
  68. } @catch (NSException *exception) {
  69. // if the snapshot method threw FBStaleElementException (implying the element is stale) we need to explicitly remove it from the cache, PR: https://github.com/appium/WebDriverAgent/pull/985
  70. if ([exception.name isEqualToString:FBStaleElementException]) {
  71. @synchronized (self.elementCache) {
  72. [self.elementCache removeObjectForKey:uuid];
  73. }
  74. }
  75. @throw exception;
  76. }
  77. }
  78. return element;
  79. }
  80. - (BOOL)hasElementWithUUID:(NSString *)uuid
  81. {
  82. if (nil == uuid) {
  83. return NO;
  84. }
  85. @synchronized (self.elementCache) {
  86. return nil != [self.elementCache objectForKey:(NSString *)uuid];
  87. }
  88. }
  89. @end