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.
5 #include "chrome/browser/apps/ephemeral_app_throttle.h"
7 #include "base/command_line.h"
8 #include "chrome/browser/apps/ephemeral_app_launcher.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/profiles/profile_io_data.h"
12 #include "chrome/common/chrome_switches.h"
13 #include "chrome/common/extensions/extension_constants.h"
14 #include "components/crx_file/id_util.h"
15 #include "components/navigation_interception/intercept_navigation_resource_throttle.h"
16 #include "components/navigation_interception/navigation_params.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/resource_throttle.h"
19 #include "content/public/browser/web_contents.h"
20 #include "extensions/browser/extension_system.h"
21 #include "net/url_request/url_request.h"
23 using content::BrowserThread
;
24 using content::WebContents
;
25 using extensions::Extension
;
29 bool LaunchEphemeralApp(
30 const std::string
& app_id
,
31 content::WebContents
* source
,
32 const navigation_interception::NavigationParams
& params
) {
33 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
35 // Redirect top-level navigations only.
36 if (source
->IsSubframe())
40 Profile::FromBrowserContext(source
->GetBrowserContext());
44 ExtensionService
* service
=
45 extensions::ExtensionSystem::Get(profile
)->extension_service();
47 const Extension
* extension
= service
->GetInstalledExtension(app_id
);
50 if (extension
&& !extension
->is_app())
53 // The EphemeralAppLauncher will handle launching of an existing app or
54 // installing and launching a new ephemeral app.
55 scoped_refptr
<EphemeralAppLauncher
> installer
=
56 EphemeralAppLauncher::CreateForWebContents(
57 app_id
, source
, EphemeralAppLauncher::LaunchCallback());
65 content::ResourceThrottle
*
66 EphemeralAppThrottle::MaybeCreateThrottleForLaunch(
67 net::URLRequest
* request
,
68 ProfileIOData
* profile_io_data
) {
69 if (!CommandLine::ForCurrentProcess()->HasSwitch(
70 switches::kEnableLinkableEphemeralApps
))
73 if (request
->method() != "GET" || !request
->url().SchemeIsHTTPOrHTTPS())
76 // Not supported for incognito profiles.
77 if (profile_io_data
->IsOffTheRecord())
80 // Only watch for links in Google search results.
81 if (request
->referrer().find("https://www.google.com") == std::string::npos
)
84 // Crudely watch for links to Chrome Web Store detail pages and assume that
85 // the app ID will be after the last slash of the URL. We cannot even
86 // differentiate between apps and extensions, so attempt to launch both.
87 // This is obviously for demonstration purposes only and will be implemented
88 // properly in production code - for example, links to ephemeral apps could
90 if (request
->url().spec().find(
91 extension_urls::GetWebstoreItemDetailURLPrefix()) != 0)
94 std::string
app_id(request
->url().ExtractFileName());
95 if (!crx_file::id_util::IdIsValid(app_id
))
98 return new navigation_interception::InterceptNavigationResourceThrottle(
100 base::Bind(&LaunchEphemeralApp
, app_id
));