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 3 // found in the LICENSE file. 4 5 #ifndef CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_CLIENT_MAC_H_ 6 #define CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_CLIENT_MAC_H_ 7 8 #import <Cocoa/Cocoa.h> 9 10 #include "base/mac/scoped_nsobject.h" 11 #include "base/synchronization/condition_variable.h" 12 #include "base/synchronization/lock.h" 13 #include "content/common/content_export.h" 14 #include "ui/gfx/point.h" 15 16 template <typename T> struct DefaultSingletonTraits; 17 18 namespace content { 19 class RenderWidgetHost; 20 21 // This class helps with the Mac OS X dictionary popup. For the design overview, 22 // look at this document: 23 // http://dev.chromium.org/developers/design-documents/system-dictionary-pop-up-architecture 24 // 25 // This service is used to marshall information for these three methods that are 26 // implemented in RenderWidgetHostViewMac: 27 // -[NSTextInput characterIndexForPoint:] 28 // -[NSTextInput attributedSubstringFromRange:] 29 // -[NSTextInput firstRectForCharacterRange:] 30 // 31 // Because these methods are part of a synchronous system API, implementing them 32 // requires getting information from the renderer synchronously. Rather than 33 // using an actual sync IPC message, a normal async ViewMsg is used with a lock 34 // and condition (managed by this service). 35 class CONTENT_EXPORT TextInputClientMac { 36 public: 37 // Returns the singleton instance. 38 static TextInputClientMac* GetInstance(); 39 40 // Each of the three methods mentioned above has an associated pair of methods 41 // to get data from the renderer. The Get*() methods block the calling thread 42 // (always the UI thread) with a short timeout after the async message has 43 // been sent to the renderer to lookup the information needed to respond to 44 // the system. The Set*AndSignal() methods store the looked up information in 45 // this service and signal the condition to allow the Get*() methods to 46 // unlock and return that stored value. 47 // 48 // Returns NSNotFound if the request times out or is not completed. 49 NSUInteger GetCharacterIndexAtPoint(RenderWidgetHost* rwh, gfx::Point point); 50 // Returns nil if the request times out or is completed. 51 NSAttributedString* GetAttributedSubstringFromRange( 52 RenderWidgetHost* rwh, NSRange range); 53 // Returns NSZeroRect if the request times out or is not completed. The result 54 // is in WebKit coordinates. 55 NSRect GetFirstRectForRange(RenderWidgetHost* rwh, NSRange range); 56 57 // When the renderer sends the ViewHostMsg reply, the RenderMessageFilter will 58 // call the corresponding method on the IO thread to unlock the condition and 59 // allow the Get*() methods to continue/return. 60 void SetCharacterIndexAndSignal(NSUInteger index); 61 void SetFirstRectAndSignal(NSRect first_rect); 62 void SetSubstringAndSignal(NSAttributedString* string); 63 64 private: 65 friend struct DefaultSingletonTraits<TextInputClientMac>; 66 TextInputClientMac(); 67 ~TextInputClientMac(); 68 69 // The critical sections that the Condition guards are in Get*() methods. 70 // These methods lock the internal condition for use before the asynchronous 71 // message is sent to the renderer to lookup the required information. These 72 // are only used on the UI thread. 73 void BeforeRequest(); 74 // Called at the end of a critical section. This will release the lock and 75 // condition. 76 void AfterRequest(); 77 78 NSUInteger character_index_; 79 NSRect first_rect_; 80 base::scoped_nsobject<NSAttributedString> substring_; 81 82 base::Lock lock_; 83 base::ConditionVariable condition_; 84 85 DISALLOW_COPY_AND_ASSIGN(TextInputClientMac); 86 }; 87 88 } // namespace content 89 90 #endif // CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_CLIENT_MAC_H_ 91