Home | History | Annotate | Download | only in tab_contents
      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/background_contents.h"
      6 
      7 #include "chrome/browser/background_contents_service.h"
      8 #include "chrome/browser/extensions/extension_message_service.h"
      9 #include "chrome/browser/profiles/profile.h"
     10 #include "chrome/browser/renderer_preferences_util.h"
     11 #include "chrome/browser/ui/webui/chrome_web_ui_factory.h"
     12 #include "chrome/common/extensions/extension_constants.h"
     13 #include "chrome/common/extensions/extension_messages.h"
     14 #include "chrome/common/url_constants.h"
     15 #include "chrome/common/view_types.h"
     16 #include "content/browser/browsing_instance.h"
     17 #include "content/browser/renderer_host/render_view_host.h"
     18 #include "content/browser/site_instance.h"
     19 #include "content/common/notification_service.h"
     20 #include "content/common/view_messages.h"
     21 #include "ui/gfx/rect.h"
     22 
     23 ////////////////
     24 // BackgroundContents
     25 
     26 BackgroundContents::BackgroundContents(SiteInstance* site_instance,
     27                                        int routing_id,
     28                                        Delegate* delegate)
     29     : delegate_(delegate) {
     30   Profile* profile = site_instance->browsing_instance()->profile();
     31 
     32   // TODO(rafaelw): Implement correct session storage.
     33   render_view_host_ = new RenderViewHost(site_instance, this, routing_id, NULL);
     34 
     35   // Close ourselves when the application is shutting down.
     36   registrar_.Add(this, NotificationType::APP_TERMINATING,
     37                  NotificationService::AllSources());
     38 
     39   // Register for our parent profile to shutdown, so we can shut ourselves down
     40   // as well (should only be called for OTR profiles, as we should receive
     41   // APP_TERMINATING before non-OTR profiles are destroyed).
     42   registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
     43                  Source<Profile>(profile));
     44 }
     45 
     46 // Exposed to allow creating mocks.
     47 BackgroundContents::BackgroundContents()
     48     : delegate_(NULL),
     49       render_view_host_(NULL) {
     50 }
     51 
     52 BackgroundContents::~BackgroundContents() {
     53   if (!render_view_host_)   // Will be null for unit tests.
     54     return;
     55   Profile* profile = render_view_host_->process()->profile();
     56   NotificationService::current()->Notify(
     57       NotificationType::BACKGROUND_CONTENTS_DELETED,
     58       Source<Profile>(profile),
     59       Details<BackgroundContents>(this));
     60   render_view_host_->Shutdown();  // deletes render_view_host
     61 }
     62 
     63 BackgroundContents* BackgroundContents::GetAsBackgroundContents() {
     64   return this;
     65 }
     66 
     67 RenderViewHostDelegate::View* BackgroundContents::GetViewDelegate() {
     68   return this;
     69 }
     70 
     71 const GURL& BackgroundContents::GetURL() const {
     72   return url_;
     73 }
     74 
     75 ViewType::Type BackgroundContents::GetRenderViewType() const {
     76   return ViewType::BACKGROUND_CONTENTS;
     77 }
     78 
     79 int BackgroundContents::GetBrowserWindowID() const {
     80   return extension_misc::kUnknownWindowId;
     81 }
     82 
     83 void BackgroundContents::DidNavigate(
     84     RenderViewHost* render_view_host,
     85     const ViewHostMsg_FrameNavigate_Params& params) {
     86   // We only care when the outer frame changes.
     87   if (!PageTransition::IsMainFrame(params.transition))
     88     return;
     89 
     90   // Note: because BackgroundContents are only available to extension apps,
     91   // navigation is limited to urls within the app's extent. This is enforced in
     92   // RenderView::decidePolicyForNaviation. If BackgroundContents become
     93   // available as a part of the web platform, it probably makes sense to have
     94   // some way to scope navigation of a background page to its opener's security
     95   // origin. Note: if the first navigation is to a URL outside the app's
     96   // extent a background page will be opened but will remain at about:blank.
     97   url_ = params.url;
     98 
     99   Profile* profile = render_view_host->process()->profile();
    100   NotificationService::current()->Notify(
    101       NotificationType::BACKGROUND_CONTENTS_NAVIGATED,
    102       Source<Profile>(profile),
    103       Details<BackgroundContents>(this));
    104 }
    105 
    106 void BackgroundContents::RunJavaScriptMessage(
    107     const std::wstring& message,
    108     const std::wstring& default_prompt,
    109     const GURL& frame_url,
    110     const int flags,
    111     IPC::Message* reply_msg,
    112     bool* did_suppress_message) {
    113   // TODO(rafaelw): Implement, The JavaScriptModalDialog needs to learn about
    114   // BackgroundContents.
    115   *did_suppress_message = true;
    116 }
    117 
    118 bool BackgroundContents::PreHandleKeyboardEvent(
    119     const NativeWebKeyboardEvent& event,
    120     bool* is_keyboard_shortcut) {
    121   return false;
    122 }
    123 
    124 void BackgroundContents::Observe(NotificationType type,
    125                                  const NotificationSource& source,
    126                                  const NotificationDetails& details) {
    127   // TODO(rafaelw): Implement pagegroup ref-counting so that non-persistent
    128   // background pages are closed when the last referencing frame is closed.
    129   switch (type.value) {
    130     case NotificationType::PROFILE_DESTROYED:
    131     case NotificationType::APP_TERMINATING: {
    132       delete this;
    133       break;
    134     }
    135     default:
    136       NOTREACHED() << "Unexpected notification sent.";
    137       break;
    138   }
    139 }
    140 
    141 void BackgroundContents::OnMessageBoxClosed(IPC::Message* reply_msg,
    142                                             bool success,
    143                                             const std::wstring& prompt) {
    144   render_view_host_->JavaScriptMessageBoxClosed(reply_msg, success, prompt);
    145 }
    146 
    147 gfx::NativeWindow BackgroundContents::GetMessageBoxRootWindow() {
    148   NOTIMPLEMENTED();
    149   return NULL;
    150 }
    151 
    152 TabContents* BackgroundContents::AsTabContents() {
    153   return NULL;
    154 }
    155 
    156 ExtensionHost* BackgroundContents::AsExtensionHost() {
    157   return NULL;
    158 }
    159 
    160 void BackgroundContents::UpdateInspectorSetting(const std::string& key,
    161                                          const std::string& value) {
    162   Profile* profile = render_view_host_->process()->profile();
    163   RenderViewHostDelegateHelper::UpdateInspectorSetting(profile, key, value);
    164 }
    165 
    166 void BackgroundContents::ClearInspectorSettings() {
    167   Profile* profile = render_view_host_->process()->profile();
    168   RenderViewHostDelegateHelper::ClearInspectorSettings(profile);
    169 }
    170 
    171 void BackgroundContents::Close(RenderViewHost* render_view_host) {
    172   Profile* profile = render_view_host->process()->profile();
    173   NotificationService::current()->Notify(
    174       NotificationType::BACKGROUND_CONTENTS_CLOSED,
    175       Source<Profile>(profile),
    176       Details<BackgroundContents>(this));
    177   delete this;
    178 }
    179 
    180 void BackgroundContents::RenderViewGone(RenderViewHost* rvh,
    181                                         base::TerminationStatus status,
    182                                         int error_code) {
    183   Profile* profile = rvh->process()->profile();
    184   NotificationService::current()->Notify(
    185       NotificationType::BACKGROUND_CONTENTS_TERMINATED,
    186       Source<Profile>(profile),
    187       Details<BackgroundContents>(this));
    188 
    189   // Our RenderView went away, so we should go away also, so killing the process
    190   // via the TaskManager doesn't permanently leave a BackgroundContents hanging
    191   // around the system, blocking future instances from being created
    192   // (http://crbug.com/65189).
    193   delete this;
    194 }
    195 
    196 RendererPreferences BackgroundContents::GetRendererPrefs(
    197     Profile* profile) const {
    198   RendererPreferences preferences;
    199   renderer_preferences_util::UpdateFromSystemSettings(&preferences, profile);
    200   return preferences;
    201 }
    202 
    203 WebPreferences BackgroundContents::GetWebkitPrefs() {
    204   // TODO(rafaelw): Consider enabling the webkit_prefs.dom_paste_enabled for
    205   // apps.
    206   Profile* profile = render_view_host_->process()->profile();
    207   return RenderViewHostDelegateHelper::GetWebkitPrefs(profile,
    208                                                       false);  // is_web_ui
    209 }
    210 
    211 void BackgroundContents::ProcessWebUIMessage(
    212     const ExtensionHostMsg_DomMessage_Params& params) {
    213   // TODO(rafaelw): It may make sense for extensions to be able to open
    214   // BackgroundContents to chrome-extension://<id> pages. Consider implementing.
    215   render_view_host_->Send(new ExtensionMsg_Response(
    216       render_view_host_->routing_id(), params.request_id, false,
    217       std::string(), "Access to extension API denied."));
    218 }
    219 
    220 void BackgroundContents::CreateNewWindow(
    221     int route_id,
    222     const ViewHostMsg_CreateWindow_Params& params) {
    223   delegate_view_helper_.CreateNewWindow(
    224       route_id,
    225       render_view_host_->process()->profile(),
    226       render_view_host_->site_instance(),
    227       ChromeWebUIFactory::GetInstance()->GetWebUIType(
    228           render_view_host_->process()->profile(), url_),
    229       this,
    230       params.window_container_type,
    231       params.frame_name);
    232 }
    233 
    234 void BackgroundContents::CreateNewWidget(int route_id,
    235                                          WebKit::WebPopupType popup_type) {
    236   NOTREACHED();
    237 }
    238 
    239 void BackgroundContents::CreateNewFullscreenWidget(int route_id) {
    240   NOTREACHED();
    241 }
    242 
    243 void BackgroundContents::ShowCreatedWindow(int route_id,
    244                                            WindowOpenDisposition disposition,
    245                                            const gfx::Rect& initial_pos,
    246                                            bool user_gesture) {
    247   TabContents* contents = delegate_view_helper_.GetCreatedWindow(route_id);
    248   if (contents)
    249     delegate_->AddTabContents(contents, disposition, initial_pos, user_gesture);
    250 }
    251 
    252 void BackgroundContents::ShowCreatedWidget(int route_id,
    253                                            const gfx::Rect& initial_pos) {
    254   NOTIMPLEMENTED();
    255 }
    256 
    257 void BackgroundContents::ShowCreatedFullscreenWidget(int route_id) {
    258   NOTIMPLEMENTED();
    259 }
    260 
    261 // static
    262 BackgroundContents*
    263 BackgroundContents::GetBackgroundContentsByID(int render_process_id,
    264                                               int render_view_id) {
    265   RenderViewHost* render_view_host =
    266       RenderViewHost::FromID(render_process_id, render_view_id);
    267   if (!render_view_host)
    268     return NULL;
    269 
    270   return render_view_host->delegate()->GetAsBackgroundContents();
    271 }
    272