Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(403)

Side by Side Diff: chrome/browser/ui/cocoa/web_intent_picker_cocoa.mm

Issue 9581041: Make web intents picker work as constrained dialog instead of InfoBubble (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed review issues Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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" 9 #include "base/bind.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
11 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/ui/browser.h" 12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_window.h" 13 #include "chrome/browser/ui/browser_window.h"
14 #import "chrome/browser/ui/cocoa/browser_window_controller.h" 14 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
15 #include "chrome/browser/ui/cocoa/constrained_window_mac.h"
15 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h" 16 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
16 #import "chrome/browser/ui/cocoa/web_intent_bubble_controller.h" 17 #import "chrome/browser/ui/cocoa/web_intent_sheet_controller.h"
17 #include "chrome/browser/ui/intents/web_intent_inline_disposition_delegate.h" 18 #include "chrome/browser/ui/intents/web_intent_inline_disposition_delegate.h"
18 #include "chrome/browser/ui/intents/web_intent_picker.h" 19 #include "chrome/browser/ui/intents/web_intent_picker.h"
19 #include "chrome/browser/ui/intents/web_intent_picker_delegate.h" 20 #include "chrome/browser/ui/intents/web_intent_picker_delegate.h"
20 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 21 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
21 #include "content/public/browser/web_contents.h" 22 #include "content/public/browser/web_contents.h"
22 #include "skia/ext/skia_utils_mac.h" 23 #include "skia/ext/skia_utils_mac.h"
23 #include "ui/gfx/image/image.h" 24 #include "ui/gfx/image/image.h"
24 25
25 using content::WebContents; 26 using content::WebContents;
26 27
28 namespace {
29
30 // Since any delegates for constrained windows are tasked with deleting
31 // themselves, and the WebIntentPicker needs to live longer than the
32 // constrained window, we need this forwarding class.
33 class ConstrainedPickerSheetDelegate :
34 public ConstrainedWindowMacDelegateCustomSheet {
35 public:
36 ConstrainedPickerSheetDelegate(
37 WebIntentPickerCocoa* picker,
38 WebIntentPickerSheetController* sheet_controller);
39 virtual ~ConstrainedPickerSheetDelegate() {}
40
41 // ConstrainedWindowMacDelegateCustomSheet interface
42 virtual void DeleteDelegate() OVERRIDE;
43
44 private:
45 WebIntentPickerCocoa* picker_; // Weak reference to picker
46
47 DISALLOW_COPY_AND_ASSIGN(ConstrainedPickerSheetDelegate);
48 };
49
50 ConstrainedPickerSheetDelegate::ConstrainedPickerSheetDelegate(
51 WebIntentPickerCocoa* picker,
52 WebIntentPickerSheetController* sheet_controller)
53 : picker_(picker) {
54 init([sheet_controller window], sheet_controller,
55 @selector(sheetDidEnd:returnCode:contextInfo:));
56 set_sheet([sheet_controller window]);
Nico 2012/03/06 22:56:26 init() already sets the sheet, so this line should
groby-ooo-7-16 2012/03/07 00:50:42 Done.
57 }
58
59 void ConstrainedPickerSheetDelegate::DeleteDelegate() {
60 if (is_sheet_open())
61 [NSApp endSheet:sheet()];
62
63 if (picker_)
64 picker_->OnCancelled();
65
66 delete this;
67 }
68
69 } // namespace
70
27 // static 71 // static
28 WebIntentPicker* WebIntentPicker::Create(Browser* browser, 72 WebIntentPicker* WebIntentPicker::Create(Browser* browser,
29 TabContentsWrapper* wrapper, 73 TabContentsWrapper* wrapper,
30 WebIntentPickerDelegate* delegate, 74 WebIntentPickerDelegate* delegate,
31 WebIntentPickerModel* model) { 75 WebIntentPickerModel* model) {
32 return new WebIntentPickerCocoa(browser, wrapper, delegate, model); 76 return new WebIntentPickerCocoa(browser, wrapper, delegate, model);
33 } 77 }
34 78
35 WebIntentPickerCocoa::WebIntentPickerCocoa() 79 WebIntentPickerCocoa::WebIntentPickerCocoa()
36 : delegate_(NULL), 80 : delegate_(NULL),
37 model_(NULL), 81 model_(NULL),
38 browser_(NULL), 82 browser_(NULL),
39 controller_(nil), 83 sheet_controller_(nil),
40 weak_ptr_factory_(this),
41 service_invoked(false) { 84 service_invoked(false) {
42 } 85 }
43 86
44
45 WebIntentPickerCocoa::WebIntentPickerCocoa(Browser* browser, 87 WebIntentPickerCocoa::WebIntentPickerCocoa(Browser* browser,
46 TabContentsWrapper* wrapper, 88 TabContentsWrapper* wrapper,
47 WebIntentPickerDelegate* delegate, 89 WebIntentPickerDelegate* delegate,
48 WebIntentPickerModel* model) 90 WebIntentPickerModel* model)
49 : delegate_(delegate), 91 : delegate_(delegate),
50 model_(model), 92 model_(model),
51 browser_(browser), 93 browser_(browser),
52 controller_(nil), 94 sheet_controller_(nil),
53 weak_ptr_factory_(this), 95 service_invoked(false) {
54 service_invoked(false) {
55 model_->set_observer(this); 96 model_->set_observer(this);
56 97
57 DCHECK(browser);
58 DCHECK(delegate); 98 DCHECK(delegate);
59 NSWindow* parentWindow = browser->window()->GetNativeHandle(); 99 DCHECK(wrapper);
60 100
61 // Compute the anchor point, relative to location bar. 101 sheet_controller_ = [
62 BrowserWindowController* controller = [parentWindow windowController]; 102 [WebIntentPickerSheetController alloc] initWithPicker:this];
63 LocationBarViewMac* locationBar = [controller locationBarBridge];
64 NSPoint anchor = locationBar->GetPageInfoBubblePoint();
65 anchor = [browser->window()->GetNativeHandle() convertBaseToScreen:anchor];
66 103
67 // The controller is deallocated when the window is closed, so no need to 104 // Deleted when ConstrainedPickerSheetDelegate::DeleteDelegate() runs.
68 // worry about it here. 105 ConstrainedPickerSheetDelegate* constrained_delegate =
69 [[WebIntentBubbleController alloc] initWithPicker:this 106 new ConstrainedPickerSheetDelegate(this, sheet_controller_);
70 parentWindow:parentWindow 107
71 anchoredAt:anchor]; 108 window_ = new ConstrainedWindowMac(wrapper, constrained_delegate);
72 } 109 }
73 110
74 WebIntentPickerCocoa::~WebIntentPickerCocoa() { 111 WebIntentPickerCocoa::~WebIntentPickerCocoa() {
75 if (model_ != NULL) 112 if (model_ != NULL)
76 model_->set_observer(NULL); 113 model_->set_observer(NULL);
77 } 114 }
78 115
116 void WebIntentPickerCocoa::OnSheetDidEnd(NSWindow* sheet) {
117 [sheet orderOut:sheet_controller_];
118 if (window_)
119 window_->CloseConstrainedWindow();
120 }
121
79 void WebIntentPickerCocoa::Close() { 122 void WebIntentPickerCocoa::Close() {
80 DCHECK(controller_); 123 DCHECK(sheet_controller_);
81 [controller_ close]; 124 [sheet_controller_ closeSheet];
125
82 if (inline_disposition_tab_contents_.get()) 126 if (inline_disposition_tab_contents_.get())
83 inline_disposition_tab_contents_->web_contents()->OnCloseStarted(); 127 inline_disposition_tab_contents_->web_contents()->OnCloseStarted();
84 } 128 }
85 129
86 void WebIntentPickerCocoa::PerformDelayedLayout() {
87 // Check to see if a layout has already been scheduled.
88 if (weak_ptr_factory_.HasWeakPtrs())
89 return;
90
91 // Delay performing layout by a second so that all the animations from
92 // InfoBubbleWindow and origin updates from BaseBubbleController finish, so
93 // that we don't all race trying to change the frame's origin.
94 //
95 // Using MessageLoop is superior here to |-performSelector:| because it will
96 // not retain its target; if the child outlives its parent, zombies get left
97 // behind (http://crbug.com/59619). This will cancel the scheduled task if
98 // the controller get destroyed before the message
99 // can be delivered.
100 MessageLoop::current()->PostDelayedTask(FROM_HERE,
101 base::Bind(&WebIntentPickerCocoa::PerformLayout,
102 weak_ptr_factory_.GetWeakPtr()),
103 100 /* milliseconds */);
104 }
105
106 void WebIntentPickerCocoa::PerformLayout() { 130 void WebIntentPickerCocoa::PerformLayout() {
107 DCHECK(controller_); 131 DCHECK(sheet_controller_);
108 // If the window is animating closed when this is called, the 132 // If the window is animating closed when this is called, the
109 // animation could be holding the last reference to |controller_| 133 // animation could be holding the last reference to |controller_|
110 // (and thus |this|). Pin it until the task is completed. 134 // (and thus |this|). Pin it until the task is completed.
111 scoped_nsobject<WebIntentBubbleController> keep_alive([controller_ retain]); 135 scoped_nsobject<WebIntentPickerSheetController>
112 [controller_ performLayoutWithModel:model_]; 136 keep_alive([sheet_controller_ retain]);
137 [sheet_controller_ performLayoutWithModel:model_];
113 } 138 }
114 139
115 void WebIntentPickerCocoa::OnModelChanged(WebIntentPickerModel* model) { 140 void WebIntentPickerCocoa::OnModelChanged(WebIntentPickerModel* model) {
116 PerformDelayedLayout(); 141 PerformLayout();
117 } 142 }
118 143
119 void WebIntentPickerCocoa::OnFaviconChanged(WebIntentPickerModel* model, 144 void WebIntentPickerCocoa::OnFaviconChanged(WebIntentPickerModel* model,
120 size_t index) { 145 size_t index) {
121 // We don't handle individual icon changes - just redo the whole model. 146 // We don't handle individual icon changes - just redo the whole model.
122 PerformDelayedLayout(); 147 PerformLayout();
123 } 148 }
124 149
125 void WebIntentPickerCocoa::OnExtensionIconChanged( 150 void WebIntentPickerCocoa::OnExtensionIconChanged(
126 WebIntentPickerModel* model, 151 WebIntentPickerModel* model,
127 const string16& extension_id) { 152 const string16& extension_id) {
128 // TODO(binji): implement. 153 // TODO(binji): implement.
129 } 154 }
130 155
131 void WebIntentPickerCocoa::OnInlineDisposition(WebIntentPickerModel* model) { 156 void WebIntentPickerCocoa::OnInlineDisposition(WebIntentPickerModel* model) {
157 DCHECK(browser_);
132 const WebIntentPickerModel::InstalledService& installed_service = 158 const WebIntentPickerModel::InstalledService& installed_service =
133 model->GetInstalledServiceAt(model->inline_disposition_index()); 159 model->GetInstalledServiceAt(model->inline_disposition_index());
134 160
135 content::WebContents* web_contents = content::WebContents::Create( 161 content::WebContents* web_contents = content::WebContents::Create(
136 browser_->profile(), NULL, MSG_ROUTING_NONE, NULL, NULL); 162 browser_->profile(), NULL, MSG_ROUTING_NONE, NULL, NULL);
137 inline_disposition_tab_contents_.reset(new TabContentsWrapper(web_contents)); 163 inline_disposition_tab_contents_.reset(new TabContentsWrapper(web_contents));
138 inline_disposition_delegate_.reset(new WebIntentInlineDispositionDelegate); 164 inline_disposition_delegate_.reset(new WebIntentInlineDispositionDelegate);
139 web_contents->SetDelegate(inline_disposition_delegate_.get()); 165 web_contents->SetDelegate(inline_disposition_delegate_.get());
140 166
141 // Must call this immediately after WebContents creation to avoid race 167 // Must call this immediately after WebContents creation to avoid race
142 // with load. 168 // with load.
143 delegate_->OnInlineDispositionWebContentsCreated(web_contents); 169 delegate_->OnInlineDispositionWebContentsCreated(web_contents);
144 170
145 inline_disposition_tab_contents_->web_contents()->GetController().LoadURL( 171 inline_disposition_tab_contents_->web_contents()->GetController().LoadURL(
146 installed_service.url, 172 installed_service.url,
147 content::Referrer(), 173 content::Referrer(),
148 content::PAGE_TRANSITION_START_PAGE, 174 content::PAGE_TRANSITION_START_PAGE,
149 std::string()); 175 std::string());
150 176
151 [controller_ setInlineDispositionTabContents: 177 [sheet_controller_ setInlineDispositionTabContents:
152 inline_disposition_tab_contents_.get()]; 178 inline_disposition_tab_contents_.get()];
153 PerformDelayedLayout(); 179 PerformLayout();
154 } 180 }
155 181
156 void WebIntentPickerCocoa::OnCancelled() { 182 void WebIntentPickerCocoa::OnCancelled() {
157 DCHECK(delegate_); 183 DCHECK(delegate_);
158 if (!service_invoked) 184 if (!service_invoked)
159 delegate_->OnCancelled(); 185 delegate_->OnCancelled();
160 delegate_->OnClosing(); 186 delegate_->OnClosing();
161 MessageLoop::current()->DeleteSoon(FROM_HERE, this); 187 MessageLoop::current()->DeleteSoon(FROM_HERE, this);
162 } 188 }
163 189
164 void WebIntentPickerCocoa::OnServiceChosen(size_t index) { 190 void WebIntentPickerCocoa::OnServiceChosen(size_t index) {
165 DCHECK(delegate_); 191 DCHECK(delegate_);
166 const WebIntentPickerModel::InstalledService& installed_service = 192 const WebIntentPickerModel::InstalledService& installed_service =
167 model_->GetInstalledServiceAt(index); 193 model_->GetInstalledServiceAt(index);
168 service_invoked = true; 194 service_invoked = true;
169 delegate_->OnServiceChosen(index, installed_service.disposition); 195 delegate_->OnServiceChosen(index, installed_service.disposition);
170 } 196 }
171 197
172 void WebIntentPickerCocoa::set_controller(
173 WebIntentBubbleController* controller) {
174 controller_ = controller;
175 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/web_intent_picker_cocoa.h ('k') | chrome/browser/ui/cocoa/web_intent_sheet_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698