1// Copyright 2013 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/android/webapps/single_tab_mode_tab_helper.h"
6
7#include "base/lazy_instance.h"
8#include "chrome/browser/android/tab_android.h"
9#include "content/public/browser/browser_thread.h"
10#include "content/public/browser/render_process_host.h"
11#include "content/public/browser/render_view_host.h"
12#include "content/public/browser/web_contents.h"
13
14DEFINE_WEB_CONTENTS_USER_DATA_KEY(SingleTabModeTabHelper);
15
16namespace {
17
18typedef std::pair<int32, int32> RenderWidgetHostID;
19typedef std::set<RenderWidgetHostID> SingleTabIDSet;
20base::LazyInstance<SingleTabIDSet> g_blocked_ids = LAZY_INSTANCE_INITIALIZER;
21
22void AddPairOnIOThread(int32 process_id, int32 routing_id) {
23  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
24  RenderWidgetHostID single_tab_pair(process_id, routing_id);
25  g_blocked_ids.Get().insert(single_tab_pair);
26}
27
28void RemovePairOnIOThread(int32 process_id, int32 routing_id) {
29  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
30  RenderWidgetHostID single_tab_pair(process_id, routing_id);
31  SingleTabIDSet::iterator itr = g_blocked_ids.Get().find(single_tab_pair);
32  DCHECK(itr != g_blocked_ids.Get().end());
33  g_blocked_ids.Get().erase(itr);
34}
35
36void AddPair(content::RenderViewHost* render_view_host) {
37  if (!render_view_host)
38    return;
39
40  int32 process_id = render_view_host->GetProcess()->GetID();
41  int32 routing_id = render_view_host->GetRoutingID();
42  content::BrowserThread::PostTask(
43      content::BrowserThread::IO, FROM_HERE,
44      base::Bind(&AddPairOnIOThread, process_id, routing_id));
45}
46
47void RemovePair(content::RenderViewHost* render_view_host) {
48  if (!render_view_host)
49    return;
50
51  int32 process_id = render_view_host->GetProcess()->GetID();
52  int32 routing_id = render_view_host->GetRoutingID();
53  content::BrowserThread::PostTask(
54      content::BrowserThread::IO, FROM_HERE,
55      base::Bind(&RemovePairOnIOThread, process_id, routing_id));
56}
57
58}  // namespace
59
60SingleTabModeTabHelper::SingleTabModeTabHelper(
61    content::WebContents* web_contents)
62    : content::WebContentsObserver(web_contents),
63      block_all_new_windows_(false) {
64}
65
66SingleTabModeTabHelper::~SingleTabModeTabHelper() {
67}
68
69void SingleTabModeTabHelper::RenderViewCreated(
70    content::RenderViewHost* render_view_host) {
71  if (!block_all_new_windows_)
72    return;
73  AddPair(render_view_host);
74}
75
76void SingleTabModeTabHelper::RenderViewDeleted(
77    content::RenderViewHost* render_view_host) {
78  if (!block_all_new_windows_)
79    return;
80  RemovePair(render_view_host);
81}
82
83void SingleTabModeTabHelper::PermanentlyBlockAllNewWindows() {
84  block_all_new_windows_ = true;
85  AddPair(web_contents()->GetRenderViewHost());
86}
87
88bool SingleTabModeTabHelper::IsRegistered(int32 process_id,
89                                          int32 routing_id) {
90  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
91  RenderWidgetHostID single_tab_pair(process_id, routing_id);
92  SingleTabIDSet::iterator itr = g_blocked_ids.Get().find(single_tab_pair);
93  return itr != g_blocked_ids.Get().end();
94}
95
96void SingleTabModeTabHelper::HandleOpenUrl(const BlockedWindowParams &params) {
97  TabAndroid* tab = TabAndroid::FromWebContents(web_contents());
98  if (!tab)
99    return;
100
101  chrome::NavigateParams nav_params =
102      params.CreateNavigateParams(web_contents());
103  tab->HandlePopupNavigation(&nav_params);
104}
105