Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "content/browser/renderer_host/render_widget_host_view_mac.h" | 5 #include "content/browser/renderer_host/render_widget_host_view_mac.h" |
| 6 | 6 |
| 7 #import <objc/runtime.h> | 7 #import <objc/runtime.h> |
| 8 #include <OpenGL/gl.h> | 8 #include <OpenGL/gl.h> |
| 9 #include <QuartzCore/QuartzCore.h> | 9 #include <QuartzCore/QuartzCore.h> |
| 10 | 10 |
| 11 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/callback_helpers.h" | 13 #include "base/callback_helpers.h" |
| 14 #include "base/command_line.h" | 14 #include "base/command_line.h" |
| 15 #include "base/debug/crash_logging.h" | 15 #include "base/debug/crash_logging.h" |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/mac/mac_util.h" | 17 #include "base/mac/mac_util.h" |
| 18 #include "base/mac/scoped_cftyperef.h" | 18 #include "base/mac/scoped_cftyperef.h" |
| 19 #import "base/mac/scoped_nsobject.h" | 19 #import "base/mac/scoped_nsobject.h" |
| 20 #include "base/mac/sdk_forward_declarations.h" | 20 #include "base/mac/sdk_forward_declarations.h" |
| 21 #include "base/message_loop/message_loop.h" | 21 #include "base/message_loop/message_loop.h" |
| 22 #include "base/metrics/histogram.h" | 22 #include "base/metrics/histogram.h" |
| 23 #include "base/numerics/safe_conversions.h" | |
| 23 #include "base/strings/string_util.h" | 24 #include "base/strings/string_util.h" |
| 24 #include "base/strings/stringprintf.h" | 25 #include "base/strings/stringprintf.h" |
| 25 #include "base/strings/sys_string_conversions.h" | 26 #include "base/strings/sys_string_conversions.h" |
| 26 #include "base/strings/utf_string_conversions.h" | 27 #include "base/strings/utf_string_conversions.h" |
| 27 #include "base/sys_info.h" | 28 #include "base/sys_info.h" |
| 28 #include "base/trace_event/trace_event.h" | 29 #include "base/trace_event/trace_event.h" |
| 29 #import "content/browser/accessibility/browser_accessibility_cocoa.h" | 30 #import "content/browser/accessibility/browser_accessibility_cocoa.h" |
| 30 #include "content/browser/accessibility/browser_accessibility_manager_mac.h" | 31 #include "content/browser/accessibility/browser_accessibility_manager_mac.h" |
| 31 #include "content/browser/bad_message.h" | 32 #include "content/browser/bad_message.h" |
| 32 #import "content/browser/cocoa/system_hotkey_helper_mac.h" | 33 #import "content/browser/cocoa/system_hotkey_helper_mac.h" |
| (...skipping 1186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1219 [cocoa_view_ setMarkedRange:range.ToNSRange()]; | 1220 [cocoa_view_ setMarkedRange:range.ToNSRange()]; |
| 1220 } | 1221 } |
| 1221 | 1222 |
| 1222 RenderWidgetHostViewBase::SelectionChanged(text, offset, range); | 1223 RenderWidgetHostViewBase::SelectionChanged(text, offset, range); |
| 1223 } | 1224 } |
| 1224 | 1225 |
| 1225 void RenderWidgetHostViewMac::SelectionBoundsChanged( | 1226 void RenderWidgetHostViewMac::SelectionBoundsChanged( |
| 1226 const ViewHostMsg_SelectionBounds_Params& params) { | 1227 const ViewHostMsg_SelectionBounds_Params& params) { |
| 1227 if (params.anchor_rect == params.focus_rect) | 1228 if (params.anchor_rect == params.focus_rect) |
| 1228 caret_rect_ = params.anchor_rect; | 1229 caret_rect_ = params.anchor_rect; |
| 1230 first_selection_rect_ = params.anchor_rect; | |
| 1229 } | 1231 } |
| 1230 | 1232 |
| 1231 void RenderWidgetHostViewMac::SetShowingContextMenu(bool showing) { | 1233 void RenderWidgetHostViewMac::SetShowingContextMenu(bool showing) { |
| 1232 RenderWidgetHostViewBase::SetShowingContextMenu(showing); | 1234 RenderWidgetHostViewBase::SetShowingContextMenu(showing); |
| 1233 | 1235 |
| 1234 // Create a fake mouse event to inform the render widget that the mouse | 1236 // Create a fake mouse event to inform the render widget that the mouse |
| 1235 // left or entered. | 1237 // left or entered. |
| 1236 NSWindow* window = [cocoa_view_ window]; | 1238 NSWindow* window = [cocoa_view_ window]; |
| 1237 // TODO(asvitkine): If the location outside of the event stream doesn't | 1239 // TODO(asvitkine): If the location outside of the event stream doesn't |
| 1238 // correspond to the current event (due to delayed event processing), then | 1240 // correspond to the current event (due to delayed event processing), then |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1439 | 1441 |
| 1440 bool RenderWidgetHostViewMac::GetCachedFirstRectForCharacterRange( | 1442 bool RenderWidgetHostViewMac::GetCachedFirstRectForCharacterRange( |
| 1441 NSRange range, | 1443 NSRange range, |
| 1442 NSRect* rect, | 1444 NSRect* rect, |
| 1443 NSRange* actual_range) { | 1445 NSRange* actual_range) { |
| 1444 DCHECK(rect); | 1446 DCHECK(rect); |
| 1445 // This exists to make IMEs more responsive, see http://crbug.com/115920 | 1447 // This exists to make IMEs more responsive, see http://crbug.com/115920 |
| 1446 TRACE_EVENT0("browser", | 1448 TRACE_EVENT0("browser", |
| 1447 "RenderWidgetHostViewMac::GetFirstRectForCharacterRange"); | 1449 "RenderWidgetHostViewMac::GetFirstRectForCharacterRange"); |
| 1448 | 1450 |
| 1451 const gfx::Range requested_range(range); | |
| 1449 // If requested range is same as caret location, we can just return it. | 1452 // If requested range is same as caret location, we can just return it. |
| 1450 if (selection_range_.is_empty() && gfx::Range(range) == selection_range_) { | 1453 if (selection_range_.is_empty() && requested_range == selection_range_) { |
| 1451 if (actual_range) | 1454 if (actual_range) |
| 1452 *actual_range = range; | 1455 *actual_range = range; |
| 1453 *rect = NSRectFromCGRect(caret_rect_.ToCGRect()); | 1456 *rect = NSRectFromCGRect(caret_rect_.ToCGRect()); |
| 1454 return true; | 1457 return true; |
| 1455 } | 1458 } |
| 1456 | 1459 |
| 1460 if (composition_range_.is_empty()) { | |
| 1461 if (!selection_range_.Contains(requested_range)) | |
| 1462 return false; | |
| 1463 if (actual_range) | |
| 1464 *actual_range = selection_range_.ToNSRange(); | |
| 1465 *rect = NSRectFromCGRect(first_selection_rect_.ToCGRect()); | |
| 1466 return true; | |
| 1467 } | |
| 1468 | |
| 1457 const gfx::Range request_range_in_composition = | 1469 const gfx::Range request_range_in_composition = |
| 1458 ConvertCharacterRangeToCompositionRange(gfx::Range(range)); | 1470 ConvertCharacterRangeToCompositionRange(requested_range); |
| 1459 if (request_range_in_composition == gfx::Range::InvalidRange()) | 1471 if (request_range_in_composition == gfx::Range::InvalidRange()) |
| 1460 return false; | 1472 return false; |
| 1461 | 1473 |
| 1462 // If firstRectForCharacterRange in WebFrame is failed in renderer, | 1474 // If firstRectForCharacterRange in WebFrame is failed in renderer, |
| 1463 // ImeCompositionRangeChanged will be sent with empty vector. | 1475 // ImeCompositionRangeChanged will be sent with empty vector. |
| 1464 if (composition_bounds_.empty()) | 1476 if (composition_bounds_.empty()) |
| 1465 return false; | 1477 return false; |
| 1466 DCHECK_EQ(composition_bounds_.size(), composition_range_.length()); | 1478 DCHECK_EQ(composition_bounds_.size(), composition_range_.length()); |
| 1467 | 1479 |
| 1468 gfx::Range ui_actual_range; | 1480 gfx::Range ui_actual_range; |
| (...skipping 1419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2888 // there. (When this method returns an empty range, the input method doesn't | 2900 // there. (When this method returns an empty range, the input method doesn't |
| 2889 // call the setMarkedText method.) | 2901 // call the setMarkedText method.) |
| 2890 return hasMarkedText_ ? markedRange_ : NSMakeRange(NSNotFound, 0); | 2902 return hasMarkedText_ ? markedRange_ : NSMakeRange(NSNotFound, 0); |
| 2891 } | 2903 } |
| 2892 | 2904 |
| 2893 - (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range | 2905 - (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range |
| 2894 actualRange:(NSRangePointer)actualRange { | 2906 actualRange:(NSRangePointer)actualRange { |
| 2895 // TODO(thakis): Pipe |actualRange| through TextInputClientMac machinery. | 2907 // TODO(thakis): Pipe |actualRange| through TextInputClientMac machinery. |
| 2896 if (actualRange) | 2908 if (actualRange) |
| 2897 *actualRange = range; | 2909 *actualRange = range; |
| 2898 NSAttributedString* str = | 2910 |
| 2899 TextInputClientMac::GetInstance()->GetAttributedSubstringFromRange( | 2911 const gfx::Range requested_range(range); |
| 2900 renderWidgetHostView_->render_widget_host_, range); | 2912 if (requested_range.is_reversed()) |
| 2901 return str; | 2913 return nil; |
| 2914 | |
| 2915 gfx::Range expected_range; | |
| 2916 const base::string16* expected_text; | |
| 2917 | |
| 2918 if (!renderWidgetHostView_->composition_range().is_empty()) { | |
| 2919 expected_text = &markedText_; | |
| 2920 expected_range = renderWidgetHostView_->composition_range(); | |
| 2921 } else { | |
| 2922 expected_text = &renderWidgetHostView_->selection_text(); | |
| 2923 size_t offset = renderWidgetHostView_->selection_text_offset(); | |
| 2924 expected_range = gfx::Range(offset, offset + expected_text->size()); | |
| 2925 } | |
| 2926 | |
| 2927 if (!expected_range.Contains(requested_range)) | |
| 2928 return nil; | |
| 2929 | |
| 2930 // Gets the raw bytes to avoid unnecessary string copies for generating | |
| 2931 // NSString. | |
| 2932 const base::char16* bytes = | |
| 2933 &(*expected_text)[requested_range.start() - expected_range.start()]; | |
|
palmer
2015/09/02 20:17:22
I still don't understand this.
Shu Chen
2015/09/03 15:07:32
For example, expected_text == "hello world", expec
palmer
2015/09/03 23:03:59
So, it sounds like you should add a check to ensur
Shu Chen
2015/09/04 01:36:47
Is above check at line 2927 not enough?
palmer
2015/09/09 23:30:20
I'm sorry, I didn't see that check. Yes, it is goo
| |
| 2934 NSUInteger bytes_len = base::strict_cast<NSUInteger, size_t>( | |
| 2935 requested_range.length() * sizeof(base::char16)); | |
|
palmer
2015/09/02 20:17:22
Could this multiplication result in integer overfl
Shu Chen
2015/09/03 15:07:32
It could, I've added the check.
| |
| 2936 base::scoped_nsobject<NSString> ns_string( | |
| 2937 [[NSString alloc] initWithBytes:bytes | |
| 2938 length:bytes_len | |
| 2939 encoding:NSUTF16LittleEndianStringEncoding]); | |
| 2940 return [[[NSAttributedString alloc] initWithString:ns_string] autorelease]; | |
| 2902 } | 2941 } |
| 2903 | 2942 |
| 2904 - (NSInteger)conversationIdentifier { | 2943 - (NSInteger)conversationIdentifier { |
| 2905 return reinterpret_cast<NSInteger>(self); | 2944 return reinterpret_cast<NSInteger>(self); |
| 2906 } | 2945 } |
| 2907 | 2946 |
| 2908 // Each RenderWidgetHostViewCocoa has its own input context, but we return | 2947 // Each RenderWidgetHostViewCocoa has its own input context, but we return |
| 2909 // nil when the caret is in non-editable content or password box to avoid | 2948 // nil when the caret is in non-editable content or password box to avoid |
| 2910 // making input methods do their work. | 2949 // making input methods do their work. |
| 2911 - (NSTextInputContext *)inputContext { | 2950 - (NSTextInputContext *)inputContext { |
| (...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3323 | 3362 |
| 3324 // "-webkit-app-region: drag | no-drag" is implemented on Mac by excluding | 3363 // "-webkit-app-region: drag | no-drag" is implemented on Mac by excluding |
| 3325 // regions that are not draggable. (See ControlRegionView in | 3364 // regions that are not draggable. (See ControlRegionView in |
| 3326 // native_app_window_cocoa.mm). This requires the render host view to be | 3365 // native_app_window_cocoa.mm). This requires the render host view to be |
| 3327 // draggable by default. | 3366 // draggable by default. |
| 3328 - (BOOL)mouseDownCanMoveWindow { | 3367 - (BOOL)mouseDownCanMoveWindow { |
| 3329 return YES; | 3368 return YES; |
| 3330 } | 3369 } |
| 3331 | 3370 |
| 3332 @end | 3371 @end |
| OLD | NEW |