Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/components/custom-widget/customWidgetContract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,10 @@ export interface CustomWidgetContract extends Contract {
* Local styles.
*/
styles: LocalStyles;

/**
* allow iframe to load content from the same origin.
* @default false
* */
allowSameOrigin: boolean;
}
5 changes: 5 additions & 0 deletions src/components/custom-widget/customWidgetModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ export class CustomWidgetModel {
*/
public instanceId: string;

/**
* Allow iframe to load content from the same origin.
*/
public allowSameOrigin: boolean;

constructor() {
this.styles = {};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export class CustomWidgetModelBinder implements IModelBinder<CustomWidgetModel>
model.customInputValue = contract.customInputValue ?? "{}";
model.instanceId = contract.instanceKey;
model.styles = contract.styles || {};
model.allowSameOrigin = contract.allowSameOrigin || false;
return model;
}

Expand All @@ -27,6 +28,7 @@ export class CustomWidgetModelBinder implements IModelBinder<CustomWidgetModel>
customInputValue: model.customInputValue,
instanceKey: model.instanceId,
styles: model.styles,
allowSameOrigin: model.allowSameOrigin,
} as CustomWidgetContract;
}
}
2 changes: 2 additions & 0 deletions src/components/custom-widget/customWidgetModelBinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export class CustomWidgetModelBinder implements IModelBinder<CustomWidgetModel>
model.customInputValue = contract.customInputValue ?? "{}";
model.instanceId = contract.instanceKey;
model.styles = contract.styles || {};
model.allowSameOrigin = contract.allowSameOrigin || false;
return model;
}

Expand All @@ -27,6 +28,7 @@ export class CustomWidgetModelBinder implements IModelBinder<CustomWidgetModel>
customInputValue: model.customInputValue,
instanceKey: model.instanceId,
styles: model.styles,
allowSameOrigin: model.allowSameOrigin,
} as CustomWidgetContract;
}
}
8 changes: 7 additions & 1 deletion src/components/custom-widget/ko/customWidgetEditorView.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
<size-editor params="{ features: 'width,height', allowUnits: 'px,%', sizeConfig: sizeStyleConfig, onUpdate: onSizeUpdate }">
</size-editor>

<label for="allowSameOrigin" class="form-label">
<input type="checkbox" id="allowSameOrigin" name="allowSameOrigin" data-bind="checked: allowSameOrigin" />
Allow allow-same-origin in iframe sandbox
<button class="btn btn-info" type="button" data-bind="tooltip: 'Select this setting to set custom widget &nbsp;<code>iframe</code> sandbox attribute allow-same-origin'"></button>
</label>

<h4>Custom properties</h4>
<p>Custom properties let you adjust values in the custom widget’s code from the administrative user interface of the developer portal, without changing the code or redeploying the custom widget.</p>
</div>
Expand All @@ -19,4 +25,4 @@ <h4>Custom properties</h4>
frameborder="0"
></iframe>
</div>
</fieldset>
</fieldset>
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export class CustomWidgetEditorViewModel implements WidgetEditor<CustomWidgetMod
public readonly instanceId: ko.Observable<string>;
public readonly iframeAllows: string = iframeAllows;
public readonly iframeSandboxAllows: string = CustomWidgetEditorViewModel.buildSandboxParams();
public readonly allowSameOrigin: ko.Observable<boolean>;

constructor(
private readonly viewManager: ViewManager,
Expand All @@ -35,6 +36,7 @@ export class CustomWidgetEditorViewModel implements WidgetEditor<CustomWidgetMod
this.sizeStyleConfig = ko.observable();
this.customInputValue = ko.observable();
this.src = ko.observable("");
this.allowSameOrigin = ko.observable();
this.instanceId = ko.observable();
}

Expand All @@ -49,6 +51,7 @@ export class CustomWidgetEditorViewModel implements WidgetEditor<CustomWidgetMod
this.customInputValue(this.model.customInputValue);
this.instanceId(this.model.instanceId);
this.updateResponsiveObservables();
this.allowSameOrigin(this.model.allowSameOrigin || false);

window.addEventListener("message", event => {
if (typeof event.data === "object" && "customInputValueChangedMSAPIM" in event.data) {
Expand All @@ -60,7 +63,7 @@ export class CustomWidgetEditorViewModel implements WidgetEditor<CustomWidgetMod
this.customInputValue(JSON.stringify({values}));
}
});

this.allowSameOrigin.subscribe(this.applyChanges);
this.customInputValue.subscribe(this.applyCustomInputValueChanges);
this.eventManager.addEventListener(Events.ViewportChange, this.updateResponsiveObservables);

Expand Down Expand Up @@ -102,6 +105,7 @@ export class CustomWidgetEditorViewModel implements WidgetEditor<CustomWidgetMod

private applyChanges(): void {
this.model.customInputValue = this.customInputValue();
this.model.allowSameOrigin = this.allowSameOrigin();
this.onChange(this.model);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export class CustomWidgetViewModelBinder implements ViewModelBinder<CustomWidget
config.src = widgetSource.src;
config.instanceId = model.instanceId;
config.name = model.name;
config.allowSameOrigin = model.allowSameOrigin;

if (model.styles) {
const styles = await this.styleCompiler.getStyleModelAsync(model.styles);
Expand Down
16 changes: 10 additions & 6 deletions src/components/custom-widget/ko/runtime/customWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@ export class CustomWidget {
this.src = ko.observable();
this.name = ko.observable();
this.instanceId = ko.observable();

const iframe = document.getElementsByTagName("iframe")[0];
this.iframeSandboxAllows = `${iframeSandboxAllows} ${iframeSandboxAllowsBrowserSpecific}`
.split(" ")
.filter(token=> iframe?.sandbox.supports(token))
.join(" ");
}

@Param()
Expand All @@ -41,10 +35,20 @@ export class CustomWidget {
@Param()
public readonly environment: Environment;

@Param()
public readonly allowSameOrigin: boolean;

@OnMounted()
public async initialize(): Promise<void> {
if (this.environment === "development") this.windowRef = window.parent.window;

const iframe = document.getElementsByTagName("iframe")[0];
const sandboxAttrs = `${iframeSandboxAllows} ${iframeSandboxAllowsBrowserSpecific}`.split(" ");
if(this.allowSameOrigin) {
sandboxAttrs.push("allow-same-origin");
}
this.iframeSandboxAllows = sandboxAttrs.filter(token=> iframe?.sandbox.supports(token)).join(" ");

this.propagateHashchange();
this.windowRef.addEventListener("hashchange", this.propagateHashchange);
}
Expand Down
Loading