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 "chrome/browser/ui/cocoa/web_intent_picker_cocoa.h" | 5 #include "chrome/browser/ui/cocoa/web_intent_picker_cocoa.h" |
6 | 6 |
7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
8 | 8 |
9 #include "base/bind.h" | |
10 #include "base/message_loop.h" | |
9 #include "chrome/browser/profiles/profile.h" | 11 #include "chrome/browser/profiles/profile.h" |
10 #include "chrome/browser/ui/browser.h" | 12 #include "chrome/browser/ui/browser.h" |
11 #include "chrome/browser/ui/browser_window.h" | 13 #include "chrome/browser/ui/browser_window.h" |
12 #import "chrome/browser/ui/cocoa/browser_window_controller.h" | 14 #import "chrome/browser/ui/cocoa/browser_window_controller.h" |
13 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h" | 15 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h" |
14 #import "chrome/browser/ui/cocoa/web_intent_bubble_controller.h" | 16 #import "chrome/browser/ui/cocoa/web_intent_bubble_controller.h" |
15 #include "chrome/browser/ui/intents/web_intent_picker.h" | 17 #include "chrome/browser/ui/intents/web_intent_picker.h" |
16 #include "chrome/browser/ui/intents/web_intent_picker_delegate.h" | 18 #include "chrome/browser/ui/intents/web_intent_picker_delegate.h" |
17 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 19 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
18 #include "content/public/browser/web_contents.h" | 20 #include "content/public/browser/web_contents.h" |
(...skipping 26 matching lines...) Expand all Loading... | |
45 TabContentsWrapper* wrapper, | 47 TabContentsWrapper* wrapper, |
46 WebIntentPickerDelegate* delegate, | 48 WebIntentPickerDelegate* delegate, |
47 WebIntentPickerModel* model) { | 49 WebIntentPickerModel* model) { |
48 return new WebIntentPickerCocoa(browser, wrapper, delegate, model); | 50 return new WebIntentPickerCocoa(browser, wrapper, delegate, model); |
49 } | 51 } |
50 | 52 |
51 WebIntentPickerCocoa::WebIntentPickerCocoa() | 53 WebIntentPickerCocoa::WebIntentPickerCocoa() |
52 : delegate_(NULL), | 54 : delegate_(NULL), |
53 model_(NULL), | 55 model_(NULL), |
54 browser_(NULL), | 56 browser_(NULL), |
55 controller_(NULL) { | 57 controller_(nil), |
58 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | |
Nico
2012/02/03 23:27:07
this macro is only needed for msvc i think
groby-ooo-7-16
2012/02/06 22:30:19
Done.
| |
56 } | 59 } |
57 | 60 |
58 | 61 |
59 WebIntentPickerCocoa::WebIntentPickerCocoa(Browser* browser, | 62 WebIntentPickerCocoa::WebIntentPickerCocoa(Browser* browser, |
60 TabContentsWrapper* wrapper, | 63 TabContentsWrapper* wrapper, |
61 WebIntentPickerDelegate* delegate, | 64 WebIntentPickerDelegate* delegate, |
62 WebIntentPickerModel* model) | 65 WebIntentPickerModel* model) |
63 : delegate_(delegate), | 66 : delegate_(delegate), |
64 model_(model), | 67 model_(model), |
65 browser_(browser), | 68 browser_(browser), |
66 controller_(NULL) { | 69 controller_(nil), |
70 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | |
67 model_->set_observer(this); | 71 model_->set_observer(this); |
68 | 72 |
69 DCHECK(browser); | 73 DCHECK(browser); |
70 DCHECK(delegate); | 74 DCHECK(delegate); |
71 NSWindow* parentWindow = browser->window()->GetNativeHandle(); | 75 NSWindow* parentWindow = browser->window()->GetNativeHandle(); |
72 | 76 |
73 // Compute the anchor point, relative to location bar. | 77 // Compute the anchor point, relative to location bar. |
74 BrowserWindowController* controller = [parentWindow windowController]; | 78 BrowserWindowController* controller = [parentWindow windowController]; |
75 LocationBarViewMac* locationBar = [controller locationBarBridge]; | 79 LocationBarViewMac* locationBar = [controller locationBarBridge]; |
76 NSPoint anchor = locationBar->GetPageInfoBubblePoint(); | 80 NSPoint anchor = locationBar->GetPageInfoBubblePoint(); |
77 anchor = [browser->window()->GetNativeHandle() convertBaseToScreen:anchor]; | 81 anchor = [browser->window()->GetNativeHandle() convertBaseToScreen:anchor]; |
78 | 82 |
79 // The controller is deallocated when the window is closed, so no need to | 83 // The controller is deallocated when the window is closed, so no need to |
80 // worry about it here. | 84 // worry about it here. |
81 [[WebIntentBubbleController alloc] initWithPicker:this | 85 [[WebIntentBubbleController alloc] initWithPicker:this |
82 parentWindow:parentWindow | 86 parentWindow:parentWindow |
83 anchoredAt:anchor]; | 87 anchoredAt:anchor]; |
84 } | 88 } |
85 | 89 |
86 WebIntentPickerCocoa::~WebIntentPickerCocoa() { | 90 WebIntentPickerCocoa::~WebIntentPickerCocoa() { |
87 if (model_ != NULL) | 91 if (model_ != NULL) |
88 model_->set_observer(NULL); | 92 model_->set_observer(NULL); |
89 } | 93 } |
90 | 94 |
91 void WebIntentPickerCocoa::Close() { | 95 void WebIntentPickerCocoa::Close() { |
92 } | 96 } |
93 | 97 |
98 void WebIntentPickerCocoa::PerformDelayedLayout() { | |
99 // Check to see if a layout has already been scheduled. | |
Nico
2012/02/03 23:27:07
indent only 2
groby-ooo-7-16
2012/02/06 22:30:19
Done.
| |
100 if (weak_ptr_factory_.HasWeakPtrs()) | |
101 return; | |
102 | |
103 // Delay performing layout by a second so that all the animations from | |
104 // InfoBubbleWindow and origin updates from BaseBubbleController finish, so | |
105 // that we don't all race trying to change the frame's origin. | |
106 // | |
107 // Using MessageLoop is superior here to |-performSelector:| because it will | |
108 // not retain its target; if the child outlives its parent, zombies get left | |
109 // behind (http://crbug.com/59619). This will cancel the scheduled task if | |
110 // the controller get destroyed before the message | |
111 // can be delivered. | |
Nico
2012/02/03 23:27:07
This looks familiar. Can this code be factored out
groby-ooo-7-16
2012/02/06 22:30:19
It _is_ familiar. The PageInfoBubble does _almost_
Nico
2012/02/06 22:39:38
:-/
| |
112 MessageLoop::current()->PostDelayedTask(FROM_HERE, | |
113 base::Bind(&WebIntentPickerCocoa::PerformLayout, | |
114 weak_ptr_factory_.GetWeakPtr()), | |
115 100 /* milliseconds */); | |
116 } | |
117 | |
118 void WebIntentPickerCocoa::PerformLayout() { | |
119 DCHECK(controller_); | |
120 // If the window is animating closed when this is called, the | |
121 // animation could be holding the last reference to |controller_| | |
122 // (and thus |this|). Pin it until the task is completed. | |
123 scoped_nsobject<WebIntentBubbleController> keep_alive([controller_ retain]); | |
124 [controller_ performLayoutWithModel:model_]; | |
125 } | |
126 | |
94 void WebIntentPickerCocoa::OnModelChanged(WebIntentPickerModel* model) { | 127 void WebIntentPickerCocoa::OnModelChanged(WebIntentPickerModel* model) { |
95 DCHECK(controller_); | 128 PerformDelayedLayout(); |
96 scoped_nsobject<NSMutableArray> urlArray( | |
97 [[NSMutableArray alloc] initWithCapacity:model->GetItemCount()]); | |
98 | |
99 for (size_t i = 0; i < model->GetItemCount(); ++i) { | |
100 const WebIntentPickerModel::Item& item = model->GetItemAt(i); | |
101 | |
102 [urlArray addObject: | |
103 [NSString stringWithUTF8String:item.url.spec().c_str()]]; | |
104 [controller_ replaceImageAtIndex:i withImage:item.favicon.ToNSImage()]; | |
105 } | |
106 | |
107 [controller_ setServiceURLs:urlArray]; | |
108 } | 129 } |
109 | 130 |
110 void WebIntentPickerCocoa::OnFaviconChanged(WebIntentPickerModel* model, | 131 void WebIntentPickerCocoa::OnFaviconChanged(WebIntentPickerModel* model, |
111 size_t index) { | 132 size_t index) { |
112 DCHECK(controller_); | 133 // We don't handle individual icon changes - just redo the whole model. |
113 | 134 PerformDelayedLayout(); |
114 const WebIntentPickerModel::Item& item = model->GetItemAt(index); | |
115 [controller_ replaceImageAtIndex:index withImage:item.favicon.ToNSImage()]; | |
116 } | 135 } |
117 | 136 |
118 void WebIntentPickerCocoa::OnInlineDisposition(WebIntentPickerModel* model) { | 137 void WebIntentPickerCocoa::OnInlineDisposition(WebIntentPickerModel* model) { |
119 const WebIntentPickerModel::Item& item = model->GetItemAt( | 138 const WebIntentPickerModel::Item& item = model->GetItemAt( |
120 model->inline_disposition_index()); | 139 model->inline_disposition_index()); |
121 | 140 |
122 content::WebContents* web_contents = content::WebContents::Create( | 141 content::WebContents* web_contents = content::WebContents::Create( |
123 browser_->profile(), NULL, MSG_ROUTING_NONE, NULL, NULL); | 142 browser_->profile(), NULL, MSG_ROUTING_NONE, NULL, NULL); |
124 inline_disposition_tab_contents_.reset(new TabContentsWrapper(web_contents)); | 143 inline_disposition_tab_contents_.reset(new TabContentsWrapper(web_contents)); |
125 inline_disposition_delegate_.reset(new InlineHtmlContentDelegate); | 144 inline_disposition_delegate_.reset(new InlineHtmlContentDelegate); |
126 web_contents->SetDelegate(inline_disposition_delegate_.get()); | 145 web_contents->SetDelegate(inline_disposition_delegate_.get()); |
127 | 146 |
128 inline_disposition_tab_contents_->web_contents()->GetController().LoadURL( | 147 inline_disposition_tab_contents_->web_contents()->GetController().LoadURL( |
129 item.url, | 148 item.url, |
130 content::Referrer(), | 149 content::Referrer(), |
131 content::PAGE_TRANSITION_START_PAGE, | 150 content::PAGE_TRANSITION_START_PAGE, |
132 std::string()); | 151 std::string()); |
133 | 152 |
134 [controller_ setInlineDispositionTabContents: | 153 [controller_ setInlineDispositionTabContents: |
135 inline_disposition_tab_contents_.get()]; | 154 inline_disposition_tab_contents_.get()]; |
155 PerformDelayedLayout(); | |
136 | 156 |
137 delegate_->OnInlineDispositionWebContentsCreated(web_contents); | 157 delegate_->OnInlineDispositionWebContentsCreated(web_contents); |
138 } | 158 } |
139 | 159 |
140 void WebIntentPickerCocoa::OnCancelled() { | 160 void WebIntentPickerCocoa::OnCancelled() { |
141 DCHECK(delegate_); | 161 DCHECK(delegate_); |
142 delegate_->OnCancelled(); | 162 delegate_->OnCancelled(); |
143 controller_ = NULL; // Controller will be unusable soon, abandon. | 163 controller_ = NULL; // Controller will be unusable soon, abandon. |
144 } | 164 } |
145 | 165 |
146 void WebIntentPickerCocoa::OnServiceChosen(size_t index) { | 166 void WebIntentPickerCocoa::OnServiceChosen(size_t index) { |
147 DCHECK(delegate_); | 167 DCHECK(delegate_); |
148 const WebIntentPickerModel::Item& item = model_->GetItemAt(index); | 168 const WebIntentPickerModel::Item& item = model_->GetItemAt(index); |
149 delegate_->OnServiceChosen(index, item.disposition); | 169 delegate_->OnServiceChosen(index, item.disposition); |
150 } | 170 } |
151 | 171 |
152 void WebIntentPickerCocoa::set_controller( | 172 void WebIntentPickerCocoa::set_controller( |
153 WebIntentBubbleController* controller) { | 173 WebIntentBubbleController* controller) { |
154 controller_ = controller; | 174 controller_ = controller; |
155 } | 175 } |
OLD | NEW |