1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_PRERENDER_PRERENDER_CONTENTS_H_
#define CHROME_BROWSER_PRERENDER_PRERENDER_CONTENTS_H_
#include <string>
#include <utility>
#include <vector>
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/prerender/prerender_final_status.h"
#include "chrome/browser/prerender/prerender_origin.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/referrer.h"
#include "ui/gfx/geometry/size.h"
class Profile;
namespace base {
class ProcessMetrics;
}
namespace content {
class RenderViewHost;
class SessionStorageNamespace;
class WebContents;
}
namespace history {
struct HistoryAddPageArgs;
}
namespace net {
class URLRequestContextGetter;
}
namespace prerender {
class PrerenderHandle;
class PrerenderManager;
class PrerenderResourceThrottle;
class PrerenderContents : public content::NotificationObserver,
public content::WebContentsObserver,
public base::SupportsWeakPtr<PrerenderContents> {
public:
// PrerenderContents::Create uses the currently registered Factory to create
// the PrerenderContents. Factory is intended for testing.
class Factory {
public:
Factory() {}
virtual ~Factory() {}
// Ownership is not transfered through this interface as prerender_manager,
// prerender_tracker, and profile are stored as weak pointers.
virtual PrerenderContents* CreatePrerenderContents(
PrerenderManager* prerender_manager,
Profile* profile,
const GURL& url,
const content::Referrer& referrer,
Origin origin,
uint8 experiment_id) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(Factory);
};
class Observer {
public:
// Signals that the prerender has started running.
virtual void OnPrerenderStart(PrerenderContents* contents) = 0;
// Signals that the prerender has had its load event.
virtual void OnPrerenderStopLoading(PrerenderContents* contents);
// Signals that the prerender has had its 'DOMContentLoaded' event.
virtual void OnPrerenderDomContentLoaded(PrerenderContents* contents);
// Signals that the prerender has stopped running. A PrerenderContents with
// an unset final status will always call OnPrerenderStop before being
// destroyed.
virtual void OnPrerenderStop(PrerenderContents* contents) = 0;
// Signals that this prerender has just become a MatchComplete replacement.
virtual void OnPrerenderCreatedMatchCompleteReplacement(
PrerenderContents* contents, PrerenderContents* replacement);
protected:
Observer();
virtual ~Observer() = 0;
};
// Indicates how this PrerenderContents relates to MatchComplete. This is to
// figure out which histograms to use to record the FinalStatus, Match (record
// all prerenders and control group prerenders) or MatchComplete (record
// running prerenders only in the way they would have been recorded in the
// control group).
enum MatchCompleteStatus {
// A regular prerender which will be recorded both in Match and
// MatchComplete.
MATCH_COMPLETE_DEFAULT,
// A prerender that used to be a regular prerender, but has since been
// replaced by a MatchComplete dummy. Therefore, we will record this only
// for Match, but not for MatchComplete.
MATCH_COMPLETE_REPLACED,
// A prerender that is a MatchComplete dummy replacing a regular prerender.
// In the control group, our prerender never would have been canceled, so
// we record in MatchComplete but not Match.
MATCH_COMPLETE_REPLACEMENT,
// A prerender that is a MatchComplete dummy, early in the process of being
// created. This prerender should not fail. Record for MatchComplete, but
// not Match.
MATCH_COMPLETE_REPLACEMENT_PENDING,
};
~PrerenderContents() override;
// All observers of a PrerenderContents are removed after the OnPrerenderStop
// event is sent, so there is no need to call RemoveObserver() in the normal
// use case.
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// For MatchComplete correctness, create a dummy replacement prerender
// contents to stand in for this prerender contents that (which we are about
// to destroy).
PrerenderContents* CreateMatchCompleteReplacement();
bool Init();
static Factory* CreateFactory();
// Returns a PrerenderContents from the given web_contents, if it's used for
// prerendering. Otherwise returns NULL. Handles a NULL input for
// convenience.
static PrerenderContents* FromWebContents(content::WebContents* web_contents);
// Start rendering the contents in the prerendered state. If
// |is_control_group| is true, this will go through some of the mechanics of
// starting a prerender, without actually creating the RenderView. |size|
// indicates the rectangular dimensions that the prerendered page should be.
// |session_storage_namespace| indicates the namespace that the prerendered
// page should be part of.
virtual void StartPrerendering(
const gfx::Size& size,
content::SessionStorageNamespace* session_storage_namespace,
net::URLRequestContextGetter* request_context);
// Verifies that the prerendering is not using too many resources, and kills
// it if not.
void DestroyWhenUsingTooManyResources();
content::RenderViewHost* GetRenderViewHostMutable();
const content::RenderViewHost* GetRenderViewHost() const;
PrerenderManager* prerender_manager() { return prerender_manager_; }
base::string16 title() const { return title_; }
int32 page_id() const { return page_id_; }
const GURL& prerender_url() const { return prerender_url_; }
const content::Referrer& referrer() const { return referrer_; }
bool has_stopped_loading() const { return has_stopped_loading_; }
bool has_finished_loading() const { return has_finished_loading_; }
bool prerendering_has_started() const { return prerendering_has_started_; }
MatchCompleteStatus match_complete_status() const {
return match_complete_status_;
}
void set_match_complete_status(MatchCompleteStatus status) {
match_complete_status_ = status;
}
// Sets the parameter to the value of the associated RenderViewHost's child id
// and returns a boolean indicating the validity of that id.
virtual bool GetChildId(int* child_id) const;
// Sets the parameter to the value of the associated RenderViewHost's route id
// and returns a boolean indicating the validity of that id.
virtual bool GetRouteId(int* route_id) const;
FinalStatus final_status() const { return final_status_; }
Origin origin() const { return origin_; }
uint8 experiment_id() const { return experiment_id_; }
int child_id() const { return child_id_; }
base::TimeTicks load_start_time() const { return load_start_time_; }
// Indicates whether this prerendered page can be used for the provided
// |url| and |session_storage_namespace|.
bool Matches(
const GURL& url,
const content::SessionStorageNamespace* session_storage_namespace) const;
// content::WebContentsObserver implementation.
void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
void DidStopLoading(content::RenderViewHost* render_view_host) override;
void DocumentLoadedInFrame(
content::RenderFrameHost* render_frame_host) override;
void DidStartProvisionalLoadForFrame(
content::RenderFrameHost* render_frame_host,
const GURL& validated_url,
bool is_error_page,
bool is_iframe_srcdoc) override;
void DidFinishLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url) override;
void DidNavigateMainFrame(
const content::LoadCommittedDetails& details,
const content::FrameNavigateParams& params) override;
void DidGetRedirectForResourceRequest(
content::RenderFrameHost* render_frame_host,
const content::ResourceRedirectDetails& details) override;
bool OnMessageReceived(const IPC::Message& message) override;
void RenderProcessGone(base::TerminationStatus status) override;
// content::NotificationObserver
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
// Checks that a URL may be prerendered, for one of the many redirections. If
// the URL can not be prerendered - for example, it's an ftp URL - |this| will
// be destroyed and false is returned. Otherwise, true is returned.
virtual bool CheckURL(const GURL& url);
// Adds an alias URL. If the URL can not be prerendered, |this| will be
// destroyed and false is returned.
bool AddAliasURL(const GURL& url);
// The prerender WebContents (may be NULL).
content::WebContents* prerender_contents() const {
return prerender_contents_.get();
}
content::WebContents* ReleasePrerenderContents();
// Sets the final status, calls OnDestroy and adds |this| to the
// PrerenderManager's pending deletes list.
void Destroy(FinalStatus reason);
// Called by the history tab helper with the information that it woudl have
// added to the history service had this web contents not been used for
// prerendering.
void DidNavigate(const history::HistoryAddPageArgs& add_page_args);
// Applies all the URL history encountered during prerendering to the
// new tab.
void CommitHistory(content::WebContents* tab);
base::Value* GetAsValue() const;
// Returns whether a pending cross-site navigation is happening.
// This could happen with renderer-issued navigations, such as a
// MouseEvent being dispatched by a link to a website installed as an app.
bool IsCrossSiteNavigationPending() const;
// Marks prerender as used and releases any throttled resource requests.
void PrepareForUse();
content::SessionStorageNamespace* GetSessionStorageNamespace() const;
// Cookie events
enum CookieEvent {
COOKIE_EVENT_SEND = 0,
COOKIE_EVENT_CHANGE = 1,
COOKIE_EVENT_MAX
};
// Record a cookie transaction for this prerender contents.
// In the event of cookies being sent, |earliest_create_date| contains
// the time that the earliest of the cookies sent was created.
void RecordCookieEvent(CookieEvent event,
bool is_main_frame_http_request,
bool is_third_party_cookie,
bool is_for_blocking_resource,
base::Time earliest_create_date);
static const int kNumCookieStatuses;
static const int kNumCookieSendTypes;
// Called when a PrerenderResourceThrottle defers a request. If the prerender
// is used it'll be resumed on the IO thread, otherwise they will get
// cancelled automatically if prerendering is cancelled.
void AddResourceThrottle(
const base::WeakPtr<PrerenderResourceThrottle>& throttle);
// Increments the number of bytes fetched over the network for this prerender.
void AddNetworkBytes(int64 bytes);
protected:
PrerenderContents(PrerenderManager* prerender_manager,
Profile* profile,
const GURL& url,
const content::Referrer& referrer,
Origin origin,
uint8 experiment_id);
// Set the final status for how the PrerenderContents was used. This
// should only be called once, and should be called before the prerender
// contents are destroyed.
void SetFinalStatus(FinalStatus final_status);
// These call out to methods on our Observers, using our observer_list_. Note
// that NotifyPrerenderStop() also clears the observer list.
void NotifyPrerenderStart();
void NotifyPrerenderStopLoading();
void NotifyPrerenderDomContentLoaded();
void NotifyPrerenderStop();
void NotifyPrerenderCreatedMatchCompleteReplacement(
PrerenderContents* replacement);
// Called whenever a RenderViewHost is created for prerendering. Only called
// once the RenderViewHost has a RenderView and RenderWidgetHostView.
virtual void OnRenderViewHostCreated(
content::RenderViewHost* new_render_view_host);
content::NotificationRegistrar& notification_registrar() {
return notification_registrar_;
}
bool prerendering_has_been_cancelled() const {
return prerendering_has_been_cancelled_;
}
content::WebContents* CreateWebContents(
content::SessionStorageNamespace* session_storage_namespace);
bool prerendering_has_started_;
// Time at which we started to load the URL. This is used to compute
// the time elapsed from initiating a prerender until the time the
// (potentially only partially) prerendered page is shown to the user.
base::TimeTicks load_start_time_;
// The prerendered WebContents; may be null.
scoped_ptr<content::WebContents> prerender_contents_;
// The session storage namespace id for use in matching. We must save it
// rather than get it from the RenderViewHost since in the control group
// we won't have a RenderViewHost.
int64 session_storage_namespace_id_;
// The time at which we started prerendering, for the purpose of comparing
// cookie creation times.
base::Time start_time_;
private:
class WebContentsDelegateImpl;
// Needs to be able to call the constructor.
friend class PrerenderContentsFactoryImpl;
// Returns the ProcessMetrics for the render process, if it exists.
base::ProcessMetrics* MaybeGetProcessMetrics();
// Message handlers.
void OnCancelPrerenderForPrinting();
ObserverList<Observer> observer_list_;
// The prerender manager owning this object.
PrerenderManager* prerender_manager_;
// The URL being prerendered.
GURL prerender_url_;
// The referrer.
content::Referrer referrer_;
// The profile being used
Profile* profile_;
// Information about the title and URL of the page that this class as a
// RenderViewHostDelegate has received from the RenderView.
// Used to apply to the new RenderViewHost delegate that might eventually
// own the contained RenderViewHost when the prerendered page is shown
// in a WebContents.
base::string16 title_;
int32 page_id_;
GURL url_;
content::NotificationRegistrar notification_registrar_;
// A vector of URLs that this prerendered page matches against.
// This array can contain more than element as a result of redirects,
// such as HTTP redirects or javascript redirects.
std::vector<GURL> alias_urls_;
bool has_stopped_loading_;
// True when the main frame has finished loading.
bool has_finished_loading_;
// This must be the same value as the PrerenderTracker has recorded for
// |this|, when |this| has a RenderView.
FinalStatus final_status_;
// The MatchComplete status of the prerender, indicating how it relates
// to being a MatchComplete dummy (see definition of MatchCompleteStatus
// above).
MatchCompleteStatus match_complete_status_;
// Tracks whether or not prerendering has been cancelled by calling Destroy.
// Used solely to prevent double deletion.
bool prerendering_has_been_cancelled_;
// Process Metrics of the render process associated with the
// RenderViewHost for this object.
scoped_ptr<base::ProcessMetrics> process_metrics_;
scoped_ptr<WebContentsDelegateImpl> web_contents_delegate_;
// These are -1 before a RenderView is created.
int child_id_;
int route_id_;
// Origin for this prerender.
Origin origin_;
// Experiment during which this prerender is performed.
uint8 experiment_id_;
// The size of the WebView from the launching page.
gfx::Size size_;
typedef std::vector<history::HistoryAddPageArgs> AddPageVector;
// Caches pages to be added to the history.
AddPageVector add_page_vector_;
// The alias session storage namespace for this prerender.
scoped_refptr<content::SessionStorageNamespace>
alias_session_storage_namespace;
// Indicates what internal cookie events (see prerender_contents.cc) have
// occurred, using 1 bit for each possible InternalCookieEvent.
int cookie_status_;
// Indicates whether existing cookies were sent for this prerender, and
// whether they were third-party cookies, and whether they were for blocking
// resources. See the enum CookieSendType in prerender_contents.cc
int cookie_send_type_;
// Resources that are throttled, pending a prerender use. Can only access a
// throttle on the IO thread.
std::vector<base::WeakPtr<PrerenderResourceThrottle> > resource_throttles_;
// A running tally of the number of bytes this prerender has caused to be
// transferred over the network for resources. Updated with AddNetworkBytes.
int64 network_bytes_;
DISALLOW_COPY_AND_ASSIGN(PrerenderContents);
};
} // namespace prerender
#endif // CHROME_BROWSER_PRERENDER_PRERENDER_CONTENTS_H_
|