Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Side by Side Diff: chrome/browser/extensions/api/identity/extension_auth_flow.cc

Issue 10178020: Start implementing an auth flow for platform apps to be able to do auth (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/extensions/api/identity/extension_auth_flow.h"
6
7 #include "base/location.h"
8 #include "base/message_loop.h"
9 #include "base/stringprintf.h"
10 #include "base/string_util.h"
11 #include "content/public/browser/invalidate_type.h"
12 #include "content/public/browser/navigation_controller.h"
13 #include "content/public/browser/web_contents.h"
14 #include "ipc/ipc_message.h"
15 #include "ui/views/controls/webview/webview.h"
16 #include "ui/views/widget/widget.h"
17
18 using content::BrowserContext;
19 using content::WebContents;
20 using content::WebContentsDelegate;
21 using views::View;
22 using views::WebView;
23 using views::Widget;
24 using views::WidgetDelegate;
25
26 namespace {
27
28 static const char kChromeExtensionSchemeUrlPattern[] =
29 "chrome-extension://%s/";
30 static const char kChromiumDomainRedirectUrlPattern[] =
31 "https://%s.chromiumapp.org/";
32
33 } // namespace
34
35 namespace extensions {
36
37 ExtensionAuthFlow::ExtensionAuthFlow(
38 Delegate* delegate,
39 content::BrowserContext* browser_context,
40 const std::string& extension_id,
41 const GURL& provider_url)
42 : delegate_(delegate),
43 browser_context_(browser_context),
44 provider_url_(provider_url),
45 contents_(NULL),
46 widget_(NULL),
47 web_view_(NULL) {
48 InitValidRedirectUrlPrefixes(extension_id);
49 }
50
51 ExtensionAuthFlow::~ExtensionAuthFlow() {
52 if (widget_)
53 widget_->Close(); // Close() deletes the widget also.
54 if (contents_) {
55 contents_->SetDelegate(NULL);
56 contents_->Stop();
57 // Tell message loop to delete contents_ instead of deleting it
58 // directly since destructor can run in response to a callback from
59 // contents_.
60 MessageLoop::current()->DeleteSoon(FROM_HERE, contents_);
61 }
62 }
63
64 void ExtensionAuthFlow::Start() {
65 contents_ = CreateWebContents();
66 contents_->SetDelegate(this);
67 contents_->GetController().LoadURL(
68 provider_url_,
69 content::Referrer(),
70 content::PAGE_TRANSITION_START_PAGE,
71 std::string());
72 }
73
74 void ExtensionAuthFlow::LoadingStateChanged(WebContents* source) {
75 if (source->IsLoading())
76 return;
77 OnUrlLoaded();
78 }
79
80 void ExtensionAuthFlow::NavigationStateChanged(
81 const WebContents* source, unsigned changed_flags) {
82 // If the URL has not changed, do not perform the check again (for
83 // efficiency).
84 if ((changed_flags & content::INVALIDATE_TYPE_URL) == 0)
85 return;
86
87 // If the URL is a valid extension redirect URL, capture the
88 // results and end the flow.
89 const GURL& url = source->GetURL();
90
91 if (IsValidRedirectUrl(url)) {
92 ReportResult(url);
93 return;
94 }
95 }
96
97 WebContents* ExtensionAuthFlow::CreateWebContents() {
98 return WebContents::Create(
99 browser_context_, NULL, MSG_ROUTING_NONE, NULL, NULL);
100 }
101
102 void ExtensionAuthFlow::OnUrlLoaded() {
103 const GURL& url = contents_->GetURL();
104
105 if (!widget_) {
106 web_view_ = new WebView(browser_context_);
107 web_view_->SetWebContents(contents_);
108 widget_ = Widget::CreateWindow(this);
109 // TODO(munjal): Make this configurable?
110 widget_->CenterWindow(gfx::Size(1024, 768));
111 widget_->Show();
112 }
113 }
114
115 View* ExtensionAuthFlow::GetContentsView() {
116 CHECK(web_view_);
117 return web_view_;
118 }
119
120 Widget* ExtensionAuthFlow::GetWidget() {
121 CHECK(widget_);
122 return widget_;
123 }
124
125 const Widget* ExtensionAuthFlow::GetWidget() const {
126 CHECK(widget_);
127 return widget_;
128 }
129
130 View* ExtensionAuthFlow::GetInitiallyFocusedView() {
131 CHECK(web_view_);
132 return web_view_;
133 }
134
135 void ExtensionAuthFlow::DeleteDelegate() {
136 ReportResult(GURL());
137 }
138
139 void ExtensionAuthFlow::ReportResult(const GURL& result) {
140 if (!delegate_)
141 return;
142
143 if (result.is_empty()) {
144 delegate_->OnAuthFlowFailure();
145 } else {
146 // TODO(munjal): Consider adding code to parse out access token
147 // from some common places (e.g. URL fragment) so the apps don't
148 // have to do that work.
149 delegate_->OnAuthFlowSuccess(result.spec());
150 }
151
152 // IMPORTANT: Do not access any members after calling the delegate
153 // since the delegate can destroy |this| in the callback and hence
154 // all data members are invalid after that.
155 }
156
157 void ExtensionAuthFlow::InitValidRedirectUrlPrefixes(
158 const std::string& extension_id) {
159 valid_prefixes_.push_back(base::StringPrintf(
160 kChromeExtensionSchemeUrlPattern, extension_id.c_str()));
161 valid_prefixes_.push_back(base::StringPrintf(
162 kChromiumDomainRedirectUrlPattern, extension_id.c_str()));
163 }
164
165 bool ExtensionAuthFlow::IsValidRedirectUrl(const GURL& url) const {
166 std::vector<std::string>::const_iterator iter;
167 for (iter = valid_prefixes_.begin(); iter != valid_prefixes_.end(); ++iter) {
168 if (StartsWithASCII(url.spec(), *iter, false))
169 return true;
170 }
171 return false;
172 }
173
174 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698