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

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: Removed unneeded code 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 }
57
58 void ConstrainedPickerSheetDelegate::DeleteDelegate() {
59 if (is_sheet_open())
60 [NSApp endSheet:sheet()];
61
62 if (picker_)
63 picker_->OnCancelled();
64
65 delete this;
66 }
67
68 } // namespace
69
27 // static 70 // static
28 WebIntentPicker* WebIntentPicker::Create(Browser* browser, 71 WebIntentPicker* WebIntentPicker::Create(Browser* browser,
29 TabContentsWrapper* wrapper, 72 TabContentsWrapper* wrapper,
30 WebIntentPickerDelegate* delegate, 73 WebIntentPickerDelegate* delegate,
31 WebIntentPickerModel* model) { 74 WebIntentPickerModel* model) {
32 return new WebIntentPickerCocoa(browser, wrapper, delegate, model); 75 return new WebIntentPickerCocoa(browser, wrapper, delegate, model);
33 } 76 }
34 77
35 WebIntentPickerCocoa::WebIntentPickerCocoa() 78 WebIntentPickerCocoa::WebIntentPickerCocoa()
36 : delegate_(NULL), 79 : delegate_(NULL),
37 model_(NULL), 80 model_(NULL),
38 browser_(NULL), 81 browser_(NULL),
39 controller_(nil), 82 sheet_controller_(nil),
40 weak_ptr_factory_(this),
41 service_invoked(false) { 83 service_invoked(false) {
42 } 84 }
43 85
44
45 WebIntentPickerCocoa::WebIntentPickerCocoa(Browser* browser, 86 WebIntentPickerCocoa::WebIntentPickerCocoa(Browser* browser,
46 TabContentsWrapper* wrapper, 87 TabContentsWrapper* wrapper,
47 WebIntentPickerDelegate* delegate, 88 WebIntentPickerDelegate* delegate,
48 WebIntentPickerModel* model) 89 WebIntentPickerModel* model)
49 : delegate_(delegate), 90 : delegate_(delegate),
50 model_(model), 91 model_(model),
51 browser_(browser), 92 browser_(browser),
52 controller_(nil), 93 sheet_controller_(nil),
53 weak_ptr_factory_(this), 94 service_invoked(false) {
54 service_invoked(false) {
55 model_->set_observer(this); 95 model_->set_observer(this);
56 96
57 DCHECK(browser);
58 DCHECK(delegate); 97 DCHECK(delegate);
59 NSWindow* parentWindow = browser->window()->GetNativeHandle(); 98 DCHECK(wrapper);
60 99
61 // Compute the anchor point, relative to location bar. 100 sheet_controller_ = [
62 BrowserWindowController* controller = [parentWindow windowController]; 101 [WebIntentPickerSheetController alloc] initWithPicker:this];
63 LocationBarViewMac* locationBar = [controller locationBarBridge];
64 NSPoint anchor = locationBar->GetPageInfoBubblePoint();
65 anchor = [browser->window()->GetNativeHandle() convertBaseToScreen:anchor];
66 102
67 // The controller is deallocated when the window is closed, so no need to 103 // Deleted when ConstrainedPickerSheetDelegate::DeleteDelegate() runs.
68 // worry about it here. 104 ConstrainedPickerSheetDelegate* constrained_delegate =
69 [[WebIntentBubbleController alloc] initWithPicker:this 105 new ConstrainedPickerSheetDelegate(this, sheet_controller_);
70 parentWindow:parentWindow 106
71 anchoredAt:anchor]; 107 window_ = new ConstrainedWindowMac(wrapper, constrained_delegate);
72 } 108 }
73 109
74 WebIntentPickerCocoa::~WebIntentPickerCocoa() { 110 WebIntentPickerCocoa::~WebIntentPickerCocoa() {
75 if (model_ != NULL) 111 if (model_ != NULL)
76 model_->set_observer(NULL); 112 model_->set_observer(NULL);
77 } 113 }
78 114
115 void WebIntentPickerCocoa::OnSheetDidEnd(NSWindow* sheet) {
116 [sheet orderOut:sheet_controller_];
117 if (window_)
118 window_->CloseConstrainedWindow();
119 }
120
79 void WebIntentPickerCocoa::Close() { 121 void WebIntentPickerCocoa::Close() {
80 DCHECK(controller_); 122 DCHECK(sheet_controller_);
81 [controller_ close]; 123 [sheet_controller_ closeSheet];
124
82 if (inline_disposition_tab_contents_.get()) 125 if (inline_disposition_tab_contents_.get())
83 inline_disposition_tab_contents_->web_contents()->OnCloseStarted(); 126 inline_disposition_tab_contents_->web_contents()->OnCloseStarted();
84 } 127 }
85 128
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() { 129 void WebIntentPickerCocoa::PerformLayout() {
107 DCHECK(controller_); 130 DCHECK(sheet_controller_);
108 // If the window is animating closed when this is called, the 131 // If the window is animating closed when this is called, the
109 // animation could be holding the last reference to |controller_| 132 // animation could be holding the last reference to |controller_|
110 // (and thus |this|). Pin it until the task is completed. 133 // (and thus |this|). Pin it until the task is completed.
111 scoped_nsobject<WebIntentBubbleController> keep_alive([controller_ retain]); 134 scoped_nsobject<WebIntentPickerSheetController>
112 [controller_ performLayoutWithModel:model_]; 135 keep_alive([sheet_controller_ retain]);
136 [sheet_controller_ performLayoutWithModel:model_];
113 } 137 }
114 138
115 void WebIntentPickerCocoa::OnModelChanged(WebIntentPickerModel* model) { 139 void WebIntentPickerCocoa::OnModelChanged(WebIntentPickerModel* model) {
116 PerformDelayedLayout(); 140 PerformLayout();
117 } 141 }
118 142
119 void WebIntentPickerCocoa::OnFaviconChanged(WebIntentPickerModel* model, 143 void WebIntentPickerCocoa::OnFaviconChanged(WebIntentPickerModel* model,
120 size_t index) { 144 size_t index) {
121 // We don't handle individual icon changes - just redo the whole model. 145 // We don't handle individual icon changes - just redo the whole model.
122 PerformDelayedLayout(); 146 PerformLayout();
123 } 147 }
124 148
125 void WebIntentPickerCocoa::OnExtensionIconChanged( 149 void WebIntentPickerCocoa::OnExtensionIconChanged(
126 WebIntentPickerModel* model, 150 WebIntentPickerModel* model,
127 const string16& extension_id) { 151 const string16& extension_id) {
128 // TODO(binji): implement. 152 // TODO(binji): implement.
129 } 153 }
130 154
131 void WebIntentPickerCocoa::OnInlineDisposition(WebIntentPickerModel* model) { 155 void WebIntentPickerCocoa::OnInlineDisposition(WebIntentPickerModel* model) {
156 DCHECK(browser_);
132 const WebIntentPickerModel::InstalledService& installed_service = 157 const WebIntentPickerModel::InstalledService& installed_service =
133 model->GetInstalledServiceAt(model->inline_disposition_index()); 158 model->GetInstalledServiceAt(model->inline_disposition_index());
134 159
135 content::WebContents* web_contents = content::WebContents::Create( 160 content::WebContents* web_contents = content::WebContents::Create(
136 browser_->profile(), NULL, MSG_ROUTING_NONE, NULL, NULL); 161 browser_->profile(), NULL, MSG_ROUTING_NONE, NULL, NULL);
137 inline_disposition_tab_contents_.reset(new TabContentsWrapper(web_contents)); 162 inline_disposition_tab_contents_.reset(new TabContentsWrapper(web_contents));
138 inline_disposition_delegate_.reset(new WebIntentInlineDispositionDelegate); 163 inline_disposition_delegate_.reset(new WebIntentInlineDispositionDelegate);
139 web_contents->SetDelegate(inline_disposition_delegate_.get()); 164 web_contents->SetDelegate(inline_disposition_delegate_.get());
140 165
141 // Must call this immediately after WebContents creation to avoid race 166 // Must call this immediately after WebContents creation to avoid race
142 // with load. 167 // with load.
143 delegate_->OnInlineDispositionWebContentsCreated(web_contents); 168 delegate_->OnInlineDispositionWebContentsCreated(web_contents);
144 169
145 inline_disposition_tab_contents_->web_contents()->GetController().LoadURL( 170 inline_disposition_tab_contents_->web_contents()->GetController().LoadURL(
146 installed_service.url, 171 installed_service.url,
147 content::Referrer(), 172 content::Referrer(),
148 content::PAGE_TRANSITION_START_PAGE, 173 content::PAGE_TRANSITION_START_PAGE,
149 std::string()); 174 std::string());
150 175
151 [controller_ setInlineDispositionTabContents: 176 [sheet_controller_ setInlineDispositionTabContents:
152 inline_disposition_tab_contents_.get()]; 177 inline_disposition_tab_contents_.get()];
153 PerformDelayedLayout(); 178 PerformLayout();
154 } 179 }
155 180
156 void WebIntentPickerCocoa::OnCancelled() { 181 void WebIntentPickerCocoa::OnCancelled() {
157 DCHECK(delegate_); 182 DCHECK(delegate_);
158 if (!service_invoked) 183 if (!service_invoked)
159 delegate_->OnCancelled(); 184 delegate_->OnCancelled();
160 delegate_->OnClosing(); 185 delegate_->OnClosing();
161 MessageLoop::current()->DeleteSoon(FROM_HERE, this); 186 MessageLoop::current()->DeleteSoon(FROM_HERE, this);
162 } 187 }
163 188
164 void WebIntentPickerCocoa::OnServiceChosen(size_t index) { 189 void WebIntentPickerCocoa::OnServiceChosen(size_t index) {
165 DCHECK(delegate_); 190 DCHECK(delegate_);
166 const WebIntentPickerModel::InstalledService& installed_service = 191 const WebIntentPickerModel::InstalledService& installed_service =
167 model_->GetInstalledServiceAt(index); 192 model_->GetInstalledServiceAt(index);
168 service_invoked = true; 193 service_invoked = true;
169 delegate_->OnServiceChosen(index, installed_service.disposition); 194 delegate_->OnServiceChosen(index, installed_service.disposition);
170 } 195 }
171 196
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