| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/api/identity/web_auth_flow.h" | 5 #include "chrome/browser/extensions/api/identity/web_auth_flow.h" |
| 6 | 6 |
| 7 #include "apps/shell_window.h" | 7 #include "apps/app_window.h" |
| 8 #include "base/base64.h" | 8 #include "base/base64.h" |
| 9 #include "base/location.h" | 9 #include "base/location.h" |
| 10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| 11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
| 12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 13 #include "chrome/browser/extensions/component_loader.h" | 13 #include "chrome/browser/extensions/component_loader.h" |
| 14 #include "chrome/browser/extensions/extension_service.h" | 14 #include "chrome/browser/extensions/extension_service.h" |
| 15 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
| 16 #include "chrome/common/extensions/api/identity_private.h" | 16 #include "chrome/common/extensions/api/identity_private.h" |
| 17 #include "chrome/common/extensions/extension_constants.h" | 17 #include "chrome/common/extensions/extension_constants.h" |
| 18 #include "content/public/browser/navigation_details.h" | 18 #include "content/public/browser/navigation_details.h" |
| 19 #include "content/public/browser/navigation_entry.h" | 19 #include "content/public/browser/navigation_entry.h" |
| 20 #include "content/public/browser/notification_details.h" | 20 #include "content/public/browser/notification_details.h" |
| 21 #include "content/public/browser/notification_service.h" | 21 #include "content/public/browser/notification_service.h" |
| 22 #include "content/public/browser/notification_source.h" | 22 #include "content/public/browser/notification_source.h" |
| 23 #include "content/public/browser/notification_types.h" | 23 #include "content/public/browser/notification_types.h" |
| 24 #include "content/public/browser/render_view_host.h" | 24 #include "content/public/browser/render_view_host.h" |
| 25 #include "content/public/browser/resource_request_details.h" | 25 #include "content/public/browser/resource_request_details.h" |
| 26 #include "content/public/browser/web_contents.h" | 26 #include "content/public/browser/web_contents.h" |
| 27 #include "crypto/random.h" | 27 #include "crypto/random.h" |
| 28 #include "extensions/browser/event_router.h" | 28 #include "extensions/browser/event_router.h" |
| 29 #include "extensions/browser/extension_system.h" | 29 #include "extensions/browser/extension_system.h" |
| 30 #include "grit/browser_resources.h" | 30 #include "grit/browser_resources.h" |
| 31 #include "url/gurl.h" | 31 #include "url/gurl.h" |
| 32 | 32 |
| 33 using apps::ShellWindow; | 33 using apps::AppWindow; |
| 34 using content::RenderViewHost; | 34 using content::RenderViewHost; |
| 35 using content::ResourceRedirectDetails; | 35 using content::ResourceRedirectDetails; |
| 36 using content::WebContents; | 36 using content::WebContents; |
| 37 using content::WebContentsObserver; | 37 using content::WebContentsObserver; |
| 38 | 38 |
| 39 namespace extensions { | 39 namespace extensions { |
| 40 | 40 |
| 41 namespace identity_private = api::identity_private; | 41 namespace identity_private = api::identity_private; |
| 42 | 42 |
| 43 WebAuthFlow::WebAuthFlow( | 43 WebAuthFlow::WebAuthFlow( |
| 44 Delegate* delegate, | 44 Delegate* delegate, |
| 45 Profile* profile, | 45 Profile* profile, |
| 46 const GURL& provider_url, | 46 const GURL& provider_url, |
| 47 Mode mode) | 47 Mode mode) |
| 48 : delegate_(delegate), | 48 : delegate_(delegate), |
| 49 profile_(profile), | 49 profile_(profile), |
| 50 provider_url_(provider_url), | 50 provider_url_(provider_url), |
| 51 mode_(mode), | 51 mode_(mode), |
| 52 embedded_window_created_(false) { | 52 embedded_window_created_(false) { |
| 53 } | 53 } |
| 54 | 54 |
| 55 WebAuthFlow::~WebAuthFlow() { | 55 WebAuthFlow::~WebAuthFlow() { |
| 56 DCHECK(delegate_ == NULL); | 56 DCHECK(delegate_ == NULL); |
| 57 | 57 |
| 58 // Stop listening to notifications first since some of the code | 58 // Stop listening to notifications first since some of the code |
| 59 // below may generate notifications. | 59 // below may generate notifications. |
| 60 registrar_.RemoveAll(); | 60 registrar_.RemoveAll(); |
| 61 WebContentsObserver::Observe(NULL); | 61 WebContentsObserver::Observe(NULL); |
| 62 | 62 |
| 63 if (!shell_window_key_.empty()) { | 63 if (!app_window_key_.empty()) { |
| 64 apps::ShellWindowRegistry::Get(profile_)->RemoveObserver(this); | 64 apps::AppWindowRegistry::Get(profile_)->RemoveObserver(this); |
| 65 | 65 |
| 66 if (shell_window_ && shell_window_->web_contents()) | 66 if (app_window_ && app_window_->web_contents()) |
| 67 shell_window_->web_contents()->Close(); | 67 app_window_->web_contents()->Close(); |
| 68 } | 68 } |
| 69 } | 69 } |
| 70 | 70 |
| 71 void WebAuthFlow::Start() { | 71 void WebAuthFlow::Start() { |
| 72 apps::ShellWindowRegistry::Get(profile_)->AddObserver(this); | 72 apps::AppWindowRegistry::Get(profile_)->AddObserver(this); |
| 73 | 73 |
| 74 // Attach a random ID string to the window so we can recoginize it | 74 // Attach a random ID string to the window so we can recoginize it |
| 75 // in OnShellWindowAdded. | 75 // in OnAppWindowAdded. |
| 76 std::string random_bytes; | 76 std::string random_bytes; |
| 77 crypto::RandBytes(WriteInto(&random_bytes, 33), 32); | 77 crypto::RandBytes(WriteInto(&random_bytes, 33), 32); |
| 78 base::Base64Encode(random_bytes, &shell_window_key_); | 78 base::Base64Encode(random_bytes, &app_window_key_); |
| 79 | 79 |
| 80 // identityPrivate.onWebFlowRequest(shell_window_key, provider_url_, mode_) | 80 // identityPrivate.onWebFlowRequest(shell_window_key, provider_url_, mode_) |
| 81 scoped_ptr<base::ListValue> args(new base::ListValue()); | 81 scoped_ptr<base::ListValue> args(new base::ListValue()); |
| 82 args->AppendString(shell_window_key_); | 82 args->AppendString(app_window_key_); |
| 83 args->AppendString(provider_url_.spec()); | 83 args->AppendString(provider_url_.spec()); |
| 84 if (mode_ == WebAuthFlow::INTERACTIVE) | 84 if (mode_ == WebAuthFlow::INTERACTIVE) |
| 85 args->AppendString("interactive"); | 85 args->AppendString("interactive"); |
| 86 else | 86 else |
| 87 args->AppendString("silent"); | 87 args->AppendString("silent"); |
| 88 | 88 |
| 89 scoped_ptr<Event> event( | 89 scoped_ptr<Event> event( |
| 90 new Event(identity_private::OnWebFlowRequest::kEventName, args.Pass())); | 90 new Event(identity_private::OnWebFlowRequest::kEventName, args.Pass())); |
| 91 event->restrict_to_browser_context = profile_; | 91 event->restrict_to_browser_context = profile_; |
| 92 ExtensionSystem* system = ExtensionSystem::Get(profile_); | 92 ExtensionSystem* system = ExtensionSystem::Get(profile_); |
| 93 | 93 |
| 94 extensions::ComponentLoader* component_loader = | 94 extensions::ComponentLoader* component_loader = |
| 95 system->extension_service()->component_loader(); | 95 system->extension_service()->component_loader(); |
| 96 if (!component_loader->Exists(extension_misc::kIdentityApiUiAppId)) { | 96 if (!component_loader->Exists(extension_misc::kIdentityApiUiAppId)) { |
| 97 component_loader->Add( | 97 component_loader->Add( |
| 98 IDR_IDENTITY_API_SCOPE_APPROVAL_MANIFEST, | 98 IDR_IDENTITY_API_SCOPE_APPROVAL_MANIFEST, |
| 99 base::FilePath(FILE_PATH_LITERAL("identity_scope_approval_dialog"))); | 99 base::FilePath(FILE_PATH_LITERAL("identity_scope_approval_dialog"))); |
| 100 } | 100 } |
| 101 | 101 |
| 102 system->event_router()->DispatchEventWithLazyListener( | 102 system->event_router()->DispatchEventWithLazyListener( |
| 103 extension_misc::kIdentityApiUiAppId, event.Pass()); | 103 extension_misc::kIdentityApiUiAppId, event.Pass()); |
| 104 } | 104 } |
| 105 | 105 |
| 106 void WebAuthFlow::DetachDelegateAndDelete() { | 106 void WebAuthFlow::DetachDelegateAndDelete() { |
| 107 delegate_ = NULL; | 107 delegate_ = NULL; |
| 108 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 108 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| 109 } | 109 } |
| 110 | 110 |
| 111 void WebAuthFlow::OnShellWindowAdded(ShellWindow* shell_window) { | 111 void WebAuthFlow::OnAppWindowAdded(AppWindow* app_window) { |
| 112 if (shell_window->window_key() == shell_window_key_ && | 112 if (app_window->window_key() == app_window_key_ && |
| 113 shell_window->extension()->id() == extension_misc::kIdentityApiUiAppId) { | 113 app_window->extension()->id() == extension_misc::kIdentityApiUiAppId) { |
| 114 shell_window_ = shell_window; | 114 app_window_ = app_window; |
| 115 WebContentsObserver::Observe(shell_window->web_contents()); | 115 WebContentsObserver::Observe(app_window->web_contents()); |
| 116 | 116 |
| 117 registrar_.Add( | 117 registrar_.Add( |
| 118 this, | 118 this, |
| 119 content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED, | 119 content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED, |
| 120 content::NotificationService::AllBrowserContextsAndSources()); | 120 content::NotificationService::AllBrowserContextsAndSources()); |
| 121 } | 121 } |
| 122 } | 122 } |
| 123 | 123 |
| 124 void WebAuthFlow::OnShellWindowIconChanged(ShellWindow* shell_window) {} | 124 void WebAuthFlow::OnAppWindowIconChanged(AppWindow* app_window) {} |
| 125 | 125 |
| 126 void WebAuthFlow::OnShellWindowRemoved(ShellWindow* shell_window) { | 126 void WebAuthFlow::OnAppWindowRemoved(AppWindow* app_window) { |
| 127 if (shell_window->window_key() == shell_window_key_ && | 127 if (app_window->window_key() == app_window_key_ && |
| 128 shell_window->extension()->id() == extension_misc::kIdentityApiUiAppId) { | 128 app_window->extension()->id() == extension_misc::kIdentityApiUiAppId) { |
| 129 shell_window_ = NULL; | 129 app_window_ = NULL; |
| 130 registrar_.RemoveAll(); | 130 registrar_.RemoveAll(); |
| 131 | 131 |
| 132 if (delegate_) | 132 if (delegate_) |
| 133 delegate_->OnAuthFlowFailure(WebAuthFlow::WINDOW_CLOSED); | 133 delegate_->OnAuthFlowFailure(WebAuthFlow::WINDOW_CLOSED); |
| 134 } | 134 } |
| 135 } | 135 } |
| 136 | 136 |
| 137 void WebAuthFlow::BeforeUrlLoaded(const GURL& url) { | 137 void WebAuthFlow::BeforeUrlLoaded(const GURL& url) { |
| 138 if (delegate_ && embedded_window_created_) | 138 if (delegate_ && embedded_window_created_) |
| 139 delegate_->OnAuthFlowURLChange(url); | 139 delegate_->OnAuthFlowURLChange(url); |
| 140 } | 140 } |
| 141 | 141 |
| 142 void WebAuthFlow::AfterUrlLoaded() { | 142 void WebAuthFlow::AfterUrlLoaded() { |
| 143 if (delegate_ && embedded_window_created_ && mode_ == WebAuthFlow::SILENT) | 143 if (delegate_ && embedded_window_created_ && mode_ == WebAuthFlow::SILENT) |
| 144 delegate_->OnAuthFlowFailure(WebAuthFlow::INTERACTION_REQUIRED); | 144 delegate_->OnAuthFlowFailure(WebAuthFlow::INTERACTION_REQUIRED); |
| 145 } | 145 } |
| 146 | 146 |
| 147 void WebAuthFlow::Observe(int type, | 147 void WebAuthFlow::Observe(int type, |
| 148 const content::NotificationSource& source, | 148 const content::NotificationSource& source, |
| 149 const content::NotificationDetails& details) { | 149 const content::NotificationDetails& details) { |
| 150 DCHECK(shell_window_); | 150 DCHECK(app_window_); |
| 151 | 151 |
| 152 if (!delegate_) | 152 if (!delegate_) |
| 153 return; | 153 return; |
| 154 | 154 |
| 155 if (!embedded_window_created_) { | 155 if (!embedded_window_created_) { |
| 156 DCHECK(type == content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED); | 156 DCHECK(type == content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED); |
| 157 | 157 |
| 158 RenderViewHost* render_view( | 158 RenderViewHost* render_view( |
| 159 content::Details<RenderViewHost>(details).ptr()); | 159 content::Details<RenderViewHost>(details).ptr()); |
| 160 WebContents* web_contents = WebContents::FromRenderViewHost(render_view); | 160 WebContents* web_contents = WebContents::FromRenderViewHost(render_view); |
| 161 | 161 |
| 162 if (web_contents && | 162 if (web_contents && |
| 163 (web_contents->GetEmbedderWebContents() == | 163 (web_contents->GetEmbedderWebContents() == |
| 164 WebContentsObserver::web_contents())) { | 164 WebContentsObserver::web_contents())) { |
| 165 // Switch from watching the shell window to the guest inside it. | 165 // Switch from watching the app window to the guest inside it. |
| 166 embedded_window_created_ = true; | 166 embedded_window_created_ = true; |
| 167 WebContentsObserver::Observe(web_contents); | 167 WebContentsObserver::Observe(web_contents); |
| 168 | 168 |
| 169 registrar_.RemoveAll(); | 169 registrar_.RemoveAll(); |
| 170 registrar_.Add(this, | 170 registrar_.Add(this, |
| 171 content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT, | 171 content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT, |
| 172 content::Source<WebContents>(web_contents)); | 172 content::Source<WebContents>(web_contents)); |
| 173 registrar_.Add(this, | 173 registrar_.Add(this, |
| 174 content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, | 174 content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, |
| 175 content::Source<WebContents>(web_contents)); | 175 content::Source<WebContents>(web_contents)); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 } | 237 } |
| 238 | 238 |
| 239 void WebAuthFlow::DidNavigateMainFrame( | 239 void WebAuthFlow::DidNavigateMainFrame( |
| 240 const content::LoadCommittedDetails& details, | 240 const content::LoadCommittedDetails& details, |
| 241 const content::FrameNavigateParams& params) { | 241 const content::FrameNavigateParams& params) { |
| 242 if (delegate_ && details.http_status_code >= 400) | 242 if (delegate_ && details.http_status_code >= 400) |
| 243 delegate_->OnAuthFlowFailure(LOAD_FAILED); | 243 delegate_->OnAuthFlowFailure(LOAD_FAILED); |
| 244 } | 244 } |
| 245 | 245 |
| 246 } // namespace extensions | 246 } // namespace extensions |
| OLD | NEW |