blob: b0e9a6e945108f239b36a468b5b93516b0f0f590 [file] [log] [blame]
// Copyright 2014 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.
#include "components/dom_distiller/ios/distiller_page_ios.h"
#import <UIKit/UIKit.h>
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/strings/sys_string_conversions.h"
#include "base/values.h"
#include "ios/public/provider/web/web_controller_provider.h"
#include "ios/web/public/browser_state.h"
namespace dom_distiller {
// Helper class for observing the loading of URLs to distill.
class DistillerWebStateObserver : public web::WebStateObserver {
public:
DistillerWebStateObserver(web::WebState* web_state,
DistillerPageIOS* distiller_page);
// WebStateObserver implementation:
void PageLoaded(
web::PageLoadCompletionStatus load_completion_status) override;
private:
DistillerPageIOS* distiller_page_; // weak, owns this object.
};
DistillerWebStateObserver::DistillerWebStateObserver(
web::WebState* web_state,
DistillerPageIOS* distiller_page)
: web::WebStateObserver(web_state), distiller_page_(distiller_page) {
DCHECK(web_state);
DCHECK(distiller_page_);
}
void DistillerWebStateObserver::PageLoaded(
web::PageLoadCompletionStatus load_completion_status) {
distiller_page_->OnLoadURLDone(load_completion_status);
}
#pragma mark -
DistillerPageIOS::DistillerPageIOS(web::BrowserState* browser_state)
: browser_state_(browser_state), weak_ptr_factory_(this) {
}
DistillerPageIOS::~DistillerPageIOS() {
}
bool DistillerPageIOS::StringifyOutput() {
// UIWebView requires JavaScript to return a single string value.
return true;
}
void DistillerPageIOS::DistillPageImpl(const GURL& url,
const std::string& script) {
if (!url.is_valid() || !script.length())
return;
url_ = url;
script_ = script;
// Lazily create provider.
if (!provider_) {
if (ios::GetWebControllerProviderFactory()) {
provider_ =
ios::GetWebControllerProviderFactory()->CreateWebControllerProvider(
browser_state_);
web_state_observer_.reset(
new DistillerWebStateObserver(provider_->GetWebState(), this));
}
}
// Load page using provider.
if (provider_)
provider_->LoadURL(url_);
else
OnLoadURLDone(web::PageLoadCompletionStatus::FAILURE);
}
void DistillerPageIOS::OnLoadURLDone(
web::PageLoadCompletionStatus load_completion_status) {
// Don't attempt to distill if the page load failed or if there is no
// provider.
if (load_completion_status == web::PageLoadCompletionStatus::FAILURE ||
!provider_) {
HandleJavaScriptResultString(@"");
return;
}
// Inject the script.
base::WeakPtr<DistillerPageIOS> weak_this = weak_ptr_factory_.GetWeakPtr();
provider_->InjectScript(script_, ^(NSString* string, NSError* error) {
DistillerPageIOS* distiller_page = weak_this.get();
if (distiller_page)
distiller_page->HandleJavaScriptResultString(string);
});
}
void DistillerPageIOS::HandleJavaScriptResultString(NSString* result) {
scoped_ptr<base::Value> resultValue = base::Value::CreateNullValue();
if (result.length) {
scoped_ptr<base::Value> dictionaryValue =
base::JSONReader::Read(base::SysNSStringToUTF8(result));
if (dictionaryValue &&
dictionaryValue->IsType(base::Value::TYPE_DICTIONARY)) {
resultValue = dictionaryValue.Pass();
}
}
OnDistillationDone(url_, resultValue.get());
}
} // namespace dom_distiller