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 "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 |