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

Side by Side Diff: chrome/browser/tab_contents/introducer_handler.cc

Issue 6880275: Web Introducer overview Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 9 years, 8 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
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/tab_contents/introducer_handler.h"
6
7 #include "chrome/app/chrome_command_ids.h"
8 #include "chrome/browser/prefs/pref_service.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
11 #include "chrome/browser/tabs/tab_strip_model.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_list.h"
14 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
15 #include "chrome/common/pref_names.h"
16 #include "content/browser/tab_contents/tab_contents.h"
17 #include "content/browser/renderer_host/render_process_host.h"
18 #include "content/browser/renderer_host/render_view_host.h"
19 #include "content/browser/tab_contents/tab_contents_observer.h"
20 #include "content/browser/worker_host/message_port_service.h"
21 #include "content/common/introducer_messages.h"
22 #include "grit/generated_resources.h"
23 #include "net/base/data_url.h"
24 #include "ui/base/l10n/l10n_util.h"
25 #include "ui/base/models/simple_menu_model.h"
26 #include "ui/gfx/favicon_size.h"
27 #include "webkit/glue/context_menu.h"
28 #include "webkit/glue/image_decoder.h"
29
30 static SkBitmap ImageFromDataUrl(const GURL& icon) {
31 std::string mime_type, charset, data;
32 if (!net::DataURL::Parse(icon, &mime_type, &charset, &data)) {
33 return SkBitmap();
34 }
35 webkit_glue::ImageDecoder decoder(gfx::Size(kFaviconSize, kFaviconSize));
36 return decoder.Decode(reinterpret_cast<const unsigned char*>(data.data()),
37 data.size());
38 }
39
40 static void InstallReturn(TabContents* tab, int request_id, bool accepted) {
41 RenderViewHost* host = tab->render_view_host();
42 if (host) {
43 host->Send(new IntroducerMsg_InstallReturn(host->routing_id(),
44 request_id, accepted));
45 }
46 }
47
48 static bool UpdateRegistration(TabContents* tab,
49 const std::string& registrant, const GURL& icon,
50 const string16& name, const GURL& home) {
51 Profile* profile = tab->profile();
52 PrefService* prefs = profile->IsOffTheRecord() ?
53 profile->GetOffTheRecordPrefs() : profile->GetPrefs();
54 DictionaryValue* registrations =
55 prefs->GetMutableDictionary(prefs::kIntroducerRegistrations);
56 if (!registrations) { return false; }
57 DictionaryValue* registration = NULL;
58 if (!registrations->GetDictionaryWithoutPathExpansion(registrant,
59 &registration)) {
60 registration = new DictionaryValue();
61 registrations->SetWithoutPathExpansion(registrant, registration);
62 }
63 registration->SetString("icon", icon.spec());
64 registration->SetString("name", name);
65 registration->SetString("home", home.spec());
66 if (!profile->IsOffTheRecord()) {
67 prefs->ScheduleSavePersistentPrefs();
68 }
69 return true;
70 }
71
72 class InstallInfoBar : public ConfirmInfoBarDelegate {
73 public:
74 InstallInfoBar(
75 TabContents* tab,
76 int request_id,
77 const std::string& registrant,
78 const GURL& icon,
79 const string16& name,
80 const GURL& home) :
81 ConfirmInfoBarDelegate(tab),
82 tab_(tab),
83 request_id_(request_id),
84 registrant_(registrant),
85 icon_(icon),
86 name_(name),
87 home_(home),
88 decoded_icon_(ImageFromDataUrl(icon)) {}
89
90 virtual void InfoBarClosed() { delete this; }
91 virtual SkBitmap* GetIcon() const {
92 return const_cast<SkBitmap*>(&decoded_icon_);
93 }
94 virtual string16 GetMessageText() const {
95 return l10n_util::GetStringFUTF16(IDS_INTRODUCER_INSTALL_QUESTION, name_);
96 }
97 virtual bool Accept() {
98 if (!UpdateRegistration(tab_, registrant_, icon_, name_, home_)) {
99 return false;
100 }
101 InstallReturn(tab_, request_id_, true);
102 return true;
103 }
104 virtual bool Cancel() {
105 InstallReturn(tab_, request_id_, false);
106 return true;
107 }
108
109 private:
110 TabContents* tab_;
111 const int request_id_;
112 const std::string registrant_;
113 const GURL icon_;
114 const string16 name_;
115 const GURL home_;
116 SkBitmap decoded_icon_;
117
118 DISALLOW_COPY_AND_ASSIGN(InstallInfoBar);
119 };
120
121 struct AcceptContext {
122 webkit_glue::IntroductionContext introduction;
123 std::string expected_registrant;
124 int customer_render_process_id;
125 int customer_render_view_id;
126 scoped_ptr<IPC::Message> connect_return;
127
128 AcceptContext() : customer_render_process_id(0),
129 customer_render_view_id(0) {}
130 };
131
132 class IntroducerHandler : public TabContentsObserver {
133 public:
134 explicit IntroducerHandler(TabContents* tab) : TabContentsObserver(tab) {}
135 virtual ~IntroducerHandler() {}
136
137 virtual bool OnMessageReceived(const IPC::Message& message) {
138 bool handled = true;
139
140 IPC_BEGIN_MESSAGE_MAP(IntroducerHandler, message)
141 IPC_MESSAGE_HANDLER(IntroducerHostMsg_Install, OnInstall)
142 IPC_MESSAGE_HANDLER(IntroducerHostMsg_Uninstall, OnUninstall)
143 IPC_MESSAGE_HANDLER(IntroducerHostMsg_Offer, OnOffer)
144 IPC_MESSAGE_HANDLER(IntroducerHostMsg_Rescind, OnRescind)
145 IPC_MESSAGE_HANDLER(IntroducerHostMsg_Connect, OnConnect)
146 IPC_MESSAGE_HANDLER(IntroducerHostMsg_Accept, OnAccept)
147 IPC_MESSAGE_UNHANDLED(handled = false)
148 IPC_END_MESSAGE_MAP()
149
150 return handled;
151 }
152
153 private:
154
155 void OnInstall(const IPC::Message& message, int request_id,
156 const std::string& registrant, const GURL& icon,
157 const string16& name, const GURL& home) {
158 TabContents* tab = tab_contents();
159 Profile* profile = tab->profile();
160 PrefService* prefs = profile->IsOffTheRecord() ?
161 profile->GetOffTheRecordPrefs() : profile->GetPrefs();
162 const DictionaryValue* registrations =
163 prefs->GetDictionary(prefs::kIntroducerRegistrations);
164 DictionaryValue* registration = NULL;
165 std::string prior_icon;
166 string16 prior_name;
167 if (!registrations ||
168 !registrations->GetDictionaryWithoutPathExpansion(registrant,
169 &registration) ||
170 !registration->GetString("icon", &prior_icon) ||
171 prior_icon != icon.spec() ||
172 !registration->GetString("name", &prior_name) ||
173 prior_name != name) {
174 tab->AddInfoBar(new InstallInfoBar(tab, request_id,
175 registrant, icon, name, home));
176 } else {
177 InstallReturn(tab, request_id,
178 UpdateRegistration(tab, registrant, icon, name, home));
179 }
180 }
181
182 void OnUninstall(const IPC::Message& message, int request_id,
183 const std::string& registrant) {
184 TabContents* tab = tab_contents();
185 Profile* profile = tab->profile();
186 PrefService* prefs = profile->IsOffTheRecord() ?
187 profile->GetOffTheRecordPrefs() : profile->GetPrefs();
188 DictionaryValue* registrations =
189 prefs->GetMutableDictionary(prefs::kIntroducerRegistrations);
190 if (registrations) {
191 registrations->RemoveWithoutPathExpansion(registrant, NULL);
192 }
193 InstallReturn(tab, request_id, true);
194 }
195
196 void OnOffer(const IPC::Message& message, int request_id,
197 const std::string& registrant,
198 IntroducerHostMsg_Offer_Params args) {
199 TabContents* tab = tab_contents();
200 Profile* profile = tab->profile();
201 PrefService* prefs = profile->IsOffTheRecord() ?
202 profile->GetOffTheRecordPrefs() : profile->GetPrefs();
203 DictionaryValue* registrations =
204 prefs->GetMutableDictionary(prefs::kIntroducerRegistrations);
205 DictionaryValue* registration = NULL;
206 const bool agreed = registrations && registrations->
207 GetDictionaryWithoutPathExpansion(registrant, &registration);
208 if (agreed) {
209 DictionaryValue* services = NULL;
210 if (!registration->GetDictionary("services", &services)) {
211 services = new DictionaryValue();
212 registration->Set("services", services);
213 }
214 DictionaryValue* service = new DictionaryValue();
215 service->SetString("label", args.label);
216 DictionaryValue* supports = new DictionaryValue();
217 for (std::vector<std::string>::iterator i = args.supports.begin(),
218 end = args.supports.end();
219 i != end; ++i) {
220 supports->SetWithoutPathExpansion(*i, Value::CreateNullValue());
221 }
222 service->Set("supports", supports);
223 if (!args.window.is_empty()) {
224 service->SetString("window", args.window.spec());
225 }
226 if (!args.frame.is_empty()) {
227 service->SetString("frame", args.frame.spec());
228 }
229 int hits = 0;
230 DictionaryValue* prior = NULL;
231 if (services->GetDictionaryWithoutPathExpansion(args.id, &prior)) {
232 prior->GetInteger("hits", &hits);
233 }
234 service->SetInteger("hits", hits);
235 services->SetWithoutPathExpansion(args.id, service);
236 if (!profile->IsOffTheRecord()) {
237 prefs->ScheduleSavePersistentPrefs();
238 }
239 }
240 InstallReturn(tab, request_id, agreed);
241 }
242
243 void OnRescind(const IPC::Message& message, int request_id,
244 const std::string& registrant, const std::string& id) {
245 TabContents* tab = tab_contents();
246 Profile* profile = tab->profile();
247 PrefService* prefs = profile->IsOffTheRecord() ?
248 profile->GetOffTheRecordPrefs() : profile->GetPrefs();
249 DictionaryValue* registrations =
250 prefs->GetMutableDictionary(prefs::kIntroducerRegistrations);
251 DictionaryValue* registration = NULL;
252 if (registrations && registrations->
253 GetDictionaryWithoutPathExpansion(registrant, &registration)) {
254 DictionaryValue* services = NULL;
255 if (registration->GetDictionary("services", &services)) {
256 if (services->RemoveWithoutPathExpansion(id, NULL)) {
257 if (!profile->IsOffTheRecord()) {
258 prefs->ScheduleSavePersistentPrefs();
259 }
260 }
261 }
262 }
263 InstallReturn(tab, request_id, true);
264 }
265
266 void OnConnect(const IPC::Message& message, int request_id,
267 const std::string& customer,
268 int64 frame_id,
269 const std::vector<std::string>& wanted,
270 int port_id) {
271 ContextMenuParams params;
272 params.introduction_context.request_id = request_id;
273 params.introduction_context.customer = customer;
274 params.introduction_context.frame_id = frame_id;
275 params.introduction_context.wanted = wanted;
276 params.introduction_context.port_id = port_id;
277 RenderViewHostDelegate::View* view =
278 tab_contents()->render_view_host()->delegate()->GetViewDelegate();
279 if (view) {
280 view->ShowContextMenu(params);
281 } else {
282 IntroducerService::Dismiss(tab_contents(), request_id);
283 }
284 }
285
286 void OnAccept(const IPC::Message& message, int request_id, int64 src,
287 const std::string& registrant, int port_id) {
288 scoped_ptr<AcceptContext> accept_context(pending_[src]);
289 pending_.erase(src);
290 RenderViewHost* service_host = tab_contents()->render_view_host();
291 if (accept_context.get()) {
292 RenderViewHost* customer_host = RenderViewHost::FromID(
293 accept_context->customer_render_process_id,
294 accept_context->customer_render_view_id);
295 if (accept_context->expected_registrant == registrant) {
296 MessagePortService* ports = MessagePortService::GetInstance();
297 ports->Entangle(port_id, accept_context->introduction.port_id);
298 ports->Entangle(accept_context->introduction.port_id, port_id);
299 service_host->Send(new IntroducerMsg_AcceptReturn(
300 service_host->routing_id(), request_id,
301 accept_context->introduction.customer,
302 accept_context->introduction.wanted));
303 if (customer_host) {
304 customer_host->Send(accept_context->connect_return.release());
305 }
306 } else {
307 service_host->Send(new IntroducerMsg_AcceptReturn(
308 service_host->routing_id(), request_id,
309 "", std::vector<std::string>()));
310 if (customer_host) {
311 customer_host->Send(new IntroducerMsg_ConnectReturn(
312 customer_host->routing_id(),
313 accept_context->introduction.request_id,
314 std::vector<std::string>()));
315 }
316 }
317 } else {
318 service_host->Send(new IntroducerMsg_AcceptReturn(
319 service_host->routing_id(), request_id,
320 "", std::vector<std::string>()));
321 }
322 }
323
324 private:
325 friend class IntroducerService;
326 std::map<int64,AcceptContext*> pending_;
327
328 DISALLOW_COPY_AND_ASSIGN(IntroducerHandler);
329 };
330
331 // static
332 TabContentsObserver* IntroducerService::Make(TabContents* tab) {
333 return new IntroducerHandler(tab);
334 }
335
336 // static
337 void IntroducerService::RegisterUserPrefs(PrefService* user_prefs) {
338 if (!user_prefs->FindPreference(prefs::kIntroducerRegistrations)) {
339 user_prefs->RegisterDictionaryPref(prefs::kIntroducerRegistrations);
340 }
341 }
342
343 // static
344 bool IntroducerService::InitMenu(
345 TabContents* tab, Profile* profile,
346 const ContextMenuParams& params,
347 std::map< int, std::pair<std::string,std::string> >* commands,
348 ui::SimpleMenuModel* menu) {
349 const std::vector<std::string>& wanted = params.introduction_context.wanted;
350 if (!wanted.empty()) {
351 PrefService* prefs = profile->IsOffTheRecord() ?
352 profile->GetOffTheRecordPrefs() : profile->GetPrefs();
353 const DictionaryValue* registrations =
354 prefs->GetDictionary(prefs::kIntroducerRegistrations);
355 if (registrations) {
356 int command_id = IDC_INTRODUCER_CONTEXT_CUSTOM_FIRST;
357 std::vector<int> priority;
358 for (DictionaryValue::key_iterator i = registrations->begin_keys(),
359 i_last = registrations->end_keys();
360 command_id < IDC_INTRODUCER_CONTEXT_CUSTOM_LAST && i != i_last; ++i) {
361 DictionaryValue* registration = NULL;
362 if (registrations->GetDictionaryWithoutPathExpansion(*i,
363 &registration)) {
364 SkBitmap icon;
365 DictionaryValue* services = NULL;
366 if (registration->GetDictionary("services", &services)) {
367 for (DictionaryValue::key_iterator j = services->begin_keys(),
368 j_last = services->end_keys();
369 command_id < IDC_INTRODUCER_CONTEXT_CUSTOM_LAST && j != j_last;
370 ++j) {
371 DictionaryValue* service = NULL;
372 if (services->GetDictionaryWithoutPathExpansion(*j, &service)) {
373 if (service->HasKey("window") ||
374 (params.introduction_context.frame_id &&
375 service->HasKey("frame"))) {
376 DictionaryValue* supports = NULL;
377 if (service->GetDictionary("supports", &supports)) {
378 for (std::vector<std::string>::const_iterator
379 k = wanted.begin(),
380 k_last = wanted.end(); k != k_last; ++k) {
381 if (supports->HasKey(*k)) {
382 int hits = 0;
383 service->GetInteger("hits", &hits);
384 int index = menu->GetItemCount();
385 std::vector<int>::iterator l_first = priority.begin(),
386 l = priority.end();
387 for (; l != l_first; --l, --index) {
388 if (*(l - 1) >= hits) {
389 break;
390 }
391 }
392 priority.insert(l, hits);
393 string16 label;
394 service->GetString("label", &label);
395 menu->InsertItemAt(index, command_id, label);
396 if (icon.isNull()) {
397 std::string icon_url;
398 if (registration->GetString("icon", &icon_url)) {
399 icon = ImageFromDataUrl(GURL(icon_url));
400 }
401 }
402 menu->SetIcon(index, icon);
403 (*commands)[command_id] = std::make_pair(*i, *j);
404 command_id += 1;
405 break;
406 }
407 }
408 }
409 }
410 }
411 }
412 }
413 }
414 }
415 }
416 }
417 return 0 != params.introduction_context.request_id;
418 }
419
420 // static
421 bool IntroducerService::Introduce(
422 TabContents* tab, Profile* profile, const ContextMenuParams& params,
423 const std::pair<std::string,std::string>& selection) {
424 PrefService* prefs = profile->IsOffTheRecord() ?
425 profile->GetOffTheRecordPrefs() : profile->GetPrefs();
426 DictionaryValue* registrations =
427 prefs->GetMutableDictionary(prefs::kIntroducerRegistrations);
428 DictionaryValue* registration = NULL;
429 DictionaryValue* services = NULL;
430 DictionaryValue* service = NULL;
431 if (!registrations ||
432 !registrations->GetDictionaryWithoutPathExpansion(selection.first,
433 &registration) ||
434 !registration->GetDictionary("services", &services) ||
435 !services->GetDictionaryWithoutPathExpansion(selection.second,
436 &service)) {
437 return false;
438 }
439 int hits = 0;
440 service->GetInteger("hits", &hits);
441 service->SetInteger("hits", hits + 1);
442 std::vector<std::string> agreed;
443 const std::vector<std::string>& wanted = params.introduction_context.wanted;
444 DictionaryValue* supports = NULL;
445 if (service->GetDictionary("supports", &supports)) {
446 for (std::vector<std::string>::const_iterator i = wanted.begin(),
447 i_last = wanted.end();
448 i != i_last; ++i) {
449 if (supports->HasKey(*i)) {
450 agreed.push_back(*i);
451 }
452 }
453 }
454 if (!profile->IsOffTheRecord()) {
455 prefs->ScheduleSavePersistentPrefs();
456 }
457
458 RenderViewHost* host = tab->render_view_host();
459 if (!host) {
460 return false;
461 }
462 scoped_ptr<AcceptContext> accept_context(new AcceptContext());
463 accept_context->introduction = params.introduction_context;
464 accept_context->expected_registrant = selection.first;
465 accept_context->customer_render_process_id = host->process()->id();
466 accept_context->customer_render_view_id = host->routing_id();
467 accept_context->connect_return.reset(new IntroducerMsg_ConnectReturn(
468 host->routing_id(), params.introduction_context.request_id, agreed));
469
470 std::string frame;
471 if (params.introduction_context.frame_id &&
472 service->GetString("frame", &frame)) {
473 IntroducerHandler* handler =
474 static_cast<IntroducerHandler*>(tab->introducer_handler_.get());
475 handler->pending_[params.introduction_context.frame_id] =
476 accept_context.release();
477 host->Send(new IntroducerMsg_ConnectNavigation(
478 host->routing_id(), params.introduction_context.request_id, GURL(frame)));
479 return true;
480 }
481
482 std::string window;
483 if (service->GetString("window", &window)) {
484 Browser* browser = BrowserList::GetLastActive();
485 if (browser) {
486 TabContentsWrapper* service_tab = browser->CreateTabContentsForURL(
487 GURL(window), GURL(), profile, PageTransition::LINK, false, NULL);
488 browser->tabstrip_model()->AppendTabContents(service_tab, true);
489 IntroducerHandler* handler = static_cast<IntroducerHandler*>(
490 service_tab->tab_contents()->introducer_handler_.get());
491 handler->pending_[0] = accept_context.release();
492 return true;
493 }
494 }
495
496 return false;
497 }
498
499 // static
500 void IntroducerService::Dismiss(TabContents* tab, int request_id) {
501 RenderViewHost* host = tab->render_view_host();
502 if (host) {
503 host->Send(new IntroducerMsg_ConnectReturn(host->routing_id(), request_id,
504 std::vector<std::string>()));
505 }
506 }
OLDNEW
« no previous file with comments | « chrome/browser/tab_contents/introducer_handler.h ('k') | chrome/browser/tab_contents/render_view_context_menu.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698