15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/tab_contents/background_contents.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/background/background_contents_service.h"
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/renderer_preferences_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/public/browser/session_storage_namespace.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/site_instance.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "extensions/browser/view_type_utils.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::SiteInstance;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)BackgroundContents::BackgroundContents(
263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    SiteInstance* site_instance,
273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int routing_id,
283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    Delegate* delegate,
293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const std::string& partition_id,
303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    content::SessionStorageNamespace* session_storage_namespace)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : delegate_(delegate) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_ = Profile::FromBrowserContext(
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      site_instance->GetBrowserContext());
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WebContents::CreateParams create_params(profile_, site_instance);
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  create_params.routing_id = routing_id;
373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (session_storage_namespace) {
383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    content::SessionStorageNamespaceMap session_storage_namespace_map;
393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    session_storage_namespace_map.insert(
403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        std::make_pair(partition_id, session_storage_namespace));
413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    web_contents_.reset(WebContents::CreateWithSessionStorage(
423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        create_params, session_storage_namespace_map));
433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else {
443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    web_contents_.reset(WebContents::Create(create_params));
453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  extensions::SetViewType(
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      web_contents_.get(), extensions::VIEW_TYPE_BACKGROUND_CONTENTS);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_contents_->SetDelegate(this);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::WebContentsObserver::Observe(web_contents_.get());
5023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      web_contents_.get());
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close ourselves when the application is shutting down.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllSources());
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register for our parent profile to shutdown, so we can shut ourselves down
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as well (should only be called for OTR profiles, as we should receive
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // APP_TERMINATING before non-OTR profiles are destroyed).
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::Source<Profile>(profile_));
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Exposed to allow creating mocks.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BackgroundContents::BackgroundContents()
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : delegate_(NULL),
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_(NULL) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BackgroundContents::~BackgroundContents() {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!web_contents_.get())   // Will be null for unit tests.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Unregister for any notifications before notifying observers that we are
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // going away - this prevents any re-entrancy due to chained notifications
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // (http://crbug.com/237781).
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  registrar_.RemoveAll();
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationService::current()->Notify(
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<Profile>(profile_),
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Details<BackgroundContents>(this));
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const GURL& BackgroundContents::GetURL() const {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return web_contents_.get() ? web_contents_->GetURL() : GURL::EmptyGURL();
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundContents::CloseContents(WebContents* source) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationService::current()->Notify(
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NOTIFICATION_BACKGROUND_CONTENTS_CLOSED,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<Profile>(profile_),
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Details<BackgroundContents>(this));
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete this;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BackgroundContents::ShouldSuppressDialogs() {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundContents::DidNavigateMainFramePostCommit(WebContents* tab) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: because BackgroundContents are only available to extension apps,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // navigation is limited to urls within the app's extent. This is enforced in
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RenderView::decidePolicyForNavigation. If BackgroundContents become
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // available as a part of the web platform, it probably makes sense to have
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // some way to scope navigation of a background page to its opener's security
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // origin. Note: if the first navigation is to a URL outside the app's
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extent a background page will be opened but will remain at about:blank.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationService::current()->Notify(
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<Profile>(profile_),
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Details<BackgroundContents>(this));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Forward requests to add a new WebContents to our delegate.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundContents::AddNewContents(WebContents* source,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        WebContents* new_contents,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        WindowOpenDisposition disposition,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const gfx::Rect& initial_pos,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        bool user_gesture,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        bool* was_blocked) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_->AddWebContents(
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_contents, disposition, initial_pos, user_gesture, was_blocked);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool BackgroundContents::IsNeverVisible(content::WebContents* web_contents) {
1270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK_EQ(extensions::VIEW_TYPE_BACKGROUND_CONTENTS,
1280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            extensions::GetViewType(web_contents));
1290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return true;
1300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid BackgroundContents::RenderProcessGone(base::TerminationStatus status) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationService::current()->Notify(
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<Profile>(profile_),
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Details<BackgroundContents>(this));
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Our RenderView went away, so we should go away also, so killing the process
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // via the TaskManager doesn't permanently leave a BackgroundContents hanging
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // around the system, blocking future instances from being created
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // <http://crbug.com/65189>.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete this;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundContents::Observe(int type,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const content::NotificationSource& source,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const content::NotificationDetails& details) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(rafaelw): Implement pagegroup ref-counting so that non-persistent
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // background pages are closed when the last referencing frame is closed.
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_PROFILE_DESTROYED:
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_APP_TERMINATING: {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete this;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Unexpected notification sent.";
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
161